Version 0.1.3.0

svn merge -r 13512:13592 https://dart.googlecode.com/svn/branches/bleeding_edge trunk

git-svn-id: http://dart.googlecode.com/svn/trunk@13596 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java b/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
index d198622..0c74025 100644
--- a/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
+++ b/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
@@ -1482,7 +1482,8 @@
         }
         if (target instanceof DartBinaryExpression) {
           DartBinaryExpression binary = (DartBinaryExpression) target;
-          if (binary.getOperator() == Token.DIV) {
+          if (binary.getOperator() == Token.DIV && intType.equals(binary.getArg1().getType())
+              && intType.equals(binary.getArg2().getType())) {
             typeError(node, TypeErrorCode.USE_INTEGER_DIVISION);
           }
         }
diff --git a/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerCompilerTest.java b/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerCompilerTest.java
index cb8a83a..961a981 100644
--- a/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerCompilerTest.java
+++ b/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerCompilerTest.java
@@ -5307,11 +5307,28 @@
   
   /**
    * Developers unfamiliar with Dart frequently write (x/y).toInt() instead of x ~/ y. The editor
-   * should recognize that pattern
+   * should recognize that pattern.
    * <p>
    * http://code.google.com/p/dart/issues/detail?id=5652
    */
-  public void test_useEffectiveIntegerDivision() throws Exception {
+  public void test_useEffectiveIntegerDivision_int() throws Exception {
+    AnalyzeLibraryResult result = analyzeLibrary(
+        "// filler filler filler filler filler filler filler filler filler filler",
+        "main() {",
+        "  int x = 7;",
+        "  int y = 2;",
+        "  print( (x / y).toInt() );",
+        "}",
+        "");
+    assertErrors(result.getErrors(), errEx(TypeErrorCode.USE_INTEGER_DIVISION, 5, 10, 15));
+  }
+  
+  /**
+   * We need to report warning only when arguments are integers.
+   * <p>
+   * http://code.google.com/p/dart/issues/detail?id=5652
+   */
+  public void test_useEffectiveIntegerDivision_num() throws Exception {
     AnalyzeLibraryResult result = analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
         "main() {",
@@ -5320,6 +5337,6 @@
         "  print( (x / y).toInt() );",
         "}",
         "");
-    assertErrors(result.getErrors(), errEx(TypeErrorCode.USE_INTEGER_DIVISION, 5, 10, 15));
+    assertErrors(result.getErrors());
   }
 }
diff --git a/lib/compiler/implementation/apiimpl.dart b/lib/compiler/implementation/apiimpl.dart
index 9a669dc..40030da 100644
--- a/lib/compiler/implementation/apiimpl.dart
+++ b/lib/compiler/implementation/apiimpl.dart
@@ -31,7 +31,9 @@
             enableUserAssertions: hasOption(options, '--enable-checked-mode'),
             enableMinification: hasOption(options, '--minify'),
             emitJavaScript: !hasOption(options, '--output-type=dart'),
-            strips: getStrips(options));
+            strips: getStrips(options),
+            enableConcreteTypeInference:
+              hasOption(options, '--enable-concrete-type-inference'));
 
   static List<String> getStrips(List<String> options) {
     for (String option in options) {
diff --git a/lib/compiler/implementation/closure.dart b/lib/compiler/implementation/closure.dart
index ec82f30..6e11253 100644
--- a/lib/compiler/implementation/closure.dart
+++ b/lib/compiler/implementation/closure.dart
@@ -18,7 +18,8 @@
 
   String get name => "Closure Simplifier";
 
-  ClosureClassMap computeClosureToClassMapping(FunctionExpression node,
+  ClosureClassMap computeClosureToClassMapping(Element element,
+                                               Expression node,
                                                TreeElements elements) {
     return measure(() {
       ClosureClassMap cached = closureMappingCache[node];
@@ -26,9 +27,16 @@
 
       ClosureTranslator translator =
           new ClosureTranslator(compiler, elements, closureMappingCache);
+
       // The translator will store the computed closure-mappings inside the
-      // cache. One for given method and one for each nested closure.
-      translator.translate(node);
+      // cache. One for given node and one for each nested closure.
+      if (node is FunctionExpression) {
+        translator.translateFunction(element, node);
+      } else {
+        // Must be the lazy initializer of a static.
+        assert(node is SendSet);
+        translator.translateLazyInitializer(element, node);
+      }
       assert(closureMappingCache[node] != null);
       return closureMappingCache[node];
     });
@@ -71,8 +79,8 @@
               STATE_DONE) {
     compiler.closureClass.ensureResolved(compiler);
     supertype = compiler.closureClass.computeType(compiler);
-    interfaces = const EmptyLink<DartType>();
-    allSupertypes = new Link<DartType>(supertype);
+    interfaces = const Link<DartType>();
+    allSupertypes = const Link<DartType>().prepend(supertype);
   }
 
   bool isClosure() => true;
@@ -113,7 +121,7 @@
 
 class ClosureClassMap {
   // The closure's element before any translation. Will be null for methods.
-  final FunctionElement closureElement;
+  final Element closureElement;
   // The closureClassElement will be null for methods that are not local
   // closures.
   final ClassElement closureClassElement;
@@ -170,7 +178,7 @@
   // will update this mapping.
   Map<Element, Element> capturedVariableMapping;
   // List of encountered closures.
-  List<FunctionExpression> closures;
+  List<Expression> closures;
 
   // The variables that have been declared in the current scope.
   List<Element> scopeVariables;
@@ -179,8 +187,8 @@
   // non-mutated variables.
   Set<Element> mutatedVariables;
 
-  FunctionElement outermostFunctionElement;
-  FunctionElement currentFunctionElement;
+  Element outermostElement;
+  Element currentElement;
 
   // The closureData of the currentFunctionElement.
   ClosureClassMap closureData;
@@ -189,11 +197,14 @@
 
   ClosureTranslator(this.compiler, this.elements, this.closureMappingCache)
       : capturedVariableMapping = new Map<Element, Element>(),
-        closures = <FunctionExpression>[],
+        closures = <Expression>[],
         mutatedVariables = new Set<Element>();
 
-  void translate(Node node) {
-    visit(node);
+  void translateFunction(Element element, FunctionExpression node) {
+    // For constructors the [element] and the [:elements[node]:] may differ.
+    // The [:elements[node]:] always points to the generative-constructor
+    // element, whereas the [element] might be the constructor-body element.
+    visit(node);  // [visitFunctionExpression] will call [visitInvokable].
     // When variables need to be boxed their [capturedVariableMapping] is
     // updated, but we delay updating the similar freeVariableMapping in the
     // closure datas that capture these variables.
@@ -201,12 +212,19 @@
     updateClosures();
   }
 
+  void translateLazyInitializer(Element element, SendSet node) {
+    assert(node.assignmentOperator.source == const SourceString("="));
+    Expression initialValue = node.argumentsNode.nodes.head;
+    visitInvokable(element, node, () { visit(initialValue); });
+    updateClosures();
+  }
+
   // This function runs through all of the existing closures and updates their
   // free variables to the boxed value. It also adds the field-elements to the
   // class representing the closure. At the same time it fills the
   // [capturedFieldMapping].
   void updateClosures() {
-    for (FunctionExpression closure in closures) {
+    for (Expression closure in closures) {
       // The captured variables that need to be stored in a field of the closure
       // class.
       Set<Element> fieldCaptures = new Set<Element>();
@@ -260,8 +278,8 @@
     // parameters, and type parameters are declared in the class, not
     // the factory.
     if (insideClosure &&
-        element.enclosingElement != currentFunctionElement &&
-        element != currentFunctionElement) {
+        element.enclosingElement != currentElement &&
+        element != currentElement) {
       assert(closureData.freeVariableMapping[element] == null ||
              closureData.freeVariableMapping[element] == element);
       closureData.freeVariableMapping[element] = element;
@@ -373,12 +391,12 @@
         }
       }
     }
-    if (outermostFunctionElement.isMember() &&
-        compiler.world.needsRti(outermostFunctionElement.getEnclosingClass())) {
-      if (outermostFunctionElement.isInstanceMember()
-          || outermostFunctionElement.isGenerativeConstructor()) {
+    if (outermostElement.isMember() &&
+        compiler.world.needsRti(outermostElement.getEnclosingClass())) {
+      if (outermostElement.isInstanceMember()
+          || outermostElement.isGenerativeConstructor()) {
         if (hasTypeVariable(type)) useLocal(closureData.thisElement);
-      } else if (outermostFunctionElement.isFactoryConstructor()) {
+      } else if (outermostElement.isFactoryConstructor()) {
         analyzeTypeVariables(type);
       }
     }
@@ -402,7 +420,7 @@
           // TODO(floitsch): construct better box names.
           SourceString boxName =
               new SourceString("box_${closureFieldCounter++}");
-          box = new BoxElement(boxName, currentFunctionElement);
+          box = new BoxElement(boxName, currentElement);
         }
         // TODO(floitsch): construct better boxed names.
         String elementName = element.name.slowToString();
@@ -501,7 +519,7 @@
                                  element,
                                  globalizedElement);
     globalizedElement.backendMembers =
-        const EmptyLink<Element>().prepend(callElement);
+        const Link<Element>().prepend(callElement);
     // The nested function's 'this' is the same as the one for the outer
     // function. It could be [null] if we are inside a static method.
     Element thisElement = closureData.thisElement;
@@ -509,25 +527,18 @@
                                callElement, thisElement);
   }
 
-  visitFunctionExpression(FunctionExpression node) {
-    Element element = elements[node];
-    if (element.isParameter()) {
-      // TODO(ahe): This is a hack. This method should *not* call
-      // visitChildren.
-      return node.name.accept(this);
-    }
-
+  void visitInvokable(Element element, Expression node, void visitChildren()) {
     bool oldInsideClosure = insideClosure;
-    FunctionElement oldFunctionElement = currentFunctionElement;
+    Element oldFunctionElement = currentElement;
     ClosureClassMap oldClosureData = closureData;
 
-    insideClosure = outermostFunctionElement != null;
-    currentFunctionElement = element;
+    insideClosure = outermostElement != null;
+    currentElement = element;
     if (insideClosure) {
       closures.add(node);
       closureData = globalizeClosure(node, element);
     } else {
-      outermostFunctionElement = element;
+      outermostElement = element;
       Element thisElement = null;
       if (element.isInstanceMember() || element.isGenerativeConstructor()) {
         thisElement = new ThisElement(element);
@@ -549,23 +560,17 @@
         declareLocal(element);
       }
 
-      if (currentFunctionElement.isFactoryConstructor()
-          && compiler.world.needsRti(currentFunctionElement.enclosingElement)) {
+      if (currentElement.isFactoryConstructor()
+          && compiler.world.needsRti(currentElement.enclosingElement)) {
         // Declare the type parameters in the scope. Generative
         // constructors just use 'this'.
-        ClassElement cls = currentFunctionElement.enclosingElement;
+        ClassElement cls = currentElement.enclosingElement;
         cls.typeVariables.forEach((TypeVariableType typeVariable) {
           declareLocal(typeVariable.element);
         });
       }
 
-      // TODO(ahe): This is problematic. The backend should not repeat
-      // the work of the resolver. It is the resolver's job to create
-      // parameters, etc. Other phases should only visit statements.
-      // TODO(floitsch): we avoid visiting the initializers on purpose so that
-      // we get an error-message later in the builder.
-      if (node.parameters !== null) node.parameters.accept(this);
-      if (node.body !== null) node.body.accept(this);
+      visitChildren();
     });
 
 
@@ -575,7 +580,7 @@
     // Restore old values.
     insideClosure = oldInsideClosure;
     closureData = oldClosureData;
-    currentFunctionElement = oldFunctionElement;
+    currentElement = oldFunctionElement;
 
     // Mark all free variables as captured and use them in the outer function.
     List<Element> freeVariables =
@@ -591,6 +596,26 @@
     }
   }
 
+  visitFunctionExpression(FunctionExpression node) {
+    Element element = elements[node];
+
+    if (element.isParameter()) {
+      // TODO(ahe): This is a hack. This method should *not* call
+      // visitChildren.
+      return node.name.accept(this);
+    }
+
+    visitInvokable(element, node, () {
+      // TODO(ahe): This is problematic. The backend should not repeat
+      // the work of the resolver. It is the resolver's job to create
+      // parameters, etc. Other phases should only visit statements.
+      // TODO(floitsch): we avoid visiting the initializers on purpose so that
+      // we get an error-message later in the builder.
+      if (node.parameters !== null) node.parameters.accept(this);
+      if (node.body !== null) node.body.accept(this);
+    });
+  }
+
   visitFunctionDeclaration(FunctionDeclaration node) {
     node.visitChildren(this);
     declareLocal(elements[node]);
diff --git a/lib/compiler/implementation/compile_time_constants.dart b/lib/compiler/implementation/compile_time_constants.dart
index 8e67ebc..ce96502 100644
--- a/lib/compiler/implementation/compile_time_constants.dart
+++ b/lib/compiler/implementation/compile_time_constants.dart
@@ -779,7 +779,7 @@
                                               0);
         evaluateSuperOrRedirectSend(functionNode,
                                     selector,
-                                    const EmptyLink<Node>(),
+                                    const Link<Node>(),
                                     targetConstructor);
       }
     }
diff --git a/lib/compiler/implementation/compiler.dart b/lib/compiler/implementation/compiler.dart
index 821fc12..e461074 100644
--- a/lib/compiler/implementation/compiler.dart
+++ b/lib/compiler/implementation/compiler.dart
@@ -100,6 +100,7 @@
   final bool enableMinification;
   final bool enableTypeAssertions;
   final bool enableUserAssertions;
+  final bool enableConcreteTypeInference;
 
   bool disableInlining = false;
 
@@ -196,6 +197,7 @@
   Compiler([this.tracer = const Tracer(),
             this.enableTypeAssertions = false,
             this.enableUserAssertions = false,
+            this.enableConcreteTypeInference = false,
             this.enableMinification = false,
             bool emitJavaScript = true,
             bool generateSourceMap = true,
@@ -213,7 +215,7 @@
     resolver = new ResolverTask(this);
     closureToClassMapper = new closureMapping.ClosureTask(this);
     checker = new TypeCheckerTask(this);
-    typesTask = new ti.TypesTask(this);
+    typesTask = new ti.TypesTask(this, enableConcreteTypeInference);
     backend = emitJavaScript ?
         new js_backend.JavaScriptBackend(this, generateSourceMap) :
         new dart_backend.DartBackend(this, strips);
@@ -477,7 +479,7 @@
     if (compilationFailed) return;
 
     log('Inferring types...');
-    typesTask.onResolutionComplete();
+    typesTask.onResolutionComplete(main);
 
     // TODO(ahe): Remove this line. Eventually, enqueuer.resolution
     // should know this.
diff --git a/lib/compiler/implementation/dart2js.dart b/lib/compiler/implementation/dart2js.dart
index ee41641..91e7b92 100644
--- a/lib/compiler/implementation/dart2js.dart
+++ b/lib/compiler/implementation/dart2js.dart
@@ -147,10 +147,13 @@
     new OptionHandler('--minify', passThrough),
     new OptionHandler('--force-strip=.*', setStrip),
     // TODO(ahe): Remove the --no-colors option.
-    new OptionHandler('--disable-diagnostic-colors', (_) => enableColors = false),
+    new OptionHandler('--disable-diagnostic-colors',
+                      (_) => enableColors = false),
     new OptionHandler('--enable-diagnostic-colors', (_) => enableColors = true),
     new OptionHandler('--enable[_-]checked[_-]mode|--checked',
                       (_) => passThrough('--enable-checked-mode')),
+    new OptionHandler('--enable-concrete-type-inference',
+                      (_) => passThrough('--enable-concrete-type-inference')),
     new OptionHandler(r'--help|/\?|/h', (_) => wantHelp = true),
     new OptionHandler(r'--package-root=.+|-p.+', setPackageRoot),
     // The following two options must come last.
@@ -386,7 +389,10 @@
 
   --allow-mock-compilation
     Do not generate a call to main if either of the following
-    libraries are used: dart:dom, dart:html dart:io.''');
+    libraries are used: dart:dom, dart:html dart:io.
+
+  --enable-concrete-type-inference
+    Enable experimental concrete type inference.''');
 }
 
 void helpAndExit(bool verbose) {
diff --git a/lib/compiler/implementation/dart_backend/backend.dart b/lib/compiler/implementation/dart_backend/backend.dart
index dd9596b..a6d59d9 100644
--- a/lib/compiler/implementation/dart_backend/backend.dart
+++ b/lib/compiler/implementation/dart_backend/backend.dart
@@ -351,14 +351,14 @@
       SynthesizedConstructorElement constructor =
           new SynthesizedConstructorElement(classElement);
       constructor.type = new FunctionType(
-          compiler.types.voidType, const EmptyLink<DartType>(),
+          compiler.types.voidType, const Link<DartType>(),
           constructor);
       constructor.cachedNode = new FunctionExpression(
           new Send(receiver: classElement.parseNode(compiler).name,
                    selector: synthesizedIdentifier),
           new NodeList(beginToken: new StringToken(OPEN_PAREN_INFO, '(', -1),
                        endToken: new StringToken(CLOSE_PAREN_INFO, ')', -1),
-                       nodes: const EmptyLink<Node>()),
+                       nodes: const Link<Node>()),
           new EmptyStatement(new StringToken(SEMICOLON_INFO, ';', -1)),
           null, Modifiers.EMPTY, null, null);
 
diff --git a/lib/compiler/implementation/dart_backend/utils.dart b/lib/compiler/implementation/dart_backend/utils.dart
index d19b6d8..53f75ea 100644
--- a/lib/compiler/implementation/dart_backend/utils.dart
+++ b/lib/compiler/implementation/dart_backend/utils.dart
@@ -44,7 +44,7 @@
       node.onKeyword, node.catchKeyword);
 
   visitClassNode(ClassNode node) => new ClassNode(
-      visit(node.name), visit(node.typeParameters),
+      visit(node.modifiers), visit(node.name), visit(node.typeParameters),
       visit(node.superclass), visit(node.interfaces), visit(node.defaultClause),
       node.beginToken, node.extendsKeyword, visit(node.body), node.endToken);
 
diff --git a/lib/compiler/implementation/elements/elements.dart b/lib/compiler/implementation/elements/elements.dart
index 9877fe7..5ae0939 100644
--- a/lib/compiler/implementation/elements/elements.dart
+++ b/lib/compiler/implementation/elements/elements.dart
@@ -114,7 +114,7 @@
   final SourceString name;
   final ElementKind kind;
   final Element enclosingElement;
-  Link<MetadataAnnotation> metadata = const EmptyLink<MetadataAnnotation>();
+  Link<MetadataAnnotation> metadata = const Link<MetadataAnnotation>();
 
   Element(this.name, this.kind, this.enclosingElement) {
     assert(isErroneous() || getImplementationLibrary() !== null);
@@ -247,11 +247,7 @@
 
   CompilationUnitElement getCompilationUnit() {
     Element element = this;
-    while (element !== null && !element.isCompilationUnit()) {
-      if (element.isLibrary()) {
-        LibraryElement library = element;
-        return library.entryCompilationUnit;
-      }
+    while (!element.isCompilationUnit()) {
       element = element.enclosingElement;
     }
     return element;
@@ -398,7 +394,7 @@
 }
 
 class ContainerElement extends Element {
-  Link<Element> localMembers = const EmptyLink<Element>();
+  Link<Element> localMembers = const Link<Element>();
 
   ContainerElement(name, kind, enclosingElement)
     : super(name, kind, enclosingElement);
@@ -561,8 +557,8 @@
   final Uri uri;
   CompilationUnitElement entryCompilationUnit;
   Link<CompilationUnitElement> compilationUnits =
-      const EmptyLink<CompilationUnitElement>();
-  Link<LibraryTag> tags = const EmptyLink<LibraryTag>();
+      const Link<CompilationUnitElement>();
+  Link<LibraryTag> tags = const Link<LibraryTag>();
   LibraryName libraryTag;
   bool canUseNative = false;
 
@@ -614,6 +610,8 @@
   LibraryElement get declaration => super.declaration;
   LibraryElement get implementation => super.implementation;
 
+  CompilationUnitElement getCompilationUnit() => entryCompilationUnit;
+
   void addCompilationUnit(CompilationUnitElement element) {
     compilationUnits = compilationUnits.prepend(element);
   }
@@ -1278,7 +1276,7 @@
    */
   static Link<DartType> createTypeVariables(TypeDeclarationElement element,
                                         NodeList parameters) {
-    if (parameters === null) return const EmptyLink<DartType>();
+    if (parameters === null) return const Link<DartType>();
 
     // Create types and elements for type variable.
     var arguments = new LinkBuilder<DartType>();
@@ -1308,7 +1306,7 @@
 
   // backendMembers are members that have been added by the backend to simplify
   // compilation. They don't have any user-side counter-part.
-  Link<Element> backendMembers = const EmptyLink<Element>();
+  Link<Element> backendMembers = const Link<Element>();
 
   Link<DartType> allSupertypes;
 
@@ -1507,7 +1505,7 @@
 
   Link<Element> get constructors {
     // TODO(ajohnsen): See if we can avoid this method at some point.
-    Link<Element> result = const EmptyLink<Element>();
+    Link<Element> result = const Link<Element>();
     // TODO(johnniwinther): Should we include injected constructors?
     forEachMember((_, Element member) {
       if (member.isConstructor()) result = result.prepend(member);
@@ -1867,7 +1865,7 @@
 class TargetElement extends Element {
   final Node statement;
   final int nestingLevel;
-  Link<LabelElement> labels = const EmptyLink<LabelElement>();
+  Link<LabelElement> labels = const Link<LabelElement>();
   bool isBreakTarget = false;
   bool isContinueTarget = false;
 
diff --git a/lib/compiler/implementation/enqueue.dart b/lib/compiler/implementation/enqueue.dart
index d41f3c4..f2e9101 100644
--- a/lib/compiler/implementation/enqueue.dart
+++ b/lib/compiler/implementation/enqueue.dart
@@ -167,7 +167,7 @@
 
     String memberName = member.name.slowToString();
     Link<Element> members = instanceMembersByName.putIfAbsent(
-        memberName, () => const EmptyLink<Element>());
+        memberName, () => const Link<Element>());
     instanceMembersByName[memberName] = members.prepend(member);
 
     if (member.kind == ElementKind.FUNCTION) {
diff --git a/lib/compiler/implementation/js/printer.dart b/lib/compiler/implementation/js/printer.dart
index 9305995..27c9aa5 100644
--- a/lib/compiler/implementation/js/printer.dart
+++ b/lib/compiler/implementation/js/printer.dart
@@ -17,9 +17,9 @@
         this.compiler = compiler,
         outBuffer = new leg.CodeBuffer(),
         danglingElseVisitor = new DanglingElseVisitor(compiler),
-        namer = DetermineRenamer(compiler.enableMinification);
+        namer = determineRenamer(compiler.enableMinification);
   
-  static Namer DetermineRenamer(bool shouldCompressOutput) {
+  static Namer determineRenamer(bool shouldCompressOutput) {
     return shouldCompressOutput ? new MinifyRenamer() : new IdentityNamer();
   }
 
@@ -852,11 +852,11 @@
 
 
 class MinifyRenamer implements Namer {
-  final List<Map<String, String>> maps;
-  final List<int> nameNumberStack;
-  int nameNumber;
+  final List<Map<String, String>> maps = [];
+  final List<int> nameNumberStack = [];
+  int nameNumber = 0;
 
-  MinifyRenamer() : maps = [], nameNumberStack = [], nameNumber = 0;
+  MinifyRenamer();
 
   void enterScope() {
     maps.add(new Map<String, String>());
@@ -877,11 +877,46 @@
     return oldName;
   }
 
+  static int nthLetter(int n) {
+    return (n < 26) ? charCodes.$a + n : charCodes.$A + n - 26;
+  }
+
   String declareName(String oldName) {
-    if (maps.length == 0) return oldName;
-    var newName = "z${nameNumber++}";
+    const LETTERS = 52;
+    const DIGITS = 10;
+    if (maps.isEmpty()) return oldName;
+    String newName;
+    int n = nameNumber;
+    if (n < LETTERS) {
+      // Start naming variables a, b, c, ..., z, A, B, C, ..., Z.
+      newName = new String.fromCharCodes([nthLetter(n)]);
+    } else {
+      // Then name variables a0, a1, a2, ..., a9, b0, b1, ..., Z9, aa0, aa1, ...
+      // For all functions with fewer than 500 locals this is just as compact
+      // as using aa, ab, etc. but avoids clashes with keywords.
+      n -= LETTERS;
+      int digit = n % DIGITS;
+      n ~/= DIGITS;
+      int alphaChars = 1;
+      int nameSpaceSize = LETTERS;
+      // Find out whether we should use the 1-character namespace (size 52), the
+      // 2-character namespace (size 52*52), etc.
+      while (n >= nameSpaceSize) {
+        n -= nameSpaceSize;
+        alphaChars++;
+        nameSpaceSize *= LETTERS;
+      }
+      var codes = <int>[];
+      for (var i = 0; i < alphaChars; i++) {
+        nameSpaceSize ~/= LETTERS;
+        codes.add(nthLetter((n ~/ nameSpaceSize) % LETTERS));
+      }
+      codes.add(charCodes.$0 + digit);
+      newName = new String.fromCharCodes(codes);
+    }
+    assert(const RegExp(r'[a-zA-Z][a-zA-Z0-9]*').hasMatch(newName));
+    nameNumber++;
     maps.last()[oldName] = newName;
     return newName;
   }
-
 }
diff --git a/lib/compiler/implementation/lib/isolate_patch.dart b/lib/compiler/implementation/lib/isolate_patch.dart
index 76fe2d0..e6fc239 100644
--- a/lib/compiler/implementation/lib/isolate_patch.dart
+++ b/lib/compiler/implementation/lib/isolate_patch.dart
@@ -85,13 +85,15 @@
 // TODO(eub, sigmund): move the "manager" to be entirely in JS.
 // Running any Dart code outside the context of an isolate gives it
 // the change to break the isolate abstraction.
-_Manager get _globalState() native "return \$globalState;";
-set _globalState(_Manager val) native "\$globalState = val;";
+_Manager get _globalState() => JS("Object", r"$globalState");
+set _globalState(_Manager val) {
+  JS("void", r"$globalState = #", val);
+}
 
-void _fillStatics(context) native r"""
-  $globals = context.isolateStatics;
-  $static_init();
-""";
+void _fillStatics(context) {
+  JS("void", r"$globals = #.isolateStatics", context);
+  JS("void", r"$static_init()");
+}
 
 ReceivePort _lazyPort;
 patch ReceivePort get port() {
@@ -185,17 +187,18 @@
     }
   }
 
-  void _nativeDetectEnvironment() native r"""
-    this.isWorker = $isWorker;
-    this.supportsWorkers = $supportsWorkers;
-    this.fromCommandLine = typeof(window) == 'undefined';
-  """;
+  void _nativeDetectEnvironment() {
+    JS("void", r"#.isWorker = $isWorker", this);
+    JS("void", r"#.supportsWorkers = $supportsWorkers", this);
+    JS("void", r"#.fromCommandLine = typeof(window) == 'undefined'", this);
+  }
 
-  void _nativeInitWorkerMessageHandler() native r"""
-    $globalThis.onmessage = function (e) {
-      _IsolateNatives._processWorkerMessage(this.mainManager, e);
-    }
-  """;
+  void _nativeInitWorkerMessageHandler() {
+    JS("void", r"""
+$globalThis.onmessage = function (e) {
+  _IsolateNatives._processWorkerMessage(this.mainManager, e);
+}""");
+  }
   /*: TODO: check that _processWorkerMessage is not discarded while treeshaking.
   """ {
     _IsolateNatives._processWorkerMessage(null, null);
@@ -229,7 +232,7 @@
   }
 
   // these are filled lazily the first time the isolate starts running.
-  void initGlobals() native r'$initGlobals(this);';
+  void initGlobals() { JS("void", r'$initGlobals(#)', this); }
 
   /**
    * Run [code] in the context of the isolate represented by [this]. Note this
@@ -249,7 +252,7 @@
     return result;
   }
 
-  void _setGlobals() native r'$setGlobals(this);';
+  void _setGlobals() { JS("void", r'$setGlobals(#)', this); }
 
   /** Lookup a port registered for this isolate. */
   ReceivePort lookup(int portId) => ports[portId];
@@ -379,7 +382,7 @@
   void set onmessage(f) {
     throw new Exception("onmessage should not be set on MainManagerStub");
   }
-  void postMessage(msg) native r"$globalThis.postMessage(msg);";
+  void postMessage(msg) { JS("void", r"$globalThis.postMessage(#)", msg); }
   void terminate() {}  // Nothing useful to do here.
 }
 
@@ -390,10 +393,10 @@
  * are actually available.
  */
 class _WorkerStub implements _ManagerStub native "*Worker" {
-  get id() native "return this.id;";
-  void set id(i) native "this.id = i;";
-  void set onmessage(f) native "this.onmessage = f;";
-  void postMessage(msg) native "return this.postMessage(msg);";
+  get id() => JS("Object", "#.id", this);
+  void set id(i) { JS("void", "#.id = #", this, i); }
+  void set onmessage(f) { JS("void", "#.onmessage = #", this, f); }
+  void postMessage(msg) => JS("Object", "#.postMessage(#)", this, msg);
   // terminate() is implemented by Worker.
   abstract void terminate();
 }
@@ -406,17 +409,17 @@
    * The src url for the script tag that loaded this code. Used to create
    * JavaScript workers.
    */
-  static String get _thisScript() native r"return $thisScriptUrl";
+  static String get _thisScript() => JS("String", r"$thisScriptUrl");
 
   /** Starts a new worker with the given URL. */
-  static _WorkerStub _newWorker(url) native "return new Worker(url);";
+  static _WorkerStub _newWorker(url) => JS("Object", r"new Worker(#)", url);
 
   /**
    * Assume that [e] is a browser message event and extract its message data.
    * We don't import the dom explicitly so, when workers are disabled, this
    * library can also run on top of nodejs.
    */
-  static _getEventData(e) native "return e.data";
+  static _getEventData(e) => JS("Object", "#.data", e);
 
   /**
    * Process messages on a worker, either to control the worker instance or to
@@ -477,41 +480,48 @@
     }
   }
 
-  static void _consoleLog(msg) native "\$globalThis.console.log(msg);";
+  static void _consoleLog(msg) {
+    JS("void", r"$globalThis.console.log(#)", msg);
+  }
 
   /**
    * Extract the constructor of runnable, so it can be allocated in another
    * isolate.
    */
-  static Dynamic _getJSConstructor(Isolate runnable) native """
-    return runnable.constructor;
-  """;
+  static Dynamic _getJSConstructor(Isolate runnable) {
+    return JS("Object", "#.constructor", runnable);
+  }
 
   /** Extract the constructor name of a runnable */
   // TODO(sigmund): find a browser-generic way to support this.
-  static Dynamic _getJSConstructorName(Isolate runnable) native """
-    return runnable.constructor.name;
-  """;
+  // TODO(floitsch): is this function still used? If yes, should we use
+  // Primitives.objectTypeName instead?
+  static Dynamic _getJSConstructorName(Isolate runnable) {
+    return JS("Object", "#.constructor.name", runnable);
+  }
 
   /** Find a constructor given its name. */
-  static Dynamic _getJSConstructorFromName(String factoryName) native """
-    return \$globalThis[factoryName];
-  """;
+  static Dynamic _getJSConstructorFromName(String factoryName) {
+    return JS("Object", r"$globalThis[#]", factoryName);
+  }
 
-  static Dynamic _getJSFunctionFromName(String functionName) native """
-    return \$globalThis[functionName];
-  """;
+  static Dynamic _getJSFunctionFromName(String functionName) {
+    return JS("Object", r"$globalThis[#]", functionName);
+  }
 
   /**
    * Get a string name for the function, if possible.  The result for
    * anonymous functions is browser-dependent -- it may be "" or "anonymous"
    * but you should probably not count on this.
    */
-  static String _getJSFunctionName(Function f)
-    native r"return f.$name || (void 0);";
+  static String _getJSFunctionName(Function f) {
+    return JS("Object", r"(#.$name || #)", f, null);
+  }
 
   /** Create a new JavaScript object instance given its constructor. */
-  static Dynamic _allocate(var ctor) native "return new ctor();";
+  static Dynamic _allocate(var ctor) {
+    return JS("Object", "new #()", ctor);
+  }
 
   // TODO(sigmund): clean up above, after we make the new API the default:
 
@@ -989,21 +999,24 @@
   }
 
   /** Remove all information injected in the native objects. */
-  cleanup() {
+  void cleanup() {
     for (int i = 0, length = tagged.length; i < length; i++) {
       _clearAttachedInfo(tagged[i]);
     }
     tagged = null;
   }
 
-  _clearAttachedInfo(var o) native
-      "o['__MessageTraverser__attached_info__'] = (void 0);";
+  void _clearAttachedInfo(var o) {
+    JS("void", "#['__MessageTraverser__attached_info__'] = #", o, null);
+  }
 
-  _setAttachedInfo(var o, var info) native
-      "o['__MessageTraverser__attached_info__'] = info;";
+  void _setAttachedInfo(var o, var info) {
+    JS("void", "#['__MessageTraverser__attached_info__'] = #", o, info);
+  }
 
-  _getAttachedInfo(var o) native
-      "return o['__MessageTraverser__attached_info__'];";
+  _getAttachedInfo(var o) {
+    return JS("Object", "#['__MessageTraverser__attached_info__']", o);
+  }
 }
 
 // only visible for testing purposes
diff --git a/lib/compiler/implementation/library_loader.dart b/lib/compiler/implementation/library_loader.dart
index c101176..a7ca9e0 100644
--- a/lib/compiler/implementation/library_loader.dart
+++ b/lib/compiler/implementation/library_loader.dart
@@ -37,6 +37,87 @@
 }
 
 /**
+ * [CombinatorFilter] is a succinct representation of a list of combinators from
+ * a library dependency tag.
+ */
+class CombinatorFilter {
+  const CombinatorFilter();
+
+  /**
+   * Returns [:true:] if [element] is excluded by this filter.
+   */
+  bool exclude(Element element) => false;
+
+  /**
+   * Creates a filter based on the combinators of [tag].
+   */
+  factory CombinatorFilter.fromTag(LibraryDependency tag) {
+    if (tag == null || tag.combinators == null) {
+      return const CombinatorFilter();
+    }
+
+    // If the list of combinators contain at least one [:show:] we can create
+    // a positive list of elements to include, otherwise we create a negative
+    // list of elements to exclude.
+    bool show = false;
+    Set<SourceString> nameSet;
+    for (Combinator combinator in tag.combinators) {
+      if (combinator.isShow) {
+        show = true;
+        var set = new Set<SourceString>();
+        for (Identifier identifier in combinator.identifiers) {
+          set.add(identifier.source);
+        }
+        if (nameSet == null) {
+          nameSet = set;
+        } else {
+          nameSet = nameSet.intersection(set);
+        }
+      }
+    }
+    if (nameSet == null) {
+      nameSet = new Set<SourceString>();
+    }
+    for (Combinator combinator in tag.combinators) {
+      if (combinator.isHide) {
+        for (Identifier identifier in combinator.identifiers) {
+          if (show) {
+            // We have a positive list => Remove hidden elements.
+            nameSet.remove(identifier.source);
+          } else {
+            // We have no positive list => Accumulate hidden elements.
+            nameSet.add(identifier.source);
+          }
+        }
+      }
+    }
+    return show ? new ShowFilter(nameSet) : new HideFilter(nameSet);
+  }
+}
+
+/**
+ * A list of combinators represented as a list of element names to include.
+ */
+class ShowFilter extends CombinatorFilter {
+  final Set<SourceString> includedNames;
+
+  ShowFilter(this.includedNames);
+
+  bool exclude(Element element) => !includedNames.contains(element.name);
+}
+
+/**
+ * A list of combinators represented as a list of element names to exclude.
+ */
+class HideFilter extends CombinatorFilter {
+  final Set<SourceString> excludedNames;
+
+  HideFilter(this.excludedNames);
+
+  bool exclude(Element element) => excludedNames.contains(element.name);
+}
+
+/**
  * Implementation class for [LibraryLoader]. The distinction between
  * [LibraryLoader] and [LibraryLoaderTask] is made to hide internal members from
  * the [LibraryLoader] interface.
@@ -91,9 +172,6 @@
     for (LibraryTag tag in library.tags.reverse()) {
       if (tag.isImport) {
         tagState = checkTag(TagState.IMPORT_OR_EXPORT, tag);
-        if (tag.combinators != null) {
-          compiler.unimplemented('combinators', node: tag.combinators);
-        }
         if (tag.uri.dartString.slowToString() == 'dart:core') {
           importsDartCore = true;
         }
@@ -291,6 +369,7 @@
     assert(invariant(importingLibrary,
                      importedLibrary.exportsHandled,
                      message: 'Exports not handled on $importedLibrary'));
+    var combinatorFilter = new CombinatorFilter.fromTag(import);
     if (import !== null && import.prefix !== null) {
       SourceString prefix = import.prefix.source;
       Element e = importingLibrary.find(prefix);
@@ -308,7 +387,7 @@
       }
       PrefixElement prefixElement = e;
       importedLibrary.forEachExport((Element element) {
-        // TODO(johnniwinther): Handle show and hide combinators.
+        if (combinatorFilter.exclude(element)) return;
         // TODO(johnniwinther): Clean-up like [checkDuplicateLibraryName].
         Element existing =
             prefixElement.imported.putIfAbsent(element.name, () => element);
@@ -326,7 +405,7 @@
     } else {
       importedLibrary.forEachExport((Element element) {
         compiler.withCurrentElement(element, () {
-          // TODO(johnniwinther): Handle show and hide combinators.
+          if (combinatorFilter.exclude(element)) return;
           importingLibrary.addImport(element, compiler);
         });
       });
@@ -335,6 +414,29 @@
 }
 
 /**
+ * The combinator filter computed from an export tag and the library dependency
+ * node for the library that declared the export tag. This represents an edge in
+ * the library dependency graph.
+ */
+class ExportLink {
+  final CombinatorFilter combinatorFilter;
+  final LibraryDependencyNode exportNode;
+
+  ExportLink(Export export, LibraryDependencyNode this.exportNode)
+      : this.combinatorFilter = new CombinatorFilter.fromTag(export);
+
+  /**
+   * Exports [element] to the dependent library unless [element] is filtered by
+   * the export combinators. Returns [:true:] if the set pending exports of the
+   * dependent library was modified.
+   */
+  bool exportElement(Element element) {
+    if (combinatorFilter.exclude(element)) return false;
+    return exportNode.addElementToPendingExports(element);
+  }
+}
+
+/**
  * A node in the library dependency graph.
  *
  * This class is used to collect the library dependencies expressed through
@@ -349,15 +451,13 @@
    * corresponding libraries. This is used to propagate exports into imports
    * after the export scopes have been computed.
    */
-  Link<ImportLink> imports = const EmptyLink<ImportLink>();
+  Link<ImportLink> imports = const Link<ImportLink>();
 
   /**
-   * The export tags that export [library] mapped to the nodes for the libraries
-   * that declared each export tag. This is used to propagete exports during the
-   * computation of export scopes.
+   * A linked list of the export tags the dependent upon this node library.
+   * This is used to propagate exports during the computation of export scopes.
    */
-  Map<Export, LibraryDependencyNode> dependencyMap =
-      new Map<Export, LibraryDependencyNode>();
+  Link<ExportLink> dependencies = const Link<ExportLink>();
 
   /**
    * The export scope for [library] which is gradually computed by the work-list
@@ -389,7 +489,8 @@
    */
   void registerExportDependency(Export export,
                                 LibraryDependencyNode exportingLibraryNode) {
-    dependencyMap[export] = exportingLibraryNode;
+    dependencies =
+        dependencies.prepend(new ExportLink(export, exportingLibraryNode));
   }
 
   /**
@@ -433,7 +534,7 @@
 
   /**
    * Adds [element] to the export scope for this node. If the [element] name
-   * is a duplicate, an error element is inserted into the exscope.
+   * is a duplicate, an error element is inserted into the export scope.
    */
   Element addElementToExportScope(Compiler compiler, Element element) {
     SourceString name = element.name;
@@ -457,11 +558,11 @@
    */
   bool propagateElement(Element element) {
     bool change = false;
-    dependencyMap.forEach((Export export, LibraryDependencyNode exportNode) {
-      if (exportNode.addElementToPendingExports(export, element)) {
+    for (ExportLink link in dependencies) {
+      if (link.exportElement(element)) {
         change = true;
       }
-    });
+    }
     return change;
   }
 
@@ -470,8 +571,7 @@
    * the pending export set was modified. The combinators of [export] are used
    * to filter the element.
    */
-  bool addElementToPendingExports(Export export, Element element) {
-    // TODO(johnniwinther): Use [export] to handle show and hide combinators.
+  bool addElementToPendingExports(Element element) {
     if (exportScope[element.name] !== element) {
       if (!pendingExportSet.contains(element)) {
         pendingExportSet.add(element);
diff --git a/lib/compiler/implementation/resolver.dart b/lib/compiler/implementation/resolver.dart
index 6292087..17c9d56 100644
--- a/lib/compiler/implementation/resolver.dart
+++ b/lib/compiler/implementation/resolver.dart
@@ -365,7 +365,7 @@
           MessageKind.CYCLIC_CLASS_HIERARCHY.error([cls.name]),
           api.Diagnostic.ERROR);
         cls.supertypeLoadState = STATE_DONE;
-        cls.allSupertypes = const EmptyLink<DartType>().prepend(
+        cls.allSupertypes = const Link<DartType>().prepend(
             compiler.objectClass.computeType(compiler));
         // TODO(ahe): We should also set cls.supertype here to avoid
         // creating a malformed class hierarchy.
@@ -788,7 +788,7 @@
     });
 
     if (functionNode.initializers === null) {
-      initializers = const EmptyLink<Node>();
+      initializers = const Link<Node>();
     } else {
       initializers = functionNode.initializers.nodes;
     }
@@ -918,8 +918,8 @@
 
   StatementScope()
       : labels = const EmptyLabelScope(),
-        breakTargetStack = const EmptyLink<TargetElement>(),
-        continueTargetStack = const EmptyLink<TargetElement>();
+        breakTargetStack = const Link<TargetElement>(),
+        continueTargetStack = const Link<TargetElement>();
 
   LabelElement lookupLabel(String label) {
     return labels.lookup(label);
@@ -1086,7 +1086,7 @@
                                       Link<DartType> typeVariables,
                                       Scope scope, onFailure, whenResolved) {
     if (node.typeArguments == null) {
-      return const EmptyLink<DartType>();
+      return const Link<DartType>();
     }
     var arguments = new LinkBuilder<DartType>();
     for (Link<Node> typeArguments = node.typeArguments.nodes;
@@ -1279,7 +1279,7 @@
     FunctionSignature functionParameters =
         function.computeSignature(compiler);
     Link<Node> parameterNodes = (node.parameters === null)
-        ? const EmptyLink<Node>() : node.parameters.nodes;
+        ? const Link<Node>() : node.parameters.nodes;
     functionParameters.forEachParameter((Element element) {
       if (element == functionParameters.optionalParameters.head) {
         NodeList nodes = parameterNodes.head;
@@ -1375,9 +1375,20 @@
     } else {
       name = node.name.asIdentifier().source;
     }
+    // TODO(ahe): we shouldn't use the scope to get the enclosing element. This
+    // is currently needed so that nested functions get their correct enclosing
+    // element.
+    Element functionEnclosing = scope.element;
+    if (functionEnclosing.kind == ElementKind.VARIABLE_LIST) {
+      compiler.internalError("Bad enclosing element", node: node);
+    }
+    if (functionEnclosing.isLibrary()) {
+      // We are in a static initializers.
+      functionEnclosing = enclosingElement;
+    }
     FunctionElement enclosing = new FunctionElement.node(
         name, node, ElementKind.FUNCTION, Modifiers.EMPTY,
-        scope.element);
+        functionEnclosing);
     setupFunction(node, enclosing);
     defineElement(node, enclosing, doAddToScope: node.name !== null);
 
@@ -1847,7 +1858,7 @@
       // Resolve the type arguments. We cannot create a type and check the
       // number of type arguments for this annotation, because we do not know
       // the element.
-      Link arguments = const EmptyLink<Node>();
+      Link arguments = const Link<Node>();
       if (annotation.typeArguments != null) {
         arguments = annotation.typeArguments.nodes;
       }
@@ -2338,7 +2349,7 @@
       element.supertype = new InterfaceType(objectElement);
     }
     assert(element.interfaces === null);
-    Link<DartType> interfaces = const EmptyLink<DartType>();
+    Link<DartType> interfaces = const Link<DartType>();
     for (Link<Node> link = node.interfaces.nodes;
          !link.isEmpty();
          link = link.tail) {
@@ -2419,8 +2430,7 @@
       ClassElement superElement = supertype.element;
       Link<DartType> superSupertypes = superElement.allSupertypes;
       assert(superSupertypes !== null);
-      Link<DartType> supertypes =
-          new Link<DartType>(supertype, superSupertypes);
+      Link<DartType> supertypes = superSupertypes.prepend(supertype);
       for (Link<DartType> interfaces = cls.interfaces;
            !interfaces.isEmpty();
            interfaces = interfaces.tail) {
@@ -2433,7 +2443,7 @@
       cls.allSupertypes = supertypes;
     } else {
       assert(cls === compiler.objectClass);
-      cls.allSupertypes = const EmptyLink<DartType>();
+      cls.allSupertypes = const Link<DartType>();
     }
   }
 
@@ -2447,7 +2457,7 @@
       new SynthesizedConstructorElement(element);
     element.addToScope(constructor, compiler);
     DartType returnType = compiler.types.voidType;
-    constructor.type = new FunctionType(returnType, const EmptyLink<DartType>(),
+    constructor.type = new FunctionType(returnType, const Link<DartType>(),
                                         constructor);
     constructor.cachedNode =
       new FunctionExpression(new Identifier(element.position()),
@@ -2582,7 +2592,7 @@
  */
 class SignatureResolver extends CommonResolverVisitor<Element> {
   final Element enclosingElement;
-  Link<Element> optionalParameters = const EmptyLink<Element>();
+  Link<Element> optionalParameters = const Link<Element>();
   int optionalParameterCount = 0;
   bool optionalParametersAreNamed = false;
   VariableDefinitions currentDefinitions;
@@ -2725,7 +2735,7 @@
                                    Node returnNode,
                                    Element element) {
     SignatureResolver visitor = new SignatureResolver(compiler, element);
-    Link<Element> parameters = const EmptyLink<Element>();
+    Link<Element> parameters = const Link<Element>();
     int requiredParameterCount = 0;
     if (formalParameters === null) {
       if (!element.isGetter()) {
diff --git a/lib/compiler/implementation/runtime_types.dart b/lib/compiler/implementation/runtime_types.dart
index cd7f49a..9f51ec4 100644
--- a/lib/compiler/implementation/runtime_types.dart
+++ b/lib/compiler/implementation/runtime_types.dart
@@ -11,6 +11,25 @@
 #import('util/util.dart');
 
 class RuntimeTypeInformation {
+  /**
+   * Names used for elements in runtime type information. This map is kept to
+   * detect elements with the same name and use a different name instead.
+   */
+  final Map<String, Element> usedNames = new Map<String, Element>();
+
+  /** Get a unique name for the element. */
+  String getName(Element element) {
+    String guess = element.name.slowToString();
+    String name = guess;
+    int id = 0;
+    while (usedNames.containsKey(name) && usedNames[name] != element) {
+      name = '$guess@$id';
+      id++;
+    }
+    usedNames[name] = element;
+    return name;
+  }
+
   bool hasTypeArguments(DartType type) {
     if (type is InterfaceType) {
       InterfaceType interfaceType = type;
@@ -48,9 +67,8 @@
    * variables than [numberOfInputs], 'Dynamic' is used as the value for these
    * arguments.
    */
-  static String generateRuntimeTypeString(ClassElement element,
-                                          int numberOfInputs) {
-    String elementName = element.name.slowToString();
+  String generateRuntimeTypeString(ClassElement element, int numberOfInputs) {
+    String elementName = getName(element);
     if (element.typeVariables.isEmpty()) return "'$elementName'";
     String stringify(_, bool hasValue) => hasValue ? "' + # + '" : "Dynamic";
     String arguments = stringifyTypeVariables(element.typeVariables,
diff --git a/lib/compiler/implementation/scanner/array_based_scanner.dart b/lib/compiler/implementation/scanner/array_based_scanner.dart
index c15c166..3b6cff2 100644
--- a/lib/compiler/implementation/scanner/array_based_scanner.dart
+++ b/lib/compiler/implementation/scanner/array_based_scanner.dart
@@ -14,7 +14,7 @@
   /** Since the input is UTF8, some characters are represented by more
    * than one byte. [extraCharOffset] tracks the difference. */
   int extraCharOffset;
-  Link<BeginGroupToken> groupingStack = const EmptyLink<BeginGroupToken>();
+  Link<BeginGroupToken> groupingStack = const Link<BeginGroupToken>();
 
   ArrayBasedScanner(this.includeComments)
     : this.extraCharOffset = 0,
diff --git a/lib/compiler/implementation/scanner/class_element_parser.dart b/lib/compiler/implementation/scanner/class_element_parser.dart
index 70655d4..b2a4b03 100644
--- a/lib/compiler/implementation/scanner/class_element_parser.dart
+++ b/lib/compiler/implementation/scanner/class_element_parser.dart
@@ -11,7 +11,7 @@
 class PartialClassElement extends ClassElement {
   final Token beginToken;
   final Token endToken;
-  Node cachedNode;
+  ClassNode cachedNode;
 
   PartialClassElement(SourceString name,
                       Token this.beginToken,
@@ -56,37 +56,11 @@
 
   Token position() => beginToken;
 
+  // TODO(johnniwinther): Ensure that modifiers are always available.
+  Modifiers get modifiers =>
+      cachedNode != null ? cachedNode.modifiers : Modifiers.EMPTY;
+
   bool isInterface() => beginToken.stringValue === "interface";
-
-  PartialClassElement cloneTo(Element enclosing, DiagnosticListener listener) {
-    parseNode(listener);
-    // TODO(lrn): Is copying id acceptable?
-    // TODO(ahe): No.
-    PartialClassElement result =
-        new PartialClassElement(name, beginToken, endToken, enclosing, id);
-
-    assert(this.supertypeLoadState == STATE_NOT_STARTED);
-    assert(this.resolutionState == STATE_NOT_STARTED);
-    assert(this.type === null);
-    assert(this.supertype === null);
-    assert(this.defaultClass === null);
-    assert(this.interfaces === null);
-    assert(this.allSupertypes === null);
-    assert(this.backendMembers.isEmpty());
-
-    // Native is only used in DOM/HTML library for which we don't
-    // support patching.
-    assert(this.nativeName === null);
-
-    Link<Element> elementList = this.localMembers;
-    while (!elementList.isEmpty()) {
-      result.addMember(elementList.head.cloneTo(result, listener), listener);
-      elementList = elementList.tail;
-    }
-
-    result.cachedNode = cachedNode;
-    return result;
-  }
 }
 
 class MemberListener extends NodeListener {
@@ -194,7 +168,7 @@
     for (Link link = metadata; !link.isEmpty(); link = link.tail) {
       memberElement.addMetadata(link.head);
     }
-    metadata = const EmptyLink<MetadataAnnotation>();
+    metadata = const Link<MetadataAnnotation>();
     enclosingElement.addMember(memberElement, listener);
   }
 }
diff --git a/lib/compiler/implementation/scanner/listener.dart b/lib/compiler/implementation/scanner/listener.dart
index 2c74e0c..86d088c 100644
--- a/lib/compiler/implementation/scanner/listener.dart
+++ b/lib/compiler/implementation/scanner/listener.dart
@@ -567,7 +567,7 @@
 
   Link<Token> expectedDeclaration(Token token) {
     error("expected a declaration, but got '${token.slowToString()}'", token);
-    return const EmptyLink<Token>();
+    return const Link<Token>();
   }
 
   Token unmatched(Token token) {
@@ -613,9 +613,9 @@
   final StringValidator stringValidator;
   Link<StringQuoting> interpolationScope;
 
-  Link<Node> nodes = const EmptyLink<Node>();
+  Link<Node> nodes = const Link<Node>();
 
-  Link<MetadataAnnotation> metadata = const EmptyLink<MetadataAnnotation>();
+  Link<MetadataAnnotation> metadata = const Link<MetadataAnnotation>();
 
   ElementListener(DiagnosticListener listener,
                   CompilationUnitElement this.compilationUnitElement,
@@ -623,7 +623,7 @@
       : this.listener = listener,
         this.idGenerator = idGenerator,
         stringValidator = new StringValidator(listener),
-        interpolationScope = const EmptyLink<StringQuoting>();
+        interpolationScope = const Link<StringQuoting>();
 
   void pushQuoting(StringQuoting quoting) {
     interpolationScope = interpolationScope.prepend(quoting);
@@ -974,7 +974,7 @@
   Link<Token> expectedDeclaration(Token token) {
     listener.cancel("expected a declaration, but got '${token.slowToString()}'",
                     token: token);
-    return const EmptyLink<Token>();
+    return const Link<Token>();
   }
 
   Token unmatched(Token token) {
@@ -990,7 +990,7 @@
     for (Link link = metadata; !link.isEmpty(); link = link.tail) {
       element.addMetadata(link.head);
     }
-    metadata = const EmptyLink<MetadataAnnotation>();
+    metadata = const Link<MetadataAnnotation>();
     compilationUnitElement.addMember(element, listener);
   }
 
@@ -1036,7 +1036,7 @@
 
   NodeList makeNodeList(int count, Token beginToken, Token endToken,
                         String delimiter) {
-    Link<Node> poppedNodes = const EmptyLink<Node>();
+    Link<Node> poppedNodes = const Link<Node>();
     for (; count > 0; --count) {
       // This effectively reverses the order of nodes so they end up
       // in correct (source) order.
@@ -1066,7 +1066,7 @@
     StringQuoting quoting = popQuoting();
 
     Link<StringInterpolationPart> parts =
-        const EmptyLink<StringInterpolationPart>();
+        const Link<StringInterpolationPart>();
     // Parts of the string interpolation are popped in reverse order,
     // starting with the last literal string part.
     bool isLast = true;
@@ -1137,8 +1137,10 @@
     TypeAnnotation supertype = popNode();
     NodeList typeParameters = popNode();
     Identifier name = popNode();
-    pushNode(new ClassNode(name, typeParameters, supertype, interfaces, null,
-                           beginToken, extendsKeyword, body, endToken));
+    Modifiers modifiers = popNode();
+    pushNode(new ClassNode(modifiers, name, typeParameters, supertype,
+                           interfaces, null, beginToken, extendsKeyword, body,
+                           endToken));
   }
 
   void endCompilationUnit(int count, Token token) {
@@ -1162,9 +1164,9 @@
                                        null, ',');
     NodeList typeParameters = popNode();
     Identifier name = popNode();
-    pushNode(new ClassNode(name, typeParameters, null, supertypes,
-                           defaultClause, interfaceKeyword, null, body,
-                           endToken));
+    pushNode(new ClassNode(Modifiers.EMPTY, name, typeParameters, null,
+                           supertypes, defaultClause, interfaceKeyword, null,
+                           body, endToken));
   }
 
   void endClassBody(int memberCount, Token beginToken, Token endToken) {
@@ -1329,7 +1331,7 @@
     if (send.asSendSet() !== null) internalError(node: send);
     NodeList arguments;
     if (send.isIndex) {
-      Link<Node> link = new Link<Node>(arg);
+      Link<Node> link = const Link<Node>().prepend(arg);
       link = link.prepend(send.arguments.head);
       arguments = new NodeList(null, link);
     } else {
@@ -1613,7 +1615,7 @@
   }
 
   void endSwitchBlock(int caseCount, Token beginToken, Token endToken) {
-    Link<Node> caseNodes = const EmptyLink<Node>();
+    Link<Node> caseNodes = const Link<Node>();
     while (caseCount > 0) {
       SwitchCase switchCase = popNode();
       caseNodes = caseNodes.prepend(switchCase);
diff --git a/lib/compiler/implementation/scanner/parser.dart b/lib/compiler/implementation/scanner/parser.dart
index 72fd63b..b2faf1a 100644
--- a/lib/compiler/implementation/scanner/parser.dart
+++ b/lib/compiler/implementation/scanner/parser.dart
@@ -433,10 +433,13 @@
   Token parseClass(Token token) {
     Token begin = token;
     listener.beginClassDeclaration(token);
+    int modifierCount = 0;
     if (optional('abstract', token)) {
-      // TODO(ahe): Notify listener about abstract modifier.
+      listener.handleModifier(token);
+      modifierCount++;
       token = token.next;
     }
+    listener.handleModifiers(modifierCount);
     token = parseIdentifier(token.next);
     token = parseTypeVariablesOpt(token);
     Token extendsKeyword;
@@ -649,7 +652,7 @@
 
   Link<Token> findMemberName(Token token) {
     Token start = token;
-    Link<Token> identifiers = const EmptyLink<Token>();
+    Link<Token> identifiers = const Link<Token>();
     while (token.kind !== EOF_TOKEN) {
       String value = token.stringValue;
       if ((value === '(') || (value === '{') || (value === '=>')) {
diff --git a/lib/compiler/implementation/ssa/builder.dart b/lib/compiler/implementation/ssa/builder.dart
index d9995d5..5cf3d37 100644
--- a/lib/compiler/implementation/ssa/builder.dart
+++ b/lib/compiler/implementation/ssa/builder.dart
@@ -367,21 +367,25 @@
    *
    * Invariant: [function] must be an implementation element.
    */
-  void startFunction(FunctionElement function,
-                     FunctionExpression node) {
-    assert(invariant(node, function.isImplementation));
+  void startFunction(Element element, Expression node) {
+    assert(invariant(node, element.isImplementation));
     Compiler compiler = builder.compiler;
     closureData = compiler.closureToClassMapper.computeClosureToClassMapping(
-            node, builder.elements);
-    FunctionSignature signature = function.computeSignature(compiler);
-    signature.orderedForEachParameter((Element element) {
-      HInstruction parameter = new HParameterValue(element);
-      builder.add(parameter);
-      builder.parameters[element] = parameter;
-      directLocals[element] = parameter;
-      parameter.guaranteedType =
-        builder.mapInferredType(typesTask.getGuaranteedTypeOfElement(element));
-    });
+            element, node, builder.elements);
+
+    if (element is FunctionElement) {
+      FunctionElement functionElement = element;
+      FunctionSignature params = functionElement.computeSignature(compiler);
+      params.orderedForEachParameter((Element parameterElement) {
+        HInstruction parameter = new HParameterValue(parameterElement);
+        builder.add(parameter);
+        builder.parameters[parameterElement] = parameter;
+        directLocals[parameterElement] = parameter;
+        parameter.guaranteedType =
+            builder.mapInferredType(
+                typesTask.getGuaranteedTypeOfElement(parameterElement));
+      });
+    }
 
     enterScope(node);
 
@@ -396,12 +400,12 @@
       HInstruction thisInstruction = new HThis();
       builder.add(thisInstruction);
       updateLocal(closureData.closureElement, thisInstruction);
-    } else if (function.isInstanceMember()
-               || function.isGenerativeConstructor()) {
+    } else if (element.isInstanceMember()
+               || element.isGenerativeConstructor()) {
       // Once closures have been mapped to classes their instance members might
       // not have any thisElement if the closure was created inside a static
       // context.
-      ClassElement cls = function.getEnclosingClass();
+      ClassElement cls = element.getEnclosingClass();
       DartType type = cls.computeType(builder.compiler);
       HInstruction thisInstruction = new HThis(new HBoundedType.nonNull(type));
       builder.add(thisInstruction);
@@ -853,6 +857,7 @@
   LocalsHandler localsHandler;
   HInstruction rethrowableException;
   Map<Element, HParameterValue> parameters;
+  final RuntimeTypeInformation rti;
 
   Map<TargetElement, JumpHandler> jumpTargets;
 
@@ -894,6 +899,7 @@
       parameters = new Map<Element, HParameterValue>(),
       sourceElementStack = <Element>[work.element],
       inliningStack = <InliningState>[],
+      rti = builder.compiler.codegenWorld.rti,
       super(work.resolutionTree) {
     localsHandler = new LocalsHandler(this);
   }
@@ -930,19 +936,15 @@
   }
 
   HGraph buildLazyInitializer(VariableElement variable) {
-    HBasicBlock block = graph.addNewBlock();
-    open(graph.entry);
-    close(new HGoto()).addSuccessor(block);
-    open(block);
     SendSet node = variable.parseNode(compiler);
+    openFunction(variable, node);
     Link<Node> link = node.arguments;
     assert(!link.isEmpty() && link.tail.isEmpty());
     visit(link.head);
     HInstruction value = pop();
     value = potentiallyCheckType(value, variable);
     close(new HReturn(value)).addSuccessor(graph.exit);
-    graph.finalize();
-    return graph;
+    return closeFunction();
   }
 
   /**
@@ -1219,7 +1221,7 @@
         }
         inlineSuperOrRedirect(target.implementation,
                               selector,
-                              const EmptyLink<Node>(),
+                              const Link<Node>(),
                               constructors,
                               fieldValues);
       }
@@ -1411,38 +1413,43 @@
    *
    * Invariant: [functionElement] must be the implementation element.
    */
-  void openFunction(FunctionElement functionElement,
-                    FunctionExpression node) {
-    assert(invariant(functionElement, functionElement.isImplementation));
+  void openFunction(Element element, Expression node) {
+    assert(invariant(element, element.isImplementation));
     HBasicBlock block = graph.addNewBlock();
     open(graph.entry);
 
-    localsHandler.startFunction(functionElement, node);
+    localsHandler.startFunction(element, node);
     close(new HGoto()).addSuccessor(block);
 
     open(block);
 
-    FunctionSignature params = functionElement.computeSignature(compiler);
-    params.orderedForEachParameter((Element element) {
-      if (elements.isParameterChecked(element)) {
-        addParameterCheckInstruction(element);
-      }
-    });
+    if (element is FunctionElement) {
+      FunctionElement functionElement = element;
+      FunctionSignature params = functionElement.computeSignature(compiler);
+      params.orderedForEachParameter((Element parameterElement) {
+        if (elements.isParameterChecked(parameterElement)) {
+          addParameterCheckInstruction(parameterElement);
+        }
+      });
 
-    // Put the type checks in the first successor of the entry,
-    // because that is where the type guards will also be inserted.
-    // This way we ensure that a type guard will dominate the type
-    // check.
-    params.orderedForEachParameter((Element element) {
-      HInstruction newParameter = potentiallyCheckType(
-          localsHandler.directLocals[element], element);
-      localsHandler.directLocals[element] = newParameter;
-    });
+      // Put the type checks in the first successor of the entry,
+      // because that is where the type guards will also be inserted.
+      // This way we ensure that a type guard will dominate the type
+      // check.
+      params.orderedForEachParameter((Element element) {
+        HInstruction newParameter = potentiallyCheckType(
+            localsHandler.directLocals[element], element);
+        localsHandler.directLocals[element] = newParameter;
+      });
+    } else {
+      // Otherwise it is a lazy initializer which does not have parameters.
+      assert(element is VariableElement);
+    }
 
     // Add the type parameters of the class as parameters of this
     // method.
-    var enclosing = functionElement.enclosingElement;
-    if (functionElement.isConstructor() && compiler.world.needsRti(enclosing)) {
+    var enclosing = element.enclosingElement;
+    if (element.isConstructor() && compiler.world.needsRti(enclosing)) {
       enclosing.typeVariables.forEach((TypeVariableType typeVariable) {
         HParameterValue param = new HParameterValue(typeVariable.element);
         add(param);
@@ -2182,7 +2189,7 @@
       // An erroneous element indicates an unresolved static getter.
       generateThrowNoSuchMethod(send,
                                 getTargetName(element, 'get'),
-                                const EmptyLink<Node>());
+                                const Link<Node>());
     } else {
       stack.add(localsHandler.readLocal(element));
     }
@@ -2792,7 +2799,7 @@
         InterfaceType interfaceType = type;
         bool hasTypeArguments = !interfaceType.arguments.isEmpty();
         if (!isInQuotes) template.add("'");
-        template.add("${type.element.name.slowToString()}");
+        template.add(rti.getName(type.element));
         if (hasTypeArguments) {
           template.add("<");
           for (DartType argument in interfaceType.arguments) {
@@ -2809,7 +2816,7 @@
       } else {
         assert(type is TypedefType);
         if (!isInQuotes) template.add("'");
-        template.add(argument.toString());
+        template.add(rti.getName(argument.element));
         if (!isInQuotes) template.add("'");
       }
     }
@@ -2854,8 +2861,7 @@
     List<HInstruction> runtimeCodeInputs = <HInstruction>[];
     if (runtimeTypeIsUsed) {
       String runtimeTypeString =
-          RuntimeTypeInformation.generateRuntimeTypeString(element,
-                                                           rtiInputs.length);
+          rti.generateRuntimeTypeString(element, rtiInputs.length);
       HInstruction runtimeType = createForeign(runtimeTypeString, rtiInputs);
       add(runtimeType);
       runtimeCodeInputs.add(runtimeType);
@@ -4059,13 +4065,16 @@
     compiler.internalError('SsaBuilder.visitTypeVariable');
   }
 
-  HType mapInferredType(Element element) {
-    if (element === builder.compiler.boolClass) return HType.BOOLEAN;
-    if (element === builder.compiler.doubleClass) return HType.DOUBLE;
-    if (element === builder.compiler.intClass) return HType.INTEGER;
-    if (element === builder.compiler.listClass) return HType.READABLE_ARRAY;
-    if (element === builder.compiler.nullClass) return HType.NULL;
-    if (element === builder.compiler.stringClass) return HType.STRING;
+  HType mapInferredType(ConcreteType concreteType) {
+    if (concreteType == null) return HType.UNKNOWN;
+    ClassElement element = concreteType.getUniqueType();
+    if (element == null) return HType.UNKNOWN;
+    if (element == builder.compiler.boolClass) return HType.BOOLEAN;
+    if (element == builder.compiler.doubleClass) return HType.DOUBLE;
+    if (element == builder.compiler.intClass) return HType.INTEGER;
+    if (element == builder.compiler.listClass) return HType.READABLE_ARRAY;
+    if (element == builder.compiler.nullClass) return HType.NULL;
+    if (element == builder.compiler.stringClass) return HType.STRING;
     return HType.UNKNOWN;
   }
 
diff --git a/lib/compiler/implementation/ssa/codegen.dart b/lib/compiler/implementation/ssa/codegen.dart
index 5afc86f..27e1b23 100644
--- a/lib/compiler/implementation/ssa/codegen.dart
+++ b/lib/compiler/implementation/ssa/codegen.dart
@@ -78,7 +78,7 @@
       // the declaration.
       FunctionElement function = work.element;
       function.computeSignature(compiler).forEachParameter((element) {
-        compiler.enqueuer.codegen.addToWorkList(element);
+        compiler.enqueuer.codegen.addToWorkList(element, work.resolutionTree);
       });
       List<js.Parameter> parameters = <js.Parameter>[];
       parameterNames.forEach((element, name) {
@@ -952,7 +952,7 @@
 
   bool visitLabeledBlockInfo(HLabeledBlockInformation labeledBlockInfo) {
     preLabeledBlock(labeledBlockInfo);
-    Link<Element> continueOverrides = const EmptyLink<Element>();
+    Link<Element> continueOverrides = const Link<Element>();
 
     js.Block oldContainer = currentContainer;
     js.Block body = new js.Block.empty();
diff --git a/lib/compiler/implementation/ssa/nodes.dart b/lib/compiler/implementation/ssa/nodes.dart
index e2da4ab..8d1f4c0 100644
--- a/lib/compiler/implementation/ssa/nodes.dart
+++ b/lib/compiler/implementation/ssa/nodes.dart
@@ -616,7 +616,7 @@
    * information on [to], and that dominates the user.
    */
   void rewriteWithBetterUser(HInstruction from, HInstruction to) {
-    Link<HCheck> better = const EmptyLink<HCheck>();
+    Link<HCheck> better = const Link<HCheck>();
     for (HInstruction user in to.usedBy) {
       if (user is HCheck && (user as HCheck).checkedInput === to) {
         better = better.prepend(user);
diff --git a/lib/compiler/implementation/ssa/ssa.dart b/lib/compiler/implementation/ssa/ssa.dart
index c5b4f1e..4a6ce7a 100644
--- a/lib/compiler/implementation/ssa/ssa.dart
+++ b/lib/compiler/implementation/ssa/ssa.dart
@@ -15,6 +15,7 @@
 #import('../runtime_types.dart');
 #import('../scanner/scannerlib.dart');
 #import('../tree/tree.dart');
+#import('../types/types.dart');
 #import('../universe/universe.dart');
 #import('../util/util.dart');
 #import('../util/characters.dart');
diff --git a/lib/compiler/implementation/tree/nodes.dart b/lib/compiler/implementation/tree/nodes.dart
index c87e893..d241628 100644
--- a/lib/compiler/implementation/tree/nodes.dart
+++ b/lib/compiler/implementation/tree/nodes.dart
@@ -202,6 +202,7 @@
 }
 
 class ClassNode extends Node {
+  final Modifiers modifiers;
   final Identifier name;
   final TypeAnnotation superclass;
   final NodeList interfaces;
@@ -215,9 +216,9 @@
   final Token extendsKeyword;
   final Token endToken;
 
-  ClassNode(this.name, this.typeParameters, this.superclass, this.interfaces,
-            this.defaultClause, this.beginToken, this.extendsKeyword,
-            this.body, this.endToken);
+  ClassNode(this.modifiers, this.name, this.typeParameters, this.superclass,
+            this.interfaces, this.defaultClause, this.beginToken,
+            this.extendsKeyword, this.body, this.endToken);
 
   ClassNode asClassNode() => this;
 
@@ -356,12 +357,12 @@
 }
 
 class Postfix extends NodeList {
-  Postfix() : super(nodes: const EmptyLink<Node>());
+  Postfix() : super(nodes: const Link<Node>());
   Postfix.singleton(Node argument) : super.singleton(argument);
 }
 
 class Prefix extends NodeList {
-  Prefix() : super(nodes: const EmptyLink<Node>());
+  Prefix() : super(nodes: const Link<Node>());
   Prefix.singleton(Node argument) : super.singleton(argument);
 }
 
@@ -439,8 +440,8 @@
 
   Iterator<Node> iterator() => nodes.iterator();
 
-  NodeList.singleton(Node node) : this(null, new Link<Node>(node));
-  NodeList.empty() : this(null, const EmptyLink<Node>());
+  NodeList.singleton(Node node) : this(null, const Link<Node>().prepend(node));
+  NodeList.empty() : this(null, const Link<Node>());
 
   NodeList asNodeList() => this;
 
diff --git a/lib/compiler/implementation/tree/prettyprint.dart b/lib/compiler/implementation/tree/prettyprint.dart
index 3132618..81886a8 100644
--- a/lib/compiler/implementation/tree/prettyprint.dart
+++ b/lib/compiler/implementation/tree/prettyprint.dart
@@ -18,7 +18,7 @@
 
   PrettyPrinter() :
       sb = new StringBuffer(),
-      tagStack = new EmptyLink<String>();
+      tagStack = const Link<String>();
 
   void pushTag(String tag) {
     tagStack = tagStack.prepend(tag);
diff --git a/lib/compiler/implementation/typechecker.dart b/lib/compiler/implementation/typechecker.dart
index b57c1a8..fbba6f3 100644
--- a/lib/compiler/implementation/typechecker.dart
+++ b/lib/compiler/implementation/typechecker.dart
@@ -123,7 +123,7 @@
   final Link<DartType> arguments;
 
   const InterfaceType(this.element,
-                      [this.arguments = const EmptyLink<DartType>()]);
+                      [this.arguments = const Link<DartType>()]);
 
   SourceString get name => element.name;
 
@@ -216,7 +216,7 @@
   final Link<DartType> typeArguments;
 
   const TypedefType(this.element,
-      [this.typeArguments = const EmptyLink<DartType>()]);
+      [this.typeArguments = const Link<DartType>()]);
 
   SourceString get name => element.name;
 
@@ -331,7 +331,7 @@
   DartType expectedReturnType;
   ClassElement currentClass;
 
-  Link<DartType> cascadeTypes = const EmptyLink<DartType>();
+  Link<DartType> cascadeTypes = const Link<DartType>();
 
   DartType intType;
   DartType doubleType;
diff --git a/lib/compiler/implementation/types/concrete_types_inferrer.dart b/lib/compiler/implementation/types/concrete_types_inferrer.dart
index 7f2b4ad..cd22a7a 100644
--- a/lib/compiler/implementation/types/concrete_types_inferrer.dart
+++ b/lib/compiler/implementation/types/concrete_types_inferrer.dart
@@ -18,6 +18,7 @@
  *   - the unknown base type
  */
 abstract class BaseType {
+  bool isClass();
   bool isUnknown();
   bool isNull();
 }
@@ -36,6 +37,7 @@
   }
   int hashCode() => element.hashCode();
   String toString() => element.name.slowToString();
+  bool isClass() => true;
   bool isUnknown() => false;
   bool isNull() => false;
 }
@@ -47,6 +49,7 @@
   const UnknownBaseType();
   bool operator ==(BaseType other) => other is UnknownBaseType;
   int hashCode() => 0;
+  bool isClass() => false;
   bool isUnknown() => true;
   bool isNull() => false;
   toString() => "unknown";
@@ -59,6 +62,7 @@
   const NullBaseType();
   bool operator ==(BaseType other) => other is NullBaseType;
   int hashCode() => 1;
+  bool isClass() => false;
   bool isUnknown() => false;
   bool isNull() => true;
   toString() => "null";
@@ -89,6 +93,12 @@
   abstract ConcreteType union(ConcreteType other);
   abstract bool isUnkown();
   abstract Set<BaseType> get baseTypes();
+
+  /**
+   * Returns the unique element of [: this :] if [: this :] is a singleton,
+   * null otherwise.
+   */
+  abstract ClassElement getUniqueType();
 }
 
 /**
@@ -102,6 +112,7 @@
       new Set<BaseType>.from([const UnknownBaseType()]);
   int hashCode() => 0;
   ConcreteType union(ConcreteType other) => this;
+  ClassElement getUniqueType() => null;
   toString() => "unknown";
 }
 
@@ -143,6 +154,17 @@
     return new UnionType(newBaseTypes);
   }
 
+  ClassElement getUniqueType() {
+    if (baseTypes.length == 1) {
+      BaseType uniqueBaseType = baseTypes.iterator().next();
+      if (uniqueBaseType.isClass()) {
+        ClassBaseType uniqueClassType = uniqueBaseType;
+        return uniqueClassType.element;
+      }
+    }
+    return null;
+  }
+
   String toString() => baseTypes.toString();
 }
 
@@ -323,7 +345,6 @@
  * of the program. The entry point is [analyzeMain].
  */
 class ConcreteTypesInferrer {
-
   static final bool LOG_FAILURES = true;
 
   final String name = "Type inferrer";
diff --git a/lib/compiler/implementation/types/types.dart b/lib/compiler/implementation/types/types.dart
index 322ceed..dbbb11e 100644
--- a/lib/compiler/implementation/types/types.dart
+++ b/lib/compiler/implementation/types/types.dart
@@ -19,10 +19,13 @@
   final String name = 'Type inference';
   final Set<Element> untypedElements;
   final Map<Element, Link<Element>> typedSends;
+  final ConcreteTypesInferrer concreteTypesInferrer;
 
-  TypesTask(Compiler compiler)
+  TypesTask(Compiler compiler, bool enableConcreteTypeInference)
     : untypedElements = new Set<Element>(),
       typedSends = new Map<Element, Link<Element>>(),
+      concreteTypesInferrer = enableConcreteTypeInference
+          ? new ConcreteTypesInferrer(compiler) : null,
       super(compiler);
 
   /**
@@ -38,18 +41,25 @@
   /**
    * Called when resolution is complete.
    */
-  void onResolutionComplete() {
+  void onResolutionComplete(Element mainElement) {
     measure(() {
-      // TODO(ahe): Do something here.
+      if (concreteTypesInferrer != null) {
+        concreteTypesInferrer.analyzeMain(mainElement);
+      }
     });
   }
 
   /**
-   * Return the (inferred) guaranteed type of [element].
+   * Return the (inferred) guaranteed concrete type of [element] or null.
    */
-  Element getGuaranteedTypeOfElement(Element element) {
+  ConcreteType getGuaranteedTypeOfElement(Element element) {
     return measure(() {
       if (!element.isParameter()) return null;
+      if (concreteTypesInferrer != null) {
+        ConcreteType guaranteedType = concreteTypesInferrer
+            .getConcreteTypeOfParameter(element);
+        if (guaranteedType != null) return guaranteedType;
+      }
       Element holder = element.enclosingElement;
       Link<Element> types = typedSends[holder];
       if (types === null) return null;
@@ -59,7 +69,9 @@
       FunctionSignature signature = function.computeSignature(compiler);
       for (Element parameter in signature.requiredParameters) {
         if (types.isEmpty()) return null;
-        if (element === parameter) return types.head;
+        if (element == parameter) {
+          return new ConcreteType.singleton(new ClassBaseType(types.head));
+        }
         types = types.tail;
       }
       return null;
@@ -67,12 +79,14 @@
   }
 
   /**
-   * Return the (inferred) guaranteed type of [node].
+   * Return the (inferred) guaranteed concrete type of [node] or null.
    * [node] must be an AST node of [owner].
    */
-  Element getGuaranteedTypeOfNode(Node node, Element owner) {
+  ConcreteType getGuaranteedTypeOfNode(Node node, Element owner) {
     return measure(() {
-      // TODO(ahe): Do something real here.
+      if (concreteTypesInferrer != null) {
+        return concreteTypesInferrer.getConcreteTypeOfNode(node);
+      }
       return null;
     });
   }
@@ -151,7 +165,7 @@
 
   Link<Element> computeConcreteSendArguments(Send node) {
     if (node.argumentsNode === null) return null;
-    if (node.arguments.isEmpty()) return const EmptyLink<Element>();
+    if (node.arguments.isEmpty()) return const Link<Element>();
     if (node.receiver !== null && concreteTypes[node.receiver] === null) {
       return null;
     }
diff --git a/lib/compiler/implementation/universe/partial_type_tree.dart b/lib/compiler/implementation/universe/partial_type_tree.dart
index 1e80361..7cc1512 100644
--- a/lib/compiler/implementation/universe/partial_type_tree.dart
+++ b/lib/compiler/implementation/universe/partial_type_tree.dart
@@ -85,7 +85,7 @@
       // the subtypes so we can move them from being children of the
       // current node to being children of a new node if we need
       // to insert that.
-      Link<PartialTypeTreeNode> subtypes = const EmptyLink();
+      Link<PartialTypeTreeNode> subtypes = const Link();
       for (Link link = current.children; !link.isEmpty(); link = link.tail) {
         PartialTypeTreeNode child = link.head;
         ClassElement childType = child.type;
@@ -107,7 +107,7 @@
       PartialTypeTreeNode newNode = newNode(type);
       if (!subtypes.isEmpty()) {
         newNode.children = subtypes;
-        Link<PartialTypeTreeNode> remaining = const EmptyLink();
+        Link<PartialTypeTreeNode> remaining = const Link();
         for (Link link = current.children; !link.isEmpty(); link = link.tail) {
           PartialTypeTreeNode child = link.head;
           if (!child.type.isSubclassOf(type)) {
@@ -159,7 +159,7 @@
   final ClassElement type;
   Link<PartialTypeTreeNode> children;
 
-  PartialTypeTreeNode(this.type) : children = const EmptyLink();
+  PartialTypeTreeNode(this.type) : children = const Link();
 
   /**
    * Visits this node and its children recursively. If the visit
@@ -174,4 +174,4 @@
     return true;
   }
 
-}
\ No newline at end of file
+}
diff --git a/lib/compiler/implementation/universe/selector_map.dart b/lib/compiler/implementation/universe/selector_map.dart
index 532acf8..148c86b 100644
--- a/lib/compiler/implementation/universe/selector_map.dart
+++ b/lib/compiler/implementation/universe/selector_map.dart
@@ -28,7 +28,8 @@
       // No existing selectors with the given name. Create a new
       // linked list.
       SelectorValue<T> head = new SelectorValue<T>(selector, value);
-      node.selectorsByName[selector.name] = new Link<SelectorValue<T>>(head);
+      node.selectorsByName[selector.name] =
+          new Link<SelectorValue<T>>().prepend(head);
     } else {
       // Run through the linked list of selectors with the same name. If
       // we find one that matches, we update the value in the mapping.
diff --git a/lib/compiler/implementation/util/link.dart b/lib/compiler/implementation/util/link.dart
index cffc7e7..1029363 100644
--- a/lib/compiler/implementation/util/link.dart
+++ b/lib/compiler/implementation/util/link.dart
@@ -2,28 +2,60 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-interface Link<T> extends Iterable<T> default LinkFactory<T> {
-  final T head;
-  final Link<T> tail;
+class Link<T> implements Iterable<T> {
+  T get head => null;
+  Link<T> get tail => null;
 
-  Link(T head, [Link<T> tail]);
-  Link.fromList(List<T> list);
+  factory Link.fromList(List<T> list) {
+    switch (list.length) {
+      case 0:
+        return new Link<T>();
+      case 1:
+        return new LinkEntry<T>(list[0]);
+      case 2:
+        return new LinkEntry<T>(list[0], new LinkEntry<T>(list[1]));
+      case 3:
+        return new LinkEntry<T>(
+            list[0], new LinkEntry<T>(list[1], new LinkEntry<T>(list[2])));
+    }
+    Link link = new Link<T>();
+    for (int i = list.length ; i > 0; i--) {
+      link = link.prepend(list[i - 1]);
+    }
+    return link;
+  }
 
-  Link<T> prepend(T element);
-  List<T> toList();
-  bool isEmpty();
-  Link<T> reverse();
-  Link<T> reversePrependAll(Link<T> from);
+  const Link();
 
-  void printOn(StringBuffer buffer, [separatedBy]);
+  Link<T> prepend(T element) {
+    // TODO(ahe): Use new Link<T>, but this cost 8% performance on VM.
+    return new LinkEntry<T>(element, this);
+  }
 
-  void forEach(void f(T element));
+  Iterator<T> iterator() => new LinkIterator<T>(this);
 
-  bool operator ==(other);
-}
+  void printOn(StringBuffer buffer, [separatedBy]) {
+  }
 
-interface EmptyLink<T> extends Link<T> default LinkTail<T> {
-  const EmptyLink();
+  List toList() => new List<T>(0);
+
+  bool isEmpty() => true;
+
+  Link<T> reverse() => this;
+
+  Link<T> reversePrependAll(Link<T> from) {
+    if (from.isEmpty()) return this;
+    return this.prepend(from.head).reversePrependAll(from.tail);
+  }
+
+  void forEach(void f(T element)) {}
+
+  bool operator ==(other) {
+    if (other is !Link<T>) return false;
+    return other.isEmpty();
+  }
+
+  String toString() => "[]";
 }
 
 interface LinkBuilder<T> default LinkBuilderImplementation<T> {
diff --git a/lib/compiler/implementation/util/link_implementation.dart b/lib/compiler/implementation/util/link_implementation.dart
index a1f8492..82a8988 100644
--- a/lib/compiler/implementation/util/link_implementation.dart
+++ b/lib/compiler/implementation/util/link_implementation.dart
@@ -13,83 +13,18 @@
   }
 }
 
-class LinkFactory<T> {
-  factory Link(T head, [Link<T> tail]) {
-    if (tail === null) {
-      tail = new LinkTail<T>();
-    }
-    return new LinkEntry<T>(head, tail);
-  }
-
-  factory Link.fromList(List<T> list) {
-    switch (list.length) {
-      case 0:
-        return new LinkTail<T>();
-      case 1:
-        return new Link<T>(list[0]);
-      case 2:
-        return new Link<T>(list[0], new Link<T>(list[1]));
-      case 3:
-        return new Link<T>(list[0], new Link<T>(list[1], new Link<T>(list[2])));
-    }
-    Link link = new Link<T>(list.last());
-    for (int i = list.length - 1; i > 0; i--) {
-      link = link.prepend(list[i - 1]);
-    }
-    return link;
-  }
-}
-
-class LinkTail<T> implements EmptyLink<T> {
-  T get head => null;
-  Link<T> get tail => null;
-
-  const LinkTail();
-
-  Link<T> prepend(T element) {
-    // TODO(ahe): Use new Link<T>, but this cost 8% performance on VM.
-    return new LinkEntry<T>(element, this);
-  }
-
-  Iterator<T> iterator() => new LinkIterator<T>(this);
-
-  void printOn(StringBuffer buffer, [separatedBy]) {
-  }
-
-  String toString() => "[]";
-
-  Link<T> reverse() => this;
-
-  Link<T> reversePrependAll(Link<T> from) {
-    if (from.isEmpty()) return this;
-    return this.prepend(from.head).reversePrependAll(from.tail);
-  }
-
-  List toList() => const [];
-
-  bool isEmpty() => true;
-
-  void forEach(void f(T element)) {}
-
-  bool operator ==(other) {
-    if (other is !Link<T>) return false;
-    return other.isEmpty();
-  }
-}
-
-class LinkEntry<T> implements Link<T> {
+class LinkEntry<T> extends Link<T> {
   final T head;
   Link<T> tail;
 
-  LinkEntry(T this.head, Link<T> this.tail);
+  LinkEntry(T this.head, [Link<T> tail])
+    : this.tail = ((tail == null) ? new Link<T>() : tail);
 
   Link<T> prepend(T element) {
     // TODO(ahe): Use new Link<T>, but this cost 8% performance on VM.
     return new LinkEntry<T>(element, this);
   }
 
-  Iterator<T> iterator() => new LinkIterator<T>(this);
-
   void printOn(StringBuffer buffer, [separatedBy]) {
     buffer.add(head);
     if (separatedBy === null) separatedBy = '';
@@ -108,7 +43,7 @@
   }
 
   Link<T> reverse() {
-    Link<T> result = const LinkTail();
+    Link<T> result = const Link();
     for (Link<T> link = this; !link.isEmpty(); link = link.tail) {
       result = result.prepend(link.head);
     }
@@ -162,8 +97,8 @@
   LinkBuilderImplementation();
 
   Link<T> toLink() {
-    if (head === null) return const LinkTail();
-    lastLink.tail = const LinkTail();
+    if (head === null) return const Link();
+    lastLink.tail = const Link();
     Link<T> link = head;
     lastLink = null;
     head = null;
diff --git a/lib/html/scripts/generator.py b/lib/html/scripts/generator.py
index 937e345..da62d88 100644
--- a/lib/html/scripts/generator.py
+++ b/lib/html/scripts/generator.py
@@ -636,6 +636,12 @@
   def has_generated_interface(self):
     raise NotImplementedError()
 
+  def merged_interface(self):
+    return None
+
+  def merged_into(self):
+    return None
+
   def native_type(self):
     return self._data.native_type or self._idl_type
 
@@ -742,6 +748,26 @@
   def has_generated_interface(self):
     return True
 
+  def merged_interface(self):
+    # All constants, attributes, and operations of merged interface should be
+    # added to this interface. Merged idl interface does not have corresponding
+    # Dart generated interface, and all references to merged idl interface
+    # (e.g. parameter types, return types, parent interfaces) should be replaced
+    # with this interface. There are two important restrictions:
+    # 1) Merged and target interfaces shouldn't have common members, otherwise
+    # there would be duplicated declarations in generated Dart code.
+    # 2) Merged interface should be direct child of target interface, so the
+    # children of merged interface are not affected by the merge.
+    # As a consequence, target interface implementation and its direct children
+    # interface implementations should implement merged attribute accessors and
+    # operations. For example, SVGElement and Element implementation classes
+    # should implement HTMLElement.insertAdjacentElement(),
+    # HTMLElement.innerHTML, etc.
+    return self._data.merged_interface
+
+  def merged_into(self):
+    return self._data.merged_into
+
 
 class CallbackIDLTypeInfo(IDLTypeInfo):
   def __init__(self, idl_type, data):
@@ -904,6 +930,7 @@
 
 class TypeData(object):
   def __init__(self, clazz, dart_type=None, native_type=None,
+               merged_interface=None, merged_into=None,
                custom_to_dart=None, custom_to_native=None,
                conversion_includes=None,
                webcore_getter_name='getAttribute',
@@ -913,6 +940,8 @@
     self.clazz = clazz
     self.dart_type = dart_type
     self.native_type = native_type
+    self.merged_interface = merged_interface
+    self.merged_into = merged_into
     self.custom_to_dart = custom_to_dart
     self.custom_to_native = custom_to_native
     self.conversion_includes = conversion_includes
@@ -978,10 +1007,14 @@
     'DOMStringList': TypeData(clazz='Interface', dart_type='List<String>', custom_to_native=True),
     'DOMStringMap': TypeData(clazz='Interface', dart_type='Map<String, String>'),
     'DOMWindow': TypeData(clazz='Interface', custom_to_dart=True),
-    'Element': TypeData(clazz='Interface', custom_to_dart=True),
+    'Document': TypeData(clazz='Interface', merged_interface='HTMLDocument'),
+    'Element': TypeData(clazz='Interface', merged_interface='HTMLElement',
+        custom_to_dart=True),
     'EventListener': TypeData(clazz='Interface', custom_to_native=True),
     'EventTarget': TypeData(clazz='Interface', custom_to_native=True),
-    'HTMLElement': TypeData(clazz='Interface', custom_to_dart=True),
+    'HTMLDocument': TypeData(clazz='Interface', merged_into='Document'),
+    'HTMLElement': TypeData(clazz='Interface', merged_into='Element',
+        custom_to_dart=True),
     'IDBAny': TypeData(clazz='Interface', dart_type='Dynamic', custom_to_native=True),
     'IDBKey': TypeData(clazz='Interface', dart_type='Dynamic', custom_to_native=True),
     'MutationRecordArray': TypeData(clazz='Interface',  # C++ pass by pointer.
diff --git a/lib/html/scripts/systemhtml.py b/lib/html/scripts/systemhtml.py
index bedffc4..26fd788 100644
--- a/lib/html/scripts/systemhtml.py
+++ b/lib/html/scripts/systemhtml.py
@@ -35,23 +35,6 @@
     'WheelEvent.wheelDeltaY',
     ])
 
-# This map controls merging of interfaces in dart:html library.
-# All constants, attributes, and operations of merged interface (key) are
-# added to target interface (value). All references to the merged interface
-# (e.g. parameter types, return types, parent interfaces) are replaced with
-# target interface. There are two important restrictions:
-# 1) Merged and target interfaces shouldn't have common members, otherwise there
-# would be duplicated declarations in generated Dart code.
-# 2) Merged interface should be direct child of target interface, so the
-# children of merged interface are not affected by the merge.
-# As a consequence, target interface implementation and its direct children
-# interface implementations should implement merged attribute accessors and
-# operations. For example, SVGElement and Element implementation classes should
-# implement HTMLElement.insertAdjacentElement(), HTMLElement.innerHTML, etc.
-_merged_html_interfaces = {
-   'HTMLDocument': 'Document',
-   'HTMLElement': 'Element'
-}
 
 # Types that are accessible cross-frame in a limited fashion.
 # In these cases, the base type (e.g., Window) provides restricted access
@@ -221,6 +204,7 @@
     self._event_generator = event_generator
     self._interface = interface
     self._backend = backend
+    self._interface_type_info = self._type_registry.TypeInfo(self._interface.id)
     self._html_interface_name = options.renamer.RenameInterface(self._interface)
 
   def Generate(self):
@@ -243,9 +227,8 @@
     self._backend.GenerateCallback(info)
 
   def GenerateInterface(self):
-    interface_type_info = self._type_registry.TypeInfo(self._interface.id)
-    if (not self._interface.id in _merged_html_interfaces and
-        interface_type_info.has_generated_interface()):
+    if (self._interface_type_info.has_generated_interface() and
+        not self._interface_type_info.merged_into()):
       interface_emitter = self._library_emitter.FileEmitter(
           self._html_interface_name)
     else:
@@ -330,16 +313,7 @@
     self._type_comment_emitter.Emit("/// @domName $DOMNAME",
         DOMNAME=self._interface.doc_js_name)
 
-    if self._backend.HasImplementation():
-      if not self._interface.id in _merged_html_interfaces:
-        name = self._html_interface_name
-        basename = '%sImpl' % name
-      else:
-        basename = '%sImpl_Merged' % self._html_interface_name
-      implementation_emitter = self._library_emitter.FileEmitter(basename)
-    else:
-      implementation_emitter = emitter.Emitter()
-
+    implementation_emitter = self._ImplementationEmitter()
     base_class = self._backend.BaseClassName()
     interface_type_info = self._type_registry.TypeInfo(self._interface.id)
     implemented_interfaces = [interface_type_info.interface_name()] +\
@@ -383,10 +357,9 @@
     old_backend = self._backend
     if not self._backend.ImplementsMergedMembers():
       self._backend = HtmlGeneratorDummyBackend()
-    for merged_interface in _merged_html_interfaces:
-      if _merged_html_interfaces[merged_interface] == self._interface.id:
-        merged_interface = self._database.GetInterface(merged_interface)
-        self.AddMembers(merged_interface)
+    merged_interface = self._interface_type_info.merged_interface()
+    if merged_interface:
+      self.AddMembers(self._database.GetInterface(merged_interface))
     self._backend = old_backend
 
     self.AddMembers(self._interface)
@@ -534,6 +507,20 @@
                                TYPE=type,
                                VALUE=constant.value)
 
+  def _ImplementationEmitter(self):
+    if IsPureInterface(self._interface.id):
+      return emitter.Emitter()
+
+    if not self._interface_type_info.merged_into():
+      name = self._html_interface_name
+      basename = '%sImpl' % name
+    else:
+      if self._backend.ImplementsMergedMembers():
+        # Merged members are implemented in target interface implementation.
+        return emitter.Emitter()
+      basename = '%sImpl_Merged' % self._html_interface_name
+    return self._library_emitter.FileEmitter(basename)
+
   def _EmitEventGetter(self, events_interface, events_class):
     self._members_emitter.Emit(
         '\n  /**'
@@ -599,13 +586,10 @@
     self._database = options.database
     self._template_loader = options.templates
     self._type_registry = options.type_registry
+    self._interface_type_info = self._type_registry.TypeInfo(self._interface.id)
     self._html_interface_name = options.renamer.RenameInterface(self._interface)
     self._current_secondary_parent = None
 
-  def HasImplementation(self):
-    return not (IsPureInterface(self._interface.id) or
-                self._interface.id in _merged_html_interfaces)
-
   def ImplementationClassName(self):
     return self._ImplClassName(self._html_interface_name)
 
@@ -737,7 +721,7 @@
     #  html_name.  Two attributes with the same IDL name might not match if one
     #  is renamed.
     (super_attribute, super_attribute_interface) = self._FindShadowedAttribute(
-        attribute, _merged_html_interfaces)
+        attribute)
     if super_attribute:
       if read_only:
         if attribute.type.id == super_attribute.type.id:
@@ -1059,7 +1043,7 @@
     secure_name = SecureOutputType(self, type_name, True)
     return self._NarrowToImplementationType(secure_name)
 
-  def _FindShadowedAttribute(self, attr, merged_interfaces={}):
+  def _FindShadowedAttribute(self, attr):
     """Returns (attribute, superinterface) or (None, None)."""
     def FindInParent(interface):
       """Returns matching attribute in parent, or None."""
@@ -1071,20 +1055,18 @@
           return (None, None)
         if self._database.HasInterface(parent.type.id):
           interfaces_to_search_in = []
-          if parent.type.id in merged_interfaces:
+          parent_interface_name = parent.type.id
+          interfaces_to_search_in.append(parent_interface_name)
+          parent_type_info = self._type_registry.TypeInfo(parent_interface_name)
+          if parent_type_info.merged_into():
             # IDL parent was merged into another interface, which became a
             # parent interface in Dart.
-            interfaces_to_search_in.append(parent.type.id)
-            parent_interface_name = merged_interfaces[parent.type.id]
-          else:
-            parent_interface_name = parent.type.id
+            parent_interface_name = parent_type_info.merged_into()
+            interfaces_to_search_in.append(parent_interface_name)
+          elif parent_type_info.merged_interface():
+            # IDL parent has another interface that was merged into it.
+            interfaces_to_search_in.append(parent_type_info.merged_interface())
 
-          for interface_name in merged_interfaces:
-            if merged_interfaces[interface_name] == parent_interface_name:
-              # IDL parent has another interface that was merged into it.
-              interfaces_to_search_in.append(interface_name)
-
-          interfaces_to_search_in.append(parent_interface_name)
           for interface_name in interfaces_to_search_in:
             interface = self._database.GetInterface(interface_name)
             attr2 = FindMatchingAttribute(interface, attr)
diff --git a/lib/html/scripts/systemnative.py b/lib/html/scripts/systemnative.py
index 0eeffb5..187a272 100644
--- a/lib/html/scripts/systemnative.py
+++ b/lib/html/scripts/systemnative.py
@@ -22,9 +22,6 @@
     self._type_registry = options.type_registry
     self._html_interface_name = options.renamer.RenameInterface(self._interface)
 
-  def HasImplementation(self):
-    return not IsPureInterface(self._interface.id)
-
   def ImplementationClassName(self):
     return self._ImplClassName(self._interface.id)
 
@@ -114,7 +111,7 @@
 
   def StartInterface(self, memebers_emitter):
     # Create emitters for c++ implementation.
-    if self.HasImplementation():
+    if not IsPureInterface(self._interface.id):
       self._cpp_header_emitter = self._cpp_library_emitter.CreateHeaderEmitter(self._interface.id)
       self._cpp_impl_emitter = self._cpp_library_emitter.CreateSourceEmitter(self._interface.id)
     else:
diff --git a/lib/isolate/timer.dart b/lib/isolate/timer.dart
index 76f98a1..a90c2d0 100644
--- a/lib/isolate/timer.dart
+++ b/lib/isolate/timer.dart
@@ -2,23 +2,35 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-interface Timer default _TimerFactory {
+abstract class Timer {
   /**
    * Creates a new timer. The [callback] callback is invoked after
    * [milliSeconds] milliseconds.
    */
-  Timer(int milliSeconds, void callback(Timer timer));
+  factory Timer(int milliSeconds, void callback(Timer timer)) {
+    if (_factory == null) {
+      throw new UnsupportedOperationException("Timer interface not supported.");
+    }
+    return _factory(milliSeconds, callback, false);
+  }
 
   /**
    * Creates a new repeating timer. The [callback] is invoked every
    * [milliSeconds] millisecond until cancelled.
    */
-  Timer.repeating(int milliSeconds, void callback(Timer timer));
+  factory Timer.repeating(int milliSeconds, void callback(Timer timer)) {
+    if (_factory == null) {
+      throw new UnsupportedOperationException("Timer interface not supported.");
+    }
+    return _factory(milliSeconds, callback, true);
+  }
 
   /**
    * Cancels the timer.
    */
   void cancel();
+
+  static _TimerFactoryClosure _factory;
 }
 
 // TODO(ajohnsen): Patch timer once we have support for patching named
@@ -28,26 +40,6 @@
                                    void callback(Timer timer),
                                    bool repeating);
 
-// _TimerFactory provides a hook which allows various implementations of this
-// library to provide a concrete class for the Timer interface.
-class _TimerFactory {
-  factory Timer(int milliSeconds, void callback(Timer timer)) {
-    if (_factory == null) {
-      throw new UnsupportedOperationException("Timer interface not supported.");
-    }
-    return _factory(milliSeconds, callback, false);
-  }
-
-  factory Timer.repeating(int milliSeconds, void callback(Timer timer)) {
-    if (_factory == null) {
-      throw new UnsupportedOperationException("Timer interface not supported.");
-    }
-    return _factory(milliSeconds, callback, true);
-  }
-
-  static _TimerFactoryClosure _factory;
-}
-
 void _setTimerFactoryClosure(_TimerFactoryClosure closure) {
-  _TimerFactory._factory = closure;
+  Timer._factory = closure;
 }
diff --git a/lib/scalarlist/byte_arrays.dart b/lib/scalarlist/byte_arrays.dart
index 81e3f24..cb3dd12 100644
--- a/lib/scalarlist/byte_arrays.dart
+++ b/lib/scalarlist/byte_arrays.dart
@@ -25,6 +25,7 @@
    */
   int lengthInBytes();
 
+  // TODO(lrn): Change the signature to match String.substring.
   /**
    * Returns a [ByteArray] _view_ of a portion of this byte array.
    * The returned byte array consists of [length] bytes starting
@@ -33,8 +34,8 @@
    * changes to the returned byte array are visible in this byte array
    * and vice-versa.
    *
-   * Throws [IndexOutOfRangeException] if [start] is negative, or if
-   * `start + length` is greater than the length of this byte array.
+   * Throws [IndexOutOfRangeException] if [start] or [length] are negative, or
+   * if `start + length` is greater than the length of this byte array.
    *
    * Throws [ArgumentError] if [length] is negative.
    */
diff --git a/runtime/bin/bin.gypi b/runtime/bin/bin.gypi
index 45d808c..4aff04b 100644
--- a/runtime/bin/bin.gypi
+++ b/runtime/bin/bin.gypi
@@ -275,6 +275,7 @@
         'libdart_vm',
         'libjscre',
         'libdouble_conversion',
+        'generate_version_cc_file',
       ],
       'include_dirs': [
         '..',
@@ -284,6 +285,7 @@
         '../include/dart_debugger_api.h',
         '../vm/dart_api_impl.cc',
         '../vm/debugger_api_impl.cc',
+        '<(version_cc_file)',
       ],
     },
     {
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 864fb6a..d4fe179 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -40,11 +40,6 @@
 static bool use_script_snapshot = false;
 static File* snapshot_file = NULL;
 
-
-// Global state that stores a file name for flow graph debugging output.
-// NULL if no output is generated.
-static File* flow_graph_file = NULL;
-
 // Global state that indicates whether there is a debug breakpoint.
 // This pointer points into an argv buffer and does not need to be
 // free'd.
@@ -80,6 +75,16 @@
 }
 
 
+static bool has_version_option = false;
+static bool ProcessVersionOption(const char* arg) {
+  if (*arg != '\0') {
+    return false;
+  }
+  has_version_option = true;
+  return true;
+}
+
+
 static bool has_help_option = false;
 static bool ProcessHelpOption(const char* arg) {
   if (*arg != '\0') {
@@ -183,19 +188,12 @@
 }
 
 
-static bool ProcessFlowGraphOption(const char* flowgraph_option) {
-  ASSERT(flowgraph_option != NULL);
-  flow_graph_file = File::Open("flowgraph.cfg", File::kWriteTruncate);
-  ASSERT(flow_graph_file != NULL);
-  return true;
-}
-
-
 static struct {
   const char* option_name;
   bool (*process)(const char* option);
 } main_options[] = {
   // Standard options shared with dart2js.
+  { "--version", ProcessVersionOption },
   { "--help", ProcessHelpOption },
   { "-h", ProcessHelpOption },
   { "--verbose", ProcessVerboseOption },
@@ -206,7 +204,6 @@
   { "--break_at=", ProcessBreakpointOption },
   { "--compile_all", ProcessCompileAllOption },
   { "--debug", ProcessDebugOption },
-  { "--generate_flow_graph", ProcessFlowGraphOption },
   { "--generate_perf_events_symbols", ProcessPerfEventsOption },
   { "--generate_pprof_symbols=", ProcessPprofOption },
   { "--use_script_snapshot=", ProcessScriptSnapshotOption },
@@ -235,12 +232,6 @@
 }
 
 
-static void WriteToFlowGraphFile(const char* buffer, int64_t num_bytes) {
-  ASSERT(flow_graph_file != NULL);
-  flow_graph_file->WriteFully(buffer, num_bytes);
-}
-
-
 // Parse out the command line arguments. Returns -1 if the arguments
 // are incorrect, 0 otherwise.
 static int ParseArguments(int argc,
@@ -287,10 +278,6 @@
     Dart_InitPprofSupport();
   }
 
-  if (flow_graph_file != NULL) {
-    Dart_InitFlowGraphPrinting(&WriteToFlowGraphFile);
-  }
-
   // Get the script name.
   if (i < argc) {
     *script_name = argv[i];
@@ -508,6 +495,11 @@
 }
 
 
+static void PrintVersion() {
+  fprintf(stderr, "Dart VM version: %s\n", Dart_VersionString());
+}
+
+
 static void PrintUsage() {
   fprintf(stderr,
       "Usage: dart [<vm-flags>] <dart-script-file> [<dart-options>]\n"
@@ -518,14 +510,18 @@
     fprintf(stderr,
 "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,
 "Supported options:\n"
-"--checked \n"
+"--checked\n"
 "  Insert runtime type checks and enable assertions (checked mode).\n"
 "\n"
+"--version\n"
+"  Print the VM version.\n"
+"\n"
 "--help\n"
 "  Display this message (add --verbose for information about all VM options).\n"
 "\n"
@@ -648,7 +644,13 @@
                      &script_name,
                      &dart_options,
                      &print_flags_seen) < 0) {
-    if (print_flags_seen) {
+    if (has_help_option) {
+      PrintUsage();
+      return 0;
+    } else if (has_version_option) {
+      PrintVersion();
+      return 0;
+    } else if (print_flags_seen) {
       // Will set the VM flags, print them out and then we exit as no
       // script was specified on the command line.
       Dart_SetVMFlags(vm_options.count(), vm_options.arguments());
@@ -659,11 +661,6 @@
     }
   }
 
-  if (has_help_option) {
-    PrintUsage();
-    return 0;
-  }
-
   Dart_SetVMFlags(vm_options.count(), vm_options.arguments());
 
   // Initialize the Dart VM.
diff --git a/runtime/dart-runtime.gyp b/runtime/dart-runtime.gyp
index a2d79e0..45548de 100644
--- a/runtime/dart-runtime.gyp
+++ b/runtime/dart-runtime.gyp
@@ -11,6 +11,10 @@
     'tools/gyp/runtime-configurations.gypi',
     '../tools/gyp/source_filter.gypi',
   ],
+  'variables': {
+    'version_in_cc_file': 'vm/version_in.cc',
+    'version_cc_file': '<(SHARED_INTERMEDIATE_DIR)/version.cc',
+  },
   'targets': [
     {
       'target_name': 'libdart',
@@ -20,6 +24,7 @@
         'libdart_vm',
         'libjscre',
         'libdouble_conversion',
+        'generate_version_cc_file',
       ],
       'include_dirs': [
         '.',
@@ -29,6 +34,8 @@
         'include/dart_debugger_api.h',
         'vm/dart_api_impl.cc',
         'vm/debugger_api_impl.cc',
+        'vm/version.h',
+        '<(version_cc_file)',
       ],
       'direct_dependent_settings': {
         'include_dirs': [
@@ -46,6 +53,7 @@
         'libdart_vm',
         'libjscre',
         'libdouble_conversion',
+        'generate_version_cc_file',
       ],
       'include_dirs': [
         '.',
@@ -55,6 +63,8 @@
         'include/dart_debugger_api.h',
         'vm/dart_api_impl.cc',
         'vm/debugger_api_impl.cc',
+        'vm/version.h',
+        '<(version_cc_file)',
       ],
       'defines': [
         'DART_SHARED_LIB',
@@ -65,5 +75,29 @@
         ],
       },
     },
+    {
+      'target_name': 'generate_version_cc_file',
+      'type': 'none',
+      'actions': [
+        {
+          'action_name': 'generate_version_cc',
+          'inputs': [
+            'tools/make_version.py',
+            '../tools/VERSION',
+            '<(version_in_cc_file)',
+          ],
+          'outputs': [
+            '<(version_cc_file)',
+          ],
+          'action': [
+            'python',
+            'tools/make_version.py',
+            '--output', '<(version_cc_file)',
+            '--input', '<(version_in_cc_file)',
+            '--version', '../tools/VERSION',
+          ],
+        },
+      ],
+    },
   ],
 }
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index bf087c3..5490dfa 100755
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -557,6 +557,15 @@
 // --- Initialization and Globals ---
 
 /**
+ * Gets the version string for the Dart VM.
+ *
+ * The version of the Dart VM can be accessed without initializing the VM.
+ *
+ * \return The version string for the embedded Dart VM.
+ */
+DART_EXPORT const char* Dart_VersionString();
+
+/**
  * An isolate creation and initialization callback function.
  *
  * This callback, provided by the embedder, is called when the vm
@@ -1970,12 +1979,6 @@
                                            int number_of_arguments,
                                            Dart_Handle* arguments);
 
-// DEPRECATED: The API below is a temporary hack.
-DART_EXPORT int64_t Dart_ClosureSmrck(Dart_Handle object);
-
-// DEPRECATED: The API below is a temporary hack.
-DART_EXPORT void Dart_ClosureSetSmrck(Dart_Handle object, int64_t value);
-
 // --- Classes and Interfaces ---
 
 /**
@@ -2726,9 +2729,6 @@
 // Support for generating symbol maps for use by the Linux perf tool.
 DART_EXPORT void Dart_InitPerfEventsSupport(Dart_FileWriterFunction function);
 
-// Support for generating flow graph compiler debugging output into a file.
-DART_EXPORT void Dart_InitFlowGraphPrinting(Dart_FileWriterFunction function);
-
 // --- Peers ---
 
 /**
diff --git a/runtime/lib/byte_array.dart b/runtime/lib/byte_array.dart
index a6efae2..feadf0e 100644
--- a/runtime/lib/byte_array.dart
+++ b/runtime/lib/byte_array.dart
@@ -1513,8 +1513,11 @@
   }
 
   ByteArray subByteArray([int start = 0, int length]) {
+    if (start is! int) throw new ArgumentError("start is not an int");
     if (length === null) {
-      length = this.lengthInBytes();
+      length = this.lengthInBytes() - start;
+    } else if (length is! int) {
+      throw new ArgumentError("length is not an int");
     }
     return new _ByteArrayView(_array, _offset + start, length);
   }
diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc
index 921368a..3c59c5c 100644
--- a/runtime/lib/isolate.cc
+++ b/runtime/lib/isolate.cc
@@ -398,10 +398,19 @@
 
 
 DEFINE_NATIVE_ENTRY(isolate_spawnFunction, 1) {
-  GET_NATIVE_ARGUMENT(Closure, closure, arguments->At(0));
-  const Function& func = Function::Handle(closure.function());
-  const Class& cls = Class::Handle(func.Owner());
-  if (!func.IsClosureFunction() || !func.is_static() || !cls.IsTopLevel()) {
+  GET_NATIVE_ARGUMENT(Instance, closure, arguments->At(0));
+  bool throw_exception = false;
+  Function& func = Function::Handle();
+  if (closure.IsClosure()) {
+    func ^= Closure::function(closure);
+    const Class& cls = Class::Handle(func.Owner());
+    if (!func.IsClosureFunction() || !func.is_static() || !cls.IsTopLevel()) {
+      throw_exception = true;
+    }
+  } else {
+    throw_exception = true;
+  }
+  if (throw_exception) {
     const String& msg = String::Handle(String::New(
         "spawnFunction expects to be passed a closure to a top-level static "
         "function"));
@@ -409,7 +418,7 @@
   }
 
 #if defined(DEBUG)
-  const Context& ctx = Context::Handle(closure.context());
+  const Context& ctx = Context::Handle(Closure::context(closure));
   ASSERT(ctx.num_variables() == 0);
 #endif
 
diff --git a/runtime/tools/make_version.py b/runtime/tools/make_version.py
new file mode 100644
index 0000000..73cfbe1
--- /dev/null
+++ b/runtime/tools/make_version.py
@@ -0,0 +1,100 @@
+# 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.
+#
+# This python script creates a version string in a C++ file.
+
+import os
+import sys
+import subprocess
+import platform
+import getpass
+from os.path import join
+import time
+from optparse import OptionParser
+
+def getVersionPart(version_file, part):
+  proc = subprocess.Popen(['awk',
+                           '$1 == "%s" {print $2}' % (part),
+                           version_file],
+                          stdout=subprocess.PIPE,
+                          stderr=subprocess.STDOUT)
+  return proc.communicate()[0].split('\n')[0]
+
+def getRevision():
+  is_svn = True
+  if os.path.exists('.svn'):
+    cmd = ['svn', 'info']
+  else:
+    cmd = ['git', 'svn', 'info']
+  try:
+    proc = subprocess.Popen(cmd,
+                            stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+    return proc.communicate()[0].split('\n')[4].split(' ')[1]
+  except Exception:
+    # If we can't get any revision info (due to lack of tooling) return ''.
+    return ''
+
+
+def makeVersionString(version_file):
+  id = platform.system()
+  if id == 'Windows' or id == 'Microsoft':
+    return '0.0.0.0'
+  major = getVersionPart(version_file, 'MAJOR')
+  minor = getVersionPart(version_file, 'MINOR')
+  build = getVersionPart(version_file, 'BUILD')
+  patch = getVersionPart(version_file, 'PATCH')
+  revision = getRevision()
+  user = getpass.getuser()
+  return '%s.%s.%s.%s_%s_%s' % (major, minor, build, patch, revision, user)
+
+def makeFile(output_file, input_file, version_file):
+  version_cc_text = open(input_file).read()
+  version_cc_text = version_cc_text.replace("{{VERSION_STR}}",
+                                            makeVersionString(version_file))
+  version_cc_text = version_cc_text.replace("{{BUILD_TIME}}",
+                                            time.ctime(time.time()))
+  open(output_file, 'w').write(version_cc_text)
+  return True
+
+
+def main(args):
+  try:
+    # Parse input.
+    parser = OptionParser()
+    parser.add_option("--output",
+                      action="store", type="string",
+                      help="output file name")
+    parser.add_option("--input",
+                      action="store", type="string",
+                      help="input template file")
+    parser.add_option("--version",
+                      action="store", type="string",
+                      help="version file")
+
+    (options, args) = parser.parse_args()
+    if not options.output:
+      sys.stderr.write('--output not specified\n')
+      return -1
+    if not len(options.input):
+      sys.stderr.write('--input not specified\n')
+      return -1
+
+    files = [ ]
+    for arg in args:
+      files.append(arg)
+
+    if not makeFile(options.output,
+                    options.input,
+                    options.version):
+      return -1
+
+    return 0
+  except Exception, inst:
+    sys.stderr.write('make_version.py exception\n')
+    sys.stderr.write(str(inst))
+    sys.stderr.write('\n')
+    return -1
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv))
diff --git a/runtime/vm/assembler_macros_ia32.cc b/runtime/vm/assembler_macros_ia32.cc
index 58cf709..38ebf3e 100644
--- a/runtime/vm/assembler_macros_ia32.cc
+++ b/runtime/vm/assembler_macros_ia32.cc
@@ -64,20 +64,6 @@
 }
 
 
-void AssemblerMacros::EnterDartLeafFrame(Assembler* assembler,
-                                         intptr_t frame_size) {
-  __ EnterFrame(0);
-  Label dart_entry;
-  // Leave room for the saved PC, it will be filled in lazily, leave
-  // uninitialized.
-  __ subl(ESP, Immediate(frame_size + kWordSize));
-#if defined(DEBUG)
-  // Store an invalid object in saved PC slot.
-  __ movl(Address(EBP, -kWordSize), Immediate(kHeapObjectTag));
-#endif
-}
-
-
 void AssemblerMacros::EnterStubFrame(Assembler* assembler) {
   __ EnterFrame(0);
   __ pushl(Immediate(0));  // Push 0 in the saved PC area for stub frames.
diff --git a/runtime/vm/assembler_macros_ia32.h b/runtime/vm/assembler_macros_ia32.h
index ad3819b..4d185f9 100644
--- a/runtime/vm/assembler_macros_ia32.h
+++ b/runtime/vm/assembler_macros_ia32.h
@@ -50,8 +50,6 @@
   //   L: <code to adjust saved pc if there is any intrinsification code>
   //   .....
   static void EnterDartFrame(Assembler* assembler, intptr_t frame_size);
-  // Populates pc local slot lazily.
-  static void EnterDartLeafFrame(Assembler* assembler, intptr_t frame_size);
 
   // Set up a stub frame so that the stack traversal code can easily identify
   // a stub frame.
diff --git a/runtime/vm/assembler_macros_x64.cc b/runtime/vm/assembler_macros_x64.cc
index fc01baf..0731cb5 100644
--- a/runtime/vm/assembler_macros_x64.cc
+++ b/runtime/vm/assembler_macros_x64.cc
@@ -67,20 +67,6 @@
 }
 
 
-void AssemblerMacros::EnterDartLeafFrame(Assembler* assembler,
-                                         intptr_t frame_size) {
-  __ EnterFrame(0);
-  Label dart_entry;
-  // Leave room for the saved PC, it will be filled in lazily, leave
-  // uninitialized.
-  __ subq(RSP, Immediate(frame_size + kWordSize));
-#if defined(DEBUG)
-  // Store an invalid object in saved PC slot.
-  __ movq(Address(RBP, -kWordSize), Immediate(kHeapObjectTag));
-#endif
-}
-
-
 void AssemblerMacros::EnterStubFrame(Assembler* assembler) {
   __ EnterFrame(0);
   __ pushq(Immediate(0));  // Push 0 in the saved PC area for stub frames.
diff --git a/runtime/vm/assembler_macros_x64.h b/runtime/vm/assembler_macros_x64.h
index acf5f71..a6912cf 100644
--- a/runtime/vm/assembler_macros_x64.h
+++ b/runtime/vm/assembler_macros_x64.h
@@ -50,8 +50,6 @@
   //   L: <code to adjust saved pc if there is any intrinsification code>
   //   .....
   static void EnterDartFrame(Assembler* assembler, intptr_t frame_size);
-  // Populates pc local slot lazily.
-  static void EnterDartLeafFrame(Assembler* assembler, intptr_t frame_size);
 
   // Set up a stub frame so that the stack traversal code can easily identify
   // a stub frame.
diff --git a/runtime/vm/ast.cc b/runtime/vm/ast.cc
index 58f6935..b70119d 100644
--- a/runtime/vm/ast.cc
+++ b/runtime/vm/ast.cc
@@ -286,8 +286,8 @@
 
 const Instance* ClosureNode::EvalConstExpr() const {
   if (function().IsImplicitStaticClosureFunction()) {
-    // Return a value that represents a closure. Only the type is relevant.
-    return &Closure::Handle();
+    // Return a value that represents an instance. Only the type is relevant.
+    return &Instance::Handle();
   }
   return NULL;
 }
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 7c2dd36..aace6ca 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -57,12 +57,14 @@
     for (intptr_t i = 0; i < class_array.Length(); i++) {
       cls ^= class_array.At(i);
       if (FLAG_trace_class_finalization) {
-        OS::Print("Resolving super and default: %s\n", cls.ToCString());
+        OS::Print("Resolving super and interfaces: %s\n", cls.ToCString());
       }
       ResolveSuperType(cls);
       if (cls.is_interface()) {
         ResolveFactoryClass(cls);
       }
+      GrowableArray<intptr_t> visited_interfaces;
+      ResolveInterfaces(cls, &visited_interfaces);
     }
     // Finalize all classes.
     for (intptr_t i = 0; i < class_array.Length(); i++) {
@@ -621,8 +623,6 @@
     FinalizationKind finalization) {
   ASSERT(arguments.Length() >= cls.NumTypeArguments());
   if (!cls.is_finalized()) {
-    GrowableArray<intptr_t> visited_interfaces;
-    ResolveInterfaces(cls, &visited_interfaces);
     FinalizeTypeParameters(cls);
   }
   Type& super_type = Type::Handle(cls.super_type());
@@ -730,8 +730,6 @@
   // parameters of the type class must be finalized.
   Class& type_class = Class::Handle(parameterized_type.type_class());
   if (!type_class.is_finalized()) {
-    GrowableArray<intptr_t> visited_interfaces;
-    ResolveInterfaces(type_class, &visited_interfaces);
     FinalizeTypeParameters(type_class);
   }
 
@@ -1186,8 +1184,6 @@
                 "class '%s' has a cycle in its superclass relationship",
                 name.ToCString());
   }
-  GrowableArray<intptr_t> visited_interfaces;
-  ResolveInterfaces(cls, &visited_interfaces);
   // Finalize super class.
   const Class& super_class = Class::Handle(cls.SuperClass());
   if (!super_class.IsNull()) {
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index f8e7c37..61fc71b 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -279,8 +279,8 @@
   // runtime.
   const Context& context = Context::Handle(isolate->top_context());
   ASSERT(!context.IsNull());
-  const Closure& closure = Closure::Handle(Closure::New(function, context));
-  closure.SetTypeArguments(type_arguments);
+  const Instance& closure = Instance::Handle(Closure::New(function, context));
+  Closure::SetTypeArguments(closure, type_arguments);
   arguments.SetReturn(closure);
 }
 
@@ -297,7 +297,7 @@
   ASSERT(!function.IsNull());
   ASSERT(function.IsImplicitStaticClosureFunction());
   const Context& context = Context::Handle(object_store->empty_context());
-  arguments.SetReturn(Closure::Handle(Closure::New(function, context)));
+  arguments.SetReturn(Instance::Handle(Closure::New(function, context)));
 }
 
 
@@ -318,8 +318,8 @@
   Context& context = Context::Handle();
   context = Context::New(1);
   context.SetAt(0, receiver);
-  const Closure& closure = Closure::Handle(Closure::New(function, context));
-  closure.SetTypeArguments(type_arguments);
+  const Instance& closure = Instance::Handle(Closure::New(function, context));
+  Closure::SetTypeArguments(closure, type_arguments);
   arguments.SetReturn(closure);
 }
 
@@ -1057,7 +1057,7 @@
   const Instance& receiver = Instance::CheckedHandle(arguments.At(0));
   const ICData& ic_data = ICData::CheckedHandle(arguments.At(1));
   const String& original_function_name = String::Handle(ic_data.target_name());
-  Closure& closure = Closure::Handle();
+  Instance& closure = Instance::Handle();
   if (!Field::IsGetterName(original_function_name)) {
     // This is not a getter so can't be the case where we are trying to
     // create an implicit closure of an instance function.
@@ -1155,10 +1155,10 @@
 DEFINE_RUNTIME_ENTRY(InvokeImplicitClosureFunction, 3) {
   ASSERT(arguments.Count() ==
          kInvokeImplicitClosureFunctionRuntimeEntry.argument_count());
-  const Closure& closure = Closure::CheckedHandle(arguments.At(0));
+  const Instance& closure = Instance::CheckedHandle(arguments.At(0));
   const Array& arg_descriptor = Array::CheckedHandle(arguments.At(1));
   const Array& func_arguments = Array::CheckedHandle(arguments.At(2));
-  const Function& function = Function::Handle(closure.function());
+  const Function& function = Function::Handle(Closure::function(closure));
   ASSERT(!function.IsNull());
   if (!function.HasCode()) {
     const Error& error = Error::Handle(Compiler::CompileFunction(function));
@@ -1166,7 +1166,7 @@
       Exceptions::PropagateError(error);
     }
   }
-  const Context& context = Context::Handle(closure.context());
+  const Context& context = Context::Handle(Closure::context(closure));
   const Code& code = Code::Handle(function.CurrentCode());
   ASSERT(!code.IsNull());
   const Instructions& instrs = Instructions::Handle(code.instructions());
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index 188b16b..91bb459 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -165,11 +165,6 @@
         FlowGraphPrinter printer(*flow_graph);
         printer.PrintBlocks();
       }
-      if (Dart::flow_graph_writer() != NULL) {
-        // Write flow graph to file.
-        FlowGraphVisualizer printer(*flow_graph);
-        printer.PrintFunction();
-      }
 
       if (optimized) {
         flow_graph->ComputeUseLists();
@@ -244,17 +239,10 @@
       }
     }
 
-    bool is_leaf = false;
-    if (optimized) {
-      FlowGraphAnalyzer analyzer(*flow_graph);
-      analyzer.Analyze();
-      is_leaf = analyzer.is_leaf();
-    }
     Assembler assembler;
     FlowGraphCompiler graph_compiler(&assembler,
                                      *flow_graph,
-                                     optimized,
-                                     is_leaf);
+                                     optimized);
     {
       TimerScope timer(FLAG_compiler_stats,
                        &CompilerStats::graphcompiler_timer,
@@ -266,7 +254,8 @@
                        &CompilerStats::codefinalizer_timer,
                        isolate);
       const Function& function = parsed_function.function();
-      const Code& code = Code::Handle(Code::FinalizeCode(function, &assembler));
+      const Code& code = Code::Handle(
+          Code::FinalizeCode(function, &assembler, optimized));
       code.set_is_optimized(optimized);
       graph_compiler.FinalizePcDescriptors(code);
       graph_compiler.FinalizeDeoptInfo(code);
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 332a3c6..0b8cdd4 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -28,6 +28,7 @@
 #include "vm/timer.h"
 #include "vm/unicode.h"
 #include "vm/verifier.h"
+#include "vm/version.h"
 
 namespace dart {
 
@@ -729,6 +730,9 @@
 
 // --- Initialization and Globals ---
 
+DART_EXPORT const char* Dart_VersionString() {
+  return Version::String();
+}
 
 DART_EXPORT bool Dart_Initialize(Dart_IsolateCreateCallback create,
                                  Dart_IsolateInterruptCallback interrupt,
@@ -2380,21 +2384,22 @@
   // different signature classes for closures.
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
-  const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object));
-  return obj.IsClosure();
+  const Instance& closure_obj = Api::UnwrapInstanceHandle(isolate, object);
+  return (!closure_obj.IsNull() && closure_obj.IsClosure());
 }
 
 
 DART_EXPORT Dart_Handle Dart_ClosureFunction(Dart_Handle closure) {
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
-  const Closure& closure_obj = Api::UnwrapClosureHandle(isolate, closure);
-  if (closure_obj.IsNull()) {
-    RETURN_TYPE_ERROR(isolate, closure, Closure);
+  const Instance& closure_obj = Api::UnwrapInstanceHandle(isolate, closure);
+  if (closure_obj.IsNull() || !closure_obj.IsClosure()) {
+    RETURN_TYPE_ERROR(isolate, closure, Instance);
   }
+
   ASSERT(ClassFinalizer::AllClassesFinalized());
 
-  RawFunction* rf = closure_obj.function();
+  RawFunction* rf = Closure::function(closure_obj);
   return Api::NewHandle(isolate, rf);
 }
 
@@ -2404,9 +2409,9 @@
                                            Dart_Handle* arguments) {
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
-  const Closure& closure_obj = Api::UnwrapClosureHandle(isolate, closure);
-  if (closure_obj.IsNull()) {
-    RETURN_TYPE_ERROR(isolate, closure, Closure);
+  const Instance& closure_obj = Api::UnwrapInstanceHandle(isolate, closure);
+  if (closure_obj.IsNull() || !closure_obj.IsClosure()) {
+    RETURN_TYPE_ERROR(isolate, closure, Instance);
   }
   if (number_of_arguments < 0) {
     return Api::NewError(
@@ -2432,26 +2437,6 @@
 }
 
 
-DART_EXPORT int64_t Dart_ClosureSmrck(Dart_Handle object) {
-  Isolate* isolate = Isolate::Current();
-  DARTSCOPE(isolate);
-  const Closure& obj =
-      Closure::CheckedHandle(isolate, Api::UnwrapHandle(object));
-  const Integer& smrck = Integer::Handle(isolate, obj.smrck());
-  return smrck.IsNull() ? 0 : smrck.AsInt64Value();
-}
-
-
-DART_EXPORT void Dart_ClosureSetSmrck(Dart_Handle object, int64_t value) {
-  Isolate* isolate = Isolate::Current();
-  DARTSCOPE(isolate);
-  const Closure& obj =
-      Closure::CheckedHandle(isolate, Api::UnwrapHandle(object));
-  const Integer& smrck = Integer::Handle(isolate, Integer::New(value));
-  obj.set_smrck(smrck);
-}
-
-
 // --- Classes and Interfaces ---
 
 
@@ -4457,11 +4442,6 @@
 }
 
 
-DART_EXPORT void Dart_InitFlowGraphPrinting(Dart_FileWriterFunction function) {
-  Dart::set_flow_graph_writer(function);
-}
-
-
 // --- Peer support ---
 
 
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index bc0a96a..476dd8c 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -83,15 +83,15 @@
 
 
 RawObject* DartEntry::InvokeClosure(
-    const Closure& closure,
+    const Instance& closure,
     const GrowableArray<const Object*>& arguments,
     const Array& optional_arguments_names) {
   // Get the entrypoint corresponding to the closure specified, this
   // will result in a compilation of the closure if it is not already
   // compiled.
   ASSERT(Class::Handle(closure.clazz()).signature_function() != Object::null());
-  const Function& function = Function::Handle(closure.function());
-  const Context& context = Context::Handle(closure.context());
+  const Function& function = Function::Handle(Closure::function(closure));
+  const Context& context = Context::Handle(Closure::context(closure));
   ASSERT(!function.IsNull());
   if (!function.HasCode()) {
     const Error& error = Error::Handle(Compiler::CompileFunction(function));
diff --git a/runtime/vm/dart_entry.h b/runtime/vm/dart_entry.h
index 2d26fe8..8e130dd 100644
--- a/runtime/vm/dart_entry.h
+++ b/runtime/vm/dart_entry.h
@@ -51,7 +51,7 @@
   // Invoke the specified closure object.
   // On success, returns a RawInstance.  On failure, a RawError.
   static RawObject* InvokeClosure(
-      const Closure& closure,
+      const Instance& closure,
       const GrowableArray<const Object*>& arguments,
       const Array& optional_arguments_names);
 
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index c84d824..ad81e2f 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -139,8 +139,7 @@
 
 FlowGraphCompiler::FlowGraphCompiler(Assembler* assembler,
                                      const FlowGraph& flow_graph,
-                                     bool is_optimizing,
-                                     bool is_leaf)
+                                     bool is_optimizing)
     : assembler_(assembler),
       parsed_function_(flow_graph.parsed_function()),
       block_order_(flow_graph.reverse_postorder()),
@@ -153,7 +152,6 @@
       deopt_infos_(),
       object_table_(GrowableObjectArray::Handle(GrowableObjectArray::New())),
       is_optimizing_(is_optimizing),
-      is_dart_leaf_(is_leaf),
       bool_true_(Bool::ZoneHandle(Bool::True())),
       bool_false_(Bool::ZoneHandle(Bool::False())),
       double_class_(Class::ZoneHandle(
@@ -173,13 +171,6 @@
 }
 
 
-bool FlowGraphCompiler::IsLeaf() const {
-  return is_dart_leaf_ &&
-         !parsed_function_.function().IsClosureFunction() &&
-         (parsed_function().num_copied_params() == 0);
-}
-
-
 bool FlowGraphCompiler::HasFinally() const {
   return parsed_function().function().has_finally();
 }
@@ -482,7 +473,6 @@
     const Array& argument_names,
     intptr_t checked_argument_count,
     LocationSummary* locs) {
-  ASSERT(!IsLeaf());
   ICData& ic_data =
       ICData::ZoneHandle(ICData::New(parsed_function().function(),
                                      function_name,
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index e4b3663..b5ce752 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -44,18 +44,6 @@
 
   ASSERT(deoptimization_env() != NULL);
 
-  if (compiler->IsLeaf()) {
-    Label L;
-    __ pushl(EAX);  // Preserve EAX.
-    __ call(&L);
-    const intptr_t offset = assem->CodeSize();
-    __ Bind(&L);
-    __ popl(EAX);
-    __ subl(EAX,
-        Immediate(offset - AssemblerMacros::kOffsetOfSavedPCfromEntrypoint));
-    __ movl(Address(EBP, -kWordSize), EAX);
-    __ popl(EAX);
-  }
   __ call(&StubCode::DeoptimizeLabel());
   set_pc_offset(assem->CodeSize());
 #undef __
@@ -825,7 +813,6 @@
                          Isolate::kNoDeoptId,
                          0);  // No token position.
   } else {
-    ASSERT(!IsLeaf());
     // Invoke noSuchMethod function.
     const int kNumArgsChecked = 1;
     ICData& ic_data = ICData::ZoneHandle();
@@ -933,11 +920,7 @@
   const int num_copied_params = parsed_function().num_copied_params();
   const int num_locals = parsed_function().num_stack_locals();
   __ Comment("Enter frame");
-  if (IsLeaf()) {
-    AssemblerMacros::EnterDartLeafFrame(assembler(), (StackSize() * kWordSize));
-  } else {
-    AssemblerMacros::EnterDartFrame(assembler(), (StackSize() * kWordSize));
-  }
+  AssemblerMacros::EnterDartFrame(assembler(), (StackSize() * kWordSize));
 
   // For optimized code, keep a bitmap of the frame in order to build
   // stackmaps for GC safepoints in the prologue.
@@ -1041,7 +1024,6 @@
                                      const ExternalLabel* label,
                                      PcDescriptors::Kind kind,
                                      LocationSummary* locs) {
-  ASSERT(!IsLeaf());
   __ call(label);
   AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos);
   RecordSafepoint(locs);
@@ -1053,7 +1035,6 @@
                                          const ExternalLabel* label,
                                          PcDescriptors::Kind kind,
                                          LocationSummary* locs) {
-  ASSERT(!IsLeaf());
   __ call(label);
   AddCurrentDescriptor(kind, deopt_id, token_pos);
   RecordSafepoint(locs);
@@ -1074,7 +1055,6 @@
 void FlowGraphCompiler::GenerateCallRuntime(intptr_t token_pos,
                                             const RuntimeEntry& entry,
                                             LocationSummary* locs) {
-  ASSERT(!IsLeaf());
   __ CallRuntime(entry);
   AddCurrentDescriptor(PcDescriptors::kOther, Isolate::kNoDeoptId, token_pos);
   RecordSafepoint(locs);
@@ -1088,7 +1068,6 @@
                                          intptr_t deopt_id,
                                          intptr_t token_pos,
                                          LocationSummary* locs) {
-  ASSERT(!IsLeaf());
   __ LoadObject(ECX, ic_data);
   __ LoadObject(EDX, arguments_descriptor);
   GenerateDartCall(deopt_id,
@@ -1106,7 +1085,6 @@
                                        intptr_t deopt_id,
                                        intptr_t token_pos,
                                        LocationSummary* locs) {
-  ASSERT(!IsLeaf());
   __ LoadObject(ECX, function);
   __ LoadObject(EDX, arguments_descriptor);
   if (function.HasCode()) {
diff --git a/runtime/vm/flow_graph_compiler_ia32.h b/runtime/vm/flow_graph_compiler_ia32.h
index 57c3f55..b5d3043 100644
--- a/runtime/vm/flow_graph_compiler_ia32.h
+++ b/runtime/vm/flow_graph_compiler_ia32.h
@@ -27,8 +27,7 @@
  public:
   FlowGraphCompiler(Assembler* assembler,
                     const FlowGraph& flow_graph,
-                    bool is_optimizing,
-                    bool is_leaf);
+                    bool is_optimizing);
 
   ~FlowGraphCompiler();
 
@@ -207,10 +206,6 @@
 
   static const int kLocalsOffsetFromFP = (-1 * kWordSize);
 
-  // Returns true if the generated code does not call other Dart code or
-  // runtime. Only deoptimization is allowed to occur. Closures are not leaf.
-  bool IsLeaf() const;
-
   static Condition FlipCondition(Condition condition);
 
   static bool EvaluateCondition(Condition condition, intptr_t l, intptr_t r);
@@ -311,7 +306,6 @@
   GrowableArray<SlowPathCode*> slow_path_code_;
   const GrowableObjectArray& object_table_;
   const bool is_optimizing_;
-  const bool is_dart_leaf_;
 
   const Bool& bool_true_;
   const Bool& bool_false_;
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index fea44cc..0c9e1aa 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -43,21 +43,6 @@
 
   ASSERT(deoptimization_env() != NULL);
 
-  if (compiler->IsLeaf()) {
-    __ Comment("Leaf method, lazy PC marker setup");
-    // TODO(srdjan): Can we use TMP instead of RAX? We must guarantee that
-    // TMP is never part of deoptimization environment.
-    __ pushq(RAX);  // Preserve RAX.
-    Label L;
-    __ call(&L);
-    const intptr_t offset = assem->CodeSize();
-    __ Bind(&L);
-    __ popq(RAX);
-    __ subq(RAX,
-        Immediate(offset - AssemblerMacros::kOffsetOfSavedPCfromEntrypoint));
-    __ movq(Address(RBP, -kWordSize), RAX);
-    __ popq(RAX);  // Restore RAX.
-  }
   __ call(&StubCode::DeoptimizeLabel());
   set_pc_offset(assem->CodeSize());
   __ int3();
@@ -831,7 +816,6 @@
                          Isolate::kNoDeoptId,
                          0);  // No token position.
   } else {
-    ASSERT(!IsLeaf());
     // Invoke noSuchMethod function.
     const int kNumArgsChecked = 1;
     ICData& ic_data = ICData::ZoneHandle();
@@ -940,11 +924,7 @@
   const int num_copied_params = parsed_function().num_copied_params();
   const int num_locals = parsed_function().num_stack_locals();
   __ Comment("Enter frame");
-  if (IsLeaf()) {
-    AssemblerMacros::EnterDartLeafFrame(assembler(), (StackSize() * kWordSize));
-  } else {
-    AssemblerMacros::EnterDartFrame(assembler(), (StackSize() * kWordSize));
-  }
+  AssemblerMacros::EnterDartFrame(assembler(), (StackSize() * kWordSize));
 
   // For optimized code, keep a bitmap of the frame in order to build
   // stackmaps for GC safepoints in the prologue.
@@ -1049,7 +1029,6 @@
                                      const ExternalLabel* label,
                                      PcDescriptors::Kind kind,
                                      LocationSummary* locs) {
-  ASSERT(!IsLeaf());
   __ call(label);
   AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos);
   RecordSafepoint(locs);
@@ -1061,7 +1040,6 @@
                                          const ExternalLabel* label,
                                          PcDescriptors::Kind kind,
                                          LocationSummary* locs) {
-  ASSERT(!IsLeaf());
   __ call(label);
   AddCurrentDescriptor(kind, deopt_id, token_pos);
   RecordSafepoint(locs);
@@ -1082,7 +1060,6 @@
 void FlowGraphCompiler::GenerateCallRuntime(intptr_t token_pos,
                                             const RuntimeEntry& entry,
                                             LocationSummary* locs) {
-  ASSERT(!IsLeaf());
   __ CallRuntime(entry);
   AddCurrentDescriptor(PcDescriptors::kOther, Isolate::kNoDeoptId, token_pos);
   RecordSafepoint(locs);
@@ -1096,7 +1073,6 @@
                                          intptr_t deopt_id,
                                          intptr_t token_pos,
                                          LocationSummary* locs) {
-  ASSERT(!IsLeaf());
   __ LoadObject(RBX, ic_data);
   __ LoadObject(R10, arguments_descriptor);
   GenerateDartCall(deopt_id,
@@ -1114,7 +1090,6 @@
                                        intptr_t deopt_id,
                                        intptr_t token_pos,
                                        LocationSummary* locs) {
-  ASSERT(!IsLeaf());
   __ LoadObject(RBX, function);
   __ LoadObject(R10, arguments_descriptor);
   if (function.HasCode()) {
diff --git a/runtime/vm/flow_graph_compiler_x64.h b/runtime/vm/flow_graph_compiler_x64.h
index 3ae6bb6..d652a4e 100644
--- a/runtime/vm/flow_graph_compiler_x64.h
+++ b/runtime/vm/flow_graph_compiler_x64.h
@@ -27,8 +27,7 @@
  public:
   FlowGraphCompiler(Assembler* assembler,
                     const FlowGraph& flow_graph,
-                    bool is_optimizing,
-                    bool is_leaf);
+                    bool is_optimizing);
 
   ~FlowGraphCompiler();
 
@@ -207,10 +206,6 @@
     return current_block_->try_index();
   }
 
-  // Returns true if the generated code does not call other Dart code or
-  // runtime. Only deoptimization is allowed to occur. Closures are not leaf.
-  bool IsLeaf() const;
-
   static Condition FlipCondition(Condition condition);
 
   static bool EvaluateCondition(Condition condition, intptr_t l, intptr_t r);
@@ -311,7 +306,6 @@
   GrowableArray<SlowPathCode*> slow_path_code_;
   const GrowableObjectArray& object_table_;
   const bool is_optimizing_;
-  const bool is_dart_leaf_;
 
   const Bool& bool_true_;
   const Bool& bool_false_;
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index f48127b..5850c8d 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -1334,7 +1334,7 @@
     for (Value* use = phi->input_use_list();
          use != NULL;
          use = use->next_use()) {
-      PhiInstr* phi_use = use->definition()->AsPhi();
+      PhiInstr* phi_use = use->instruction()->AsPhi();
       if ((phi_use != NULL) &&
           (phi_use->GetPropagatedCid() == kDynamicCid) &&
           IsPossiblySmiPhi(phi_use)) {
@@ -1353,7 +1353,7 @@
       for (Value* use = phi->input_use_list();
            use != NULL;
            use = use->next_use()) {
-        PhiInstr* phi_use = use->definition()->AsPhi();
+        PhiInstr* phi_use = use->instruction()->AsPhi();
         if ((phi_use != NULL) && (phi_use->GetPropagatedCid() == kSmiCid)) {
           AddToWorklist(phi_use);
         }
@@ -2164,21 +2164,6 @@
 }
 
 
-void FlowGraphAnalyzer::Analyze() {
-  is_leaf_ = true;
-  for (intptr_t i = 0; i < blocks_.length(); ++i) {
-    BlockEntryInstr* entry = blocks_[i];
-    for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
-      LocationSummary* locs = it.Current()->locs();
-      if ((locs != NULL) && locs->can_call()) {
-        is_leaf_ = false;
-        return;
-      }
-    }
-  }
-}
-
-
 static BlockEntryInstr* FindPreHeader(BlockEntryInstr* header) {
   for (intptr_t j = 0; j < header->PredecessorCount(); ++j) {
     BlockEntryInstr* candidate = header->PredecessorAt(j);
diff --git a/runtime/vm/flow_graph_optimizer.h b/runtime/vm/flow_graph_optimizer.h
index a6a32d2..1d5afe2 100644
--- a/runtime/vm/flow_graph_optimizer.h
+++ b/runtime/vm/flow_graph_optimizer.h
@@ -85,26 +85,6 @@
 };
 
 
-// Analyze the generated flow graph. Currently only if it is a leaf
-// method, i.e., does not contain any calls to runtime or other Dart code.
-class FlowGraphAnalyzer : public ValueObject {
- public:
-  explicit FlowGraphAnalyzer(const FlowGraph& flow_graph)
-      : blocks_(flow_graph.reverse_postorder()), is_leaf_(false) {}
-  virtual ~FlowGraphAnalyzer() {}
-
-  void Analyze();
-
-  bool is_leaf() const { return is_leaf_; }
-
- private:
-  const GrowableArray<BlockEntryInstr*>& blocks_;
-  bool is_leaf_;
-
-  DISALLOW_COPY_AND_ASSIGN(FlowGraphAnalyzer);
-};
-
-
 class ParsedFunction;
 
 
diff --git a/runtime/vm/il_printer.cc b/runtime/vm/il_printer.cc
index f41dba6..c847c2e 100644
--- a/runtime/vm/il_printer.cc
+++ b/runtime/vm/il_printer.cc
@@ -169,11 +169,6 @@
 }
 
 
-void Instruction::PrintToVisualizer(BufferFormatter* f) const {
-  PrintTo(f);
-}
-
-
 void Definition::PrintTo(BufferFormatter* f) const {
   PrintUse(f, *this);
   if (is_used()) {
@@ -198,11 +193,6 @@
 }
 
 
-void Definition::PrintToVisualizer(BufferFormatter* f) const {
-  PrintTo(f);
-}
-
-
 void Value::PrintTo(BufferFormatter* f) const {
   PrintUse(f, *definition());
 }
@@ -649,214 +639,6 @@
 }
 
 
-void FlowGraphVisualizer::Print(const char* format, ...) {
-  char str[1000];
-  BufferFormatter f(str, sizeof(str));
-  f.Print("%*s", static_cast<int>(2 * indent_), "");
-  va_list args;
-  va_start(args, format);
-  f.VPrint(format, args);
-  va_end(args);
-  (*Dart::flow_graph_writer())(str, strlen(str));
-}
-
-
-void FlowGraphVisualizer::PrintInstruction(Instruction* instr) {
-  char str[1000];
-  BufferFormatter f(str, sizeof(str));
-  instr->PrintToVisualizer(&f);
-  if (FLAG_print_environments && (instr->env() != NULL)) {
-    instr->env()->PrintTo(&f);
-  }
-  f.Print(" <|@\n");
-  (*Dart::flow_graph_writer())(str, strlen(str));
-}
-
-
-void FlowGraphVisualizer::PrintFunction() {
-#define BEGIN(name)          \
-  Print("begin_%s\n", name); \
-  indent_++;
-#define END(name)          \
-  Print("end_%s\n", name); \
-  indent_--;
-
-  {
-    BEGIN("compilation");
-    const char* name = function_.ToFullyQualifiedCString();
-    Print("%s \"%s\"\n", "name", name);
-    Print("%s \"%s\"\n", "method", name);
-    Print("%s %d\n", "date", 0);  // Required field. Unused.
-    END("compilation");
-  }
-
-  {
-    BEGIN("cfg");
-    Print("%s \"%s\"\n", "name", "Flow graph builder");
-
-    for (intptr_t i = 0; i < block_order_.length(); ++i) {
-      BEGIN("block");
-      BlockEntryInstr* entry = block_order_[i];
-      Print("%s \"B%"Pd"\"\n", "name", entry->block_id());
-      Print("%s %d\n", "from_bci", -1);  // Required field. Unused.
-      Print("%s %d\n", "to_bci", -1);  // Required field. Unused.
-
-      Print("predecessors");
-      for (intptr_t j = 0; j < entry->PredecessorCount(); ++j) {
-        BlockEntryInstr* pred = entry->PredecessorAt(j);
-        Print(" \"B%"Pd"\"", pred->block_id());
-      }
-      Print("\n");
-
-      Print("successors");
-      Instruction* last = entry->last_instruction();
-      for (intptr_t j = 0; j < last->SuccessorCount(); ++j) {
-        intptr_t next_id = last->SuccessorAt(j)->block_id();
-        Print(" \"B%"Pd"\"", next_id);
-      }
-      Print("\n");
-
-      // TODO(fschneider): Use this for exception handlers.
-      Print("xhandlers\n");
-
-      // Can be freely used to mark blocks
-      Print("flags\n");
-
-      if (entry->dominator() != NULL) {
-        Print("%s \"B%"Pd"\"\n", "dominator", entry->dominator()->block_id());
-      }
-
-      // TODO(fschneider): Mark blocks with loop nesting level.
-      Print("%s %d\n", "loop_depth", 0);
-
-      {
-        BEGIN("states");  // Required section.
-        {
-          BEGIN("locals");  // Required section.
-          JoinEntryInstr* join = entry->AsJoinEntry();
-          intptr_t num_phis = (join != NULL && join->phi_count())
-              ? join->phis()->length()
-              : 0;
-          Print("%s %"Pd"\n", "size", num_phis);
-          for (intptr_t j = 0; j < num_phis; ++j) {
-            PhiInstr* phi = (*join->phis())[j];
-            if (phi != NULL) {
-              Print("%"Pd" ", j);  // Print variable index.
-              char buffer[120];
-              BufferFormatter formatter(buffer, sizeof(buffer));
-              phi->PrintToVisualizer(&formatter);
-              Print("%s\n", buffer);
-            }
-          }
-          END("locals");
-        }
-        END("states");
-      }
-
-      {
-        BEGIN("HIR");
-        // Print the block entry.
-        Print("0 0 ");  // Required fields "bci" and "use". Unused.
-        PrintInstruction(block_order_[i]);
-        // And all the successors until an exit, branch, or a block entry.
-        BlockEntryInstr* entry = block_order_[i];
-        Instruction* current = entry;
-        for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
-          current = it.Current();
-          Print("0 0 ");
-          PrintInstruction(current);
-        }
-        if (current->next() != NULL) {
-          ASSERT(current->next()->IsBlockEntry());
-          Print("0 0 _ Goto B%"Pd" <|@\n",
-                current->next()->AsBlockEntry()->block_id());
-        }
-        END("HIR");
-      }
-      END("block");
-    }
-    END("cfg");
-  }
-#undef BEGIN
-#undef END
-}
-
-
-// === Printing instructions in a visualizer-understandable format:
-// "result instruction(op1, op2)" where result is a temporary name
-// or _ for instruction without result.
-void GraphEntryInstr::PrintToVisualizer(BufferFormatter* f) const {
-  const GrowableArray<Definition*>& defns = initial_definitions_;
-  f->Print("_ [graph]");
-  if (defns.length() > 0) {
-    f->Print(" init={ ");
-    for (intptr_t i = 0; i < defns.length(); ++i) {
-      if (i > 0) f->Print(", ");
-      defns[i]->PrintTo(f);
-    }
-    f->Print(" }");
-  }
-}
-
-
-void JoinEntryInstr::PrintToVisualizer(BufferFormatter* f) const {
-  f->Print("_ [join]");
-}
-
-
-void PhiInstr::PrintToVisualizer(BufferFormatter* f) const {
-  f->Print("v%"Pd" [", ssa_temp_index());
-  for (intptr_t i = 0; i < InputCount(); ++i) {
-    if (i > 0) f->Print(" ");
-    InputAt(i)->PrintTo(f);
-  }
-  f->Print("]");
-}
-
-
-void ParameterInstr::PrintToVisualizer(BufferFormatter* f) const {
-  ASSERT(HasSSATemp());
-  ASSERT(temp_index() == -1);
-  f->Print("v%"Pd" Parameter(%"Pd")", ssa_temp_index(), index());
-}
-
-
-void TargetEntryInstr::PrintToVisualizer(BufferFormatter* f) const {
-  f->Print("_ [target");
-  if (IsCatchEntry()) {
-    f->Print(" catch %"Pd"]", catch_try_index());
-  } else {
-    f->Print("]");
-  }
-}
-
-
-void PushArgumentInstr::PrintToVisualizer(BufferFormatter* f) const {
-  f->Print("_ %s ", DebugName());
-  value()->PrintTo(f);
-}
-
-
-void GotoInstr::PrintToVisualizer(BufferFormatter* f) const {
-  f->Print("_ goto B%"Pd"", successor()->block_id());
-}
-
-
-void BranchInstr::PrintToVisualizer(BufferFormatter* f) const {
-  f->Print("_ %s ", DebugName());
-  f->Print("if ");
-  comparison()->PrintTo(f);
-  f->Print(" goto (B%"Pd", B%"Pd")",
-            true_successor()->block_id(),
-            false_successor()->block_id());
-}
-
-
-void ParallelMoveInstr::PrintToVisualizer(BufferFormatter* f) const {
-  UNIMPLEMENTED();
-}
-
-
 void Environment::PrintTo(BufferFormatter* f) const {
   f->Print(" env={ ");
   int arg_count = 0;
diff --git a/runtime/vm/il_printer.h b/runtime/vm/il_printer.h
index 2c62490..3da0191 100644
--- a/runtime/vm/il_printer.h
+++ b/runtime/vm/il_printer.h
@@ -60,28 +60,6 @@
   const bool print_locations_;
 };
 
-
-class FlowGraphVisualizer : public ValueObject {
- public:
-  explicit FlowGraphVisualizer(const FlowGraph& flow_graph)
-      : function_(flow_graph.parsed_function().function()),
-        block_order_(flow_graph.reverse_postorder()),
-        indent_(0) { }
-
-  void PrintFunction();
-
- private:
-  // Helpers for printing.
-  void PrintInstruction(Instruction* instr);
-  void Print(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
-
-  const Function& function_;
-  const GrowableArray<BlockEntryInstr*>& block_order_;
-  intptr_t indent_;
-
-  DISALLOW_COPY_AND_ASSIGN(FlowGraphVisualizer);
-};
-
 }  // namespace dart
 
 #endif  // VM_IL_PRINTER_H_
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index f4d8da7..c846045 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -409,7 +409,6 @@
   // Printing support.
   virtual void PrintTo(BufferFormatter* f) const;
   virtual void PrintOperandsTo(BufferFormatter* f) const;
-  virtual void PrintToVisualizer(BufferFormatter* f) const;
 
 #define INSTRUCTION_TYPE_CHECK(type)                                           \
   bool Is##type() { return (As##type() != NULL); }                             \
@@ -651,7 +650,6 @@
   intptr_t NumMoves() const { return moves_.length(); }
 
   virtual void PrintTo(BufferFormatter* f) const;
-  virtual void PrintToVisualizer(BufferFormatter* f) const;
 
  private:
   GrowableArray<MoveOperands*> moves_;   // Elements cannot be null.
@@ -885,7 +883,6 @@
   TargetEntryInstr* normal_entry() const { return normal_entry_; }
 
   virtual void PrintTo(BufferFormatter* f) const;
-  virtual void PrintToVisualizer(BufferFormatter* f) const;
 
  private:
   virtual void ClearPredecessors() { UNREACHABLE(); }
@@ -928,7 +925,6 @@
   intptr_t phi_count() const { return phi_count_; }
 
   virtual void PrintTo(BufferFormatter* f) const;
-  virtual void PrintToVisualizer(BufferFormatter* f) const;
 
  private:
   friend class FlowGraph;  // Access to predecessors_ when inlining.
@@ -1004,7 +1000,6 @@
   virtual void PrepareEntry(FlowGraphCompiler* compiler);
 
   virtual void PrintTo(BufferFormatter* f) const;
-  virtual void PrintToVisualizer(BufferFormatter* f) const;
 
  private:
   virtual void ClearPredecessors() { predecessor_ = NULL; }
@@ -1107,7 +1102,6 @@
   // formatting. Otherwise, it prints in the format "opcode(op1, op2, op3)".
   virtual void PrintTo(BufferFormatter* f) const;
   virtual void PrintOperandsTo(BufferFormatter* f) const;
-  virtual void PrintToVisualizer(BufferFormatter* f) const;
 
   // A value in the constant propagation lattice.
   //    - non-constant sentinel
@@ -1210,7 +1204,6 @@
   DECLARE_INSTRUCTION(Phi)
 
   virtual void PrintTo(BufferFormatter* f) const;
-  virtual void PrintToVisualizer(BufferFormatter* f) const;
 
   virtual bool InferRange(RangeOperator op);
 
@@ -1272,7 +1265,6 @@
   }
 
   virtual void PrintOperandsTo(BufferFormatter* f) const;
-  virtual void PrintToVisualizer(BufferFormatter* f) const;
 
  private:
   const intptr_t index_;
@@ -1329,7 +1321,6 @@
   virtual bool HasSideEffect() const { return false; }
 
   virtual void PrintOperandsTo(BufferFormatter* f) const;
-  virtual void PrintToVisualizer(BufferFormatter* f) const;
 
  private:
   Value* value_;
@@ -1442,7 +1433,6 @@
   }
 
   virtual void PrintTo(BufferFormatter* f) const;
-  virtual void PrintToVisualizer(BufferFormatter* f) const;
 
  private:
   JoinEntryInstr* successor_;
@@ -1520,7 +1510,6 @@
   }
 
   virtual void PrintTo(BufferFormatter* f) const;
-  virtual void PrintToVisualizer(BufferFormatter* f) const;
 
  private:
   ComparisonInstr* comparison_;
diff --git a/runtime/vm/intrinsifier.h b/runtime/vm/intrinsifier.h
index 3924bfd..9b4bc5b 100644
--- a/runtime/vm/intrinsifier.h
+++ b/runtime/vm/intrinsifier.h
@@ -87,6 +87,8 @@
   V(_Uint32Array, [], Uint32Array_getIndexed)                                  \
   V(_Float32Array, [], Float32Array_getIndexed)                                \
   V(_Float32Array, []=, Float32Array_setIndexed)                               \
+  V(_Float64Array, [], Float64Array_getIndexed)                                \
+  V(_Float64Array, []=, Float64Array_setIndexed)                               \
 
 // Forward declarations.
 class Assembler;
diff --git a/runtime/vm/intrinsifier_ia32.cc b/runtime/vm/intrinsifier_ia32.cc
index 6f4eb81..2c2e8d3 100644
--- a/runtime/vm/intrinsifier_ia32.cc
+++ b/runtime/vm/intrinsifier_ia32.cc
@@ -627,6 +627,54 @@
 }
 
 
+bool Intrinsifier::Float64Array_getIndexed(Assembler* assembler) {
+  Label fall_through;
+  TestByteArrayIndex(assembler, &fall_through);
+  // After TestByteArrayIndex:
+  // * EAX has the base address of the byte array.
+  // * EBX has the index into the array.
+  // EBX contains the SMI index which is shifted left by 1.
+  // This shift means we only multiply the index by 4 not 8 (sizeof double).
+  // Load double precision float into XMM7.
+  __ movsd(XMM7, FieldAddress(EAX, EBX, TIMES_4,
+                              Float64Array::data_offset()));
+  // Allocate a double instance.
+  const Class& double_class = Class::Handle(
+    Isolate::Current()->object_store()->double_class());
+  AssemblerMacros::TryAllocate(assembler,
+                               double_class,
+                               &fall_through,
+                               Assembler::kNearJump, EAX);
+  // Store XMM7 into double instance.
+  __ movsd(FieldAddress(EAX, Double::value_offset()), XMM7);
+  __ ret();
+  __ Bind(&fall_through);
+  return false;
+}
+
+
+bool Intrinsifier::Float64Array_setIndexed(Assembler* assembler) {
+  Label fall_through;
+  __ movl(EAX, Address(ESP, + 1 * kWordSize));  // Value.
+  // If EAX is not an instance of double, jump to fall through.
+  __ CompareClassId(EAX, kDoubleCid, EDI);
+  __ j(NOT_EQUAL, &fall_through);
+  // Load double value into XMM7.
+  __ movsd(XMM7, FieldAddress(EAX, Double::value_offset()));
+  TestByteArraySetIndex(assembler, &fall_through);
+  // After TestByteArraySetIndex:
+  // * EAX has the base address of the byte array.
+  // * EBX has the index into the array.
+  // EBX contains the SMI index which is shifted by 1.
+  // This shift means we only multiply the index by 4 not 8 (sizeof float).
+  // Store into array.
+  __ movsd(FieldAddress(EAX, EBX, TIMES_4, Float64Array::data_offset()), XMM7);
+  __ 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 781cf4a..b3f7be7 100644
--- a/runtime/vm/intrinsifier_x64.cc
+++ b/runtime/vm/intrinsifier_x64.cc
@@ -585,6 +585,54 @@
 }
 
 
+bool Intrinsifier::Float64Array_getIndexed(Assembler* assembler) {
+  Label fall_through;
+  TestByteArrayIndex(assembler, &fall_through);
+  // After TestByteArrayIndex:
+  // * RAX has the base address of the byte array.
+  // * R12 has the index into the array.
+  // R12 contains the SMI index which is shifted left by 1.
+  // This shift means we only multiply the index by 4 not 8 (sizeof double).
+  // Load double precision float into XMM7.
+  __ movsd(XMM7, FieldAddress(RAX, R12, TIMES_4,
+                              Float64Array::data_offset()));
+  // Allocate a double instance.
+  const Class& double_class = Class::Handle(
+    Isolate::Current()->object_store()->double_class());
+  AssemblerMacros::TryAllocate(assembler,
+                               double_class,
+                               &fall_through,
+                               Assembler::kNearJump, RAX);
+  // Store XMM7 into double instance.
+  __ movsd(FieldAddress(RAX, Double::value_offset()), XMM7);
+  __ ret();
+  __ Bind(&fall_through);
+  return false;
+}
+
+
+bool Intrinsifier::Float64Array_setIndexed(Assembler* assembler) {
+  Label fall_through;
+  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.
+  // This shift means we only multiply the index by 4 not 8 (sizeof double).
+  __ movq(RDX, Address(RSP, + 1 * kWordSize));  // Value.
+  // If RDX is not an instance of double, jump to fall through.
+  __ CompareClassId(RDX, kDoubleCid);
+  __ j(NOT_EQUAL, &fall_through);
+  // Load double value into XMM7.
+  __ movsd(XMM7, FieldAddress(RDX, Double::value_offset()));
+  // Store into array.
+  __ movsd(FieldAddress(RAX, R12, TIMES_4, Float64Array::data_offset()), XMM7);
+  __ 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/object.cc b/runtime/vm/object.cc
index adf5d90..bf300c7 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -1345,8 +1345,7 @@
   result.set_handle_vtable(fake.vtable());
   result.set_instance_size(FakeObject::InstanceSize());
   result.set_next_field_offset(FakeObject::InstanceSize());
-  ASSERT((FakeObject::kClassId != kInstanceCid) &&
-         (FakeObject::kClassId != kClosureCid));
+  ASSERT((FakeObject::kClassId != kInstanceCid));
   result.set_id(FakeObject::kClassId);
   result.raw_ptr()->state_bits_ = 0;
   // VM backed classes are almost ready: run checks and resolve class
@@ -1778,10 +1777,6 @@
 }
 
 
-// Force instantiation of template version to work around ld problems.
-template RawClass* Class::New<Closure>(intptr_t index);
-
-
 template <class FakeInstance>
 RawClass* Class::New(const String& name,
                      const Script& script,
@@ -1827,10 +1822,12 @@
     type_parameters = owner_class.type_parameters();
   }
   const intptr_t token_pos = signature_function.token_pos();
-  Class& result = Class::Handle(New<Closure>(name, script, token_pos));
+  Class& result = Class::Handle(New<Instance>(name, script, token_pos));
   const Type& super_type = Type::Handle(Type::ObjectType());
   const Array& empty_array = Array::Handle(Object::empty_array());
   ASSERT(!super_type.IsNull());
+  result.set_instance_size(Closure::InstanceSize());
+  result.set_next_field_offset(Closure::InstanceSize());
   result.set_super_type(super_type);
   result.set_signature_function(signature_function);
   result.set_type_parameters(type_parameters);
@@ -3142,7 +3139,7 @@
   if (!IsFactory() || (raw_ptr()->data_ == Object::null())) {
     return false;
   }
-  ASSERT(!IsClosure());  // A factory cannot also be a closure.
+  ASSERT(!IsClosureFunction());  // A factory cannot also be a closure.
   return true;
 }
 
@@ -6980,7 +6977,9 @@
 }
 
 
-RawCode* Code::FinalizeCode(const char* name, Assembler* assembler) {
+RawCode* Code::FinalizeCode(const char* name,
+                            Assembler* assembler,
+                            bool optimized) {
   ASSERT(assembler != NULL);
 
   // Allocate the Instructions object.
@@ -6994,12 +6993,13 @@
   assembler->FinalizeInstructions(region);
   Dart_FileWriterFunction perf_events_writer = Dart::perf_events_writer();
   if (perf_events_writer != NULL) {
-    const char* format = "%"Px" %"Px" %s\n";
+    const char* format = "%"Px" %"Px" %s%s\n";
     uword addr = instrs.EntryPoint();
     uword size = instrs.size();
-    intptr_t len = OS::SNPrint(NULL, 0, format, addr, size, name);
+    const char* marker = optimized ? "*" : "";
+    intptr_t len = OS::SNPrint(NULL, 0, format, addr, size, marker, name);
     char* buffer = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
-    OS::SNPrint(buffer, len + 1, format, addr, size, name);
+    OS::SNPrint(buffer, len + 1, format, addr, size, marker, name);
     (*perf_events_writer)(buffer, len);
   }
   DebugInfo* pprof_symbol_generator = Dart::pprof_symbol_generator();
@@ -7058,12 +7058,16 @@
 }
 
 
-RawCode* Code::FinalizeCode(const Function& function, Assembler* assembler) {
+RawCode* Code::FinalizeCode(const Function& function,
+                            Assembler* assembler,
+                            bool optimized) {
   // Calling ToFullyQualifiedCString is very expensive, try to avoid it.
   if (FLAG_generate_gdb_symbols ||
       Dart::perf_events_writer() != NULL ||
       Dart::pprof_symbol_generator() != NULL) {
-    return FinalizeCode(function.ToFullyQualifiedCString(), assembler);
+    return FinalizeCode(function.ToFullyQualifiedCString(),
+                        assembler,
+                        optimized);
   } else {
     return FinalizeCode("", assembler);
   }
@@ -8113,6 +8117,12 @@
 }
 
 
+bool Instance::IsClosure() const {
+  const Class& cls = Class::Handle(clazz());
+  return cls.IsSignatureClass();
+}
+
+
 RawInstance* Instance::New(const Class& cls, Heap::Space space) {
   Instance& result = Instance::Handle();
   {
@@ -8151,8 +8161,11 @@
     // Can occur when running disassembler.
     return "Instance";
   } else {
+    if (IsClosure()) {
+      return Closure::ToCString(*this);
+    }
     const char* kFormat = "Instance of '%s'";
-    Class& cls = Class::Handle(clazz());
+    const Class& cls = Class::Handle(clazz());
     AbstractTypeArguments& type_arguments = AbstractTypeArguments::Handle();
     const intptr_t num_type_arguments = cls.NumTypeArguments();
     if (num_type_arguments > 0) {
@@ -11887,43 +11900,8 @@
 }
 
 
-
-RawClosure* Closure::New(const Function& function,
-                         const Context& context,
-                         Heap::Space space) {
-  Isolate* isolate = Isolate::Current();
-  ASSERT(context.isolate() == isolate);
-
-  const Class& cls = Class::Handle(function.signature_class());
-  Closure& result = Closure::Handle();
-  {
-    RawObject* raw = Object::Allocate(cls.id(), Closure::InstanceSize(), space);
-    NoGCScope no_gc;
-    result ^= raw;
-  }
-  result.set_function(function);
-  result.set_context(context);
-  return result.raw();
-}
-
-
-void Closure::set_context(const Context& value) const {
-  StorePointer(&raw_ptr()->context_, value.raw());
-}
-
-
-void Closure::set_function(const Function& value) const {
-  StorePointer(&raw_ptr()->function_, value.raw());
-}
-
-
-const char* DartFunction::ToCString() const {
-  return "Function type class";
-}
-
-
-const char* Closure::ToCString() const {
-  const Function& fun = Function::Handle(function());
+const char* Closure::ToCString(const Instance& closure) {
+  const Function& fun = Function::Handle(Closure::function(closure));
   const bool is_implicit_closure = fun.IsImplicitClosureFunction();
   const char* fun_sig = String::Handle(fun.Signature()).ToCString();
   const char* from = is_implicit_closure ? " from " : "";
@@ -11936,6 +11914,31 @@
 }
 
 
+RawInstance* Closure::New(const Function& function,
+                          const Context& context,
+                          Heap::Space space) {
+  Isolate* isolate = Isolate::Current();
+  ASSERT(context.isolate() == isolate);
+
+  const Class& cls = Class::Handle(function.signature_class());
+  ASSERT(cls.instance_size() == Closure::InstanceSize());
+  Instance& result = Instance::Handle();
+  {
+    RawObject* raw = Object::Allocate(cls.id(), Closure::InstanceSize(), space);
+    NoGCScope no_gc;
+    result ^= raw;
+  }
+  Closure::set_function(result, function);
+  Closure::set_context(result, context);
+  return result.raw();
+}
+
+
+const char* DartFunction::ToCString() const {
+  return "Function type class";
+}
+
+
 intptr_t Stacktrace::Length() const {
   const Array& code_array = Array::Handle(raw_ptr()->code_array_);
   return code_array.Length();
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 1fbca5a..8413fc6 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -27,6 +27,7 @@
 #undef DEFINE_FORWARD_DECLARATION
 class Api;
 class Assembler;
+class Closure;
 class Code;
 class LocalScope;
 class Symbols;
@@ -421,6 +422,7 @@
 
   friend void ClassTable::Register(const Class& cls);
   friend void RawObject::Validate(Isolate* isolate) const;
+  friend class Closure;
   friend class SnapshotReader;
 
   // Disallow allocation.
@@ -2495,8 +2497,12 @@
     ASSERT(0 <= len && len <= kMaxElements);
     return RoundedAllocationSize(sizeof(RawCode) + (len * kBytesPerElement));
   }
-  static RawCode* FinalizeCode(const Function& function, Assembler* assembler);
-  static RawCode* FinalizeCode(const char* name, Assembler* assembler);
+  static RawCode* FinalizeCode(const Function& function,
+                               Assembler* assembler,
+                               bool optimized = false);
+  static RawCode* FinalizeCode(const char* name,
+                               Assembler* assembler,
+                               bool optimized = false);
   static RawCode* LookupCode(uword pc);
 
   int32_t GetPointerOffsetAt(int index) const {
@@ -3005,6 +3011,9 @@
     *NativeFieldAddr(index) = value;
   }
 
+  // Returns true if the instance is a closure object.
+  bool IsClosure() const;
+
   static intptr_t InstanceSize() {
     return RoundedAllocationSize(sizeof(RawInstance));
   }
@@ -3033,6 +3042,7 @@
   // TODO(iposva): Determine if this gets in the way of Smi.
   HEAP_OBJECT_IMPLEMENTATION(Instance, Object);
   friend class Class;
+  friend class Closure;
 };
 
 
@@ -5451,46 +5461,75 @@
 };
 
 
-class Closure : public Instance {
+class Closure : public AllStatic {
  public:
-  RawFunction* function() const { return raw_ptr()->function_; }
+  static RawFunction* function(const Instance& closure) {
+    return *FunctionAddr(closure);
+  }
   static intptr_t function_offset() {
-    return OFFSET_OF(RawClosure, function_);
+    return static_cast<intptr_t>(kFunctionOffset * kWordSize);
   }
 
-  RawContext* context() const { return raw_ptr()->context_; }
-  static intptr_t context_offset() { return OFFSET_OF(RawClosure, context_); }
-
-  virtual RawAbstractTypeArguments* GetTypeArguments() const {
-    return raw_ptr()->type_arguments_;
+  static RawContext* context(const Instance& closure) {
+    return *ContextAddr(closure);
   }
-  virtual void SetTypeArguments(const AbstractTypeArguments& value) const {
-    StorePointer(&raw_ptr()->type_arguments_, value.raw());
+  static intptr_t context_offset() {
+    return static_cast<intptr_t>(kContextOffset * kWordSize);
+  }
+
+  static RawAbstractTypeArguments* GetTypeArguments(const Instance& closure) {
+    return *TypeArgumentsAddr(closure);
+  }
+  static void SetTypeArguments(const Instance& closure,
+                               const AbstractTypeArguments& value) {
+    closure.StorePointer(TypeArgumentsAddr(closure), value.raw());
   }
   static intptr_t type_arguments_offset() {
-    return OFFSET_OF(RawClosure, type_arguments_);
+    return static_cast<intptr_t>(kTypeArgumentsOffset * kWordSize);
   }
 
-  // TODO(iposva): Remove smrck support once mapping to arbitrary is available.
-  RawInteger* smrck() const { return raw_ptr()->smrck_; }
-  void set_smrck(const Integer& smrck) const {
-    StorePointer(&raw_ptr()->smrck_, smrck.raw());
-  }
-  static intptr_t smrck_offset() { return OFFSET_OF(RawClosure, smrck_); }
+  static const char* ToCString(const Instance& closure);
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(RawClosure));
+    intptr_t size = sizeof(RawInstance) + (kNumFields * kWordSize);
+    ASSERT(size == Object::RoundedAllocationSize(size));
+    return size;
   }
 
-  static RawClosure* New(const Function& function,
-                         const Context& context,
-                         Heap::Space space = Heap::kNew);
+  static RawInstance* New(const Function& function,
+                          const Context& context,
+                          Heap::Space space = Heap::kNew);
 
  private:
-  void set_function(const Function& value) const;
-  void set_context(const Context& value) const;
+  static const int kTypeArgumentsOffset = 1;
+  static const int kFunctionOffset = 2;
+  static const int kContextOffset = 3;
+  static const int kNumFields = 3;
 
-  HEAP_OBJECT_IMPLEMENTATION(Closure, Instance);
+  static RawAbstractTypeArguments** TypeArgumentsAddr(const Instance& obj) {
+    ASSERT(obj.IsClosure());
+    return reinterpret_cast<RawAbstractTypeArguments**>(
+        reinterpret_cast<intptr_t>(obj.raw_ptr()) + type_arguments_offset());
+  }
+  static RawFunction** FunctionAddr(const Instance& obj) {
+    ASSERT(obj.IsClosure());
+    return reinterpret_cast<RawFunction**>(
+        reinterpret_cast<intptr_t>(obj.raw_ptr()) + function_offset());
+  }
+  static RawContext** ContextAddr(const Instance& obj) {
+    ASSERT(obj.IsClosure());
+    return reinterpret_cast<RawContext**>(
+        reinterpret_cast<intptr_t>(obj.raw_ptr()) + context_offset());
+  }
+  static void set_function(const Instance& closure,
+                           const Function& value) {
+    closure.StorePointer(FunctionAddr(closure), value.raw());
+  }
+  static void set_context(const Instance& closure,
+                          const Context& value) {
+    closure.StorePointer(ContextAddr(closure), value.raw());
+  }
+
   friend class Class;
 };
 
@@ -5681,11 +5720,7 @@
 #endif
     set_vtable(builtin_vtables_[cid]);
   } else {
-#if !defined(DEBUG)
-    Isolate* isolate = Isolate::Current();
-#endif
-    RawClass* raw_class = isolate->class_table()->At(cid);
-    set_vtable(raw_class->ptr()->handle_vtable_);
+    set_vtable(builtin_vtables_[kInstanceCid]);
   }
 }
 
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index e63c0bd..6bcf17c 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -2338,7 +2338,7 @@
   function = Function::NewClosureFunction(function_name, parent, 0);
   const Class& signature_class = Class::Handle(
       Class::NewSignatureClass(function_name, function, script));
-  const Closure& closure = Closure::Handle(Closure::New(function, context));
+  const Instance& closure = Instance::Handle(Closure::New(function, context));
   const Class& closure_class = Class::Handle(closure.clazz());
   EXPECT(closure_class.IsSignatureClass());
   EXPECT(closure_class.IsCanonicalSignatureClass());
@@ -2346,7 +2346,7 @@
   const Function& signature_function =
     Function::Handle(signature_class.signature_function());
   EXPECT_EQ(signature_function.raw(), function.raw());
-  const Context& closure_context = Context::Handle(closure.context());
+  const Context& closure_context = Context::Handle(Closure::context(closure));
   EXPECT_EQ(closure_context.raw(), closure_context.raw());
 }
 
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index 57ac4d9..2d41d74 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -286,14 +286,8 @@
         break;
     }
   } else {
-    RawClass* raw_class = visitor->isolate()->class_table()->At(class_id);
-    if (Class::IsSignatureClass(raw_class)) {
-      RawClosure* raw_obj = reinterpret_cast<RawClosure*>(this);
-      size = RawClosure::VisitClosurePointers(raw_obj, visitor);
-    } else {
-      RawInstance* raw_obj = reinterpret_cast<RawInstance*>(this);
-      size = RawInstance::VisitInstancePointers(raw_obj, visitor);
-    }
+    RawInstance* raw_obj = reinterpret_cast<RawInstance*>(this);
+    size = RawInstance::VisitInstancePointers(raw_obj, visitor);
   }
 
   ASSERT(size != 0);
@@ -964,15 +958,6 @@
 }
 
 
-intptr_t RawClosure::VisitClosurePointers(RawClosure* raw_obj,
-                                          ObjectPointerVisitor* visitor) {
-  // Make sure that we got here with the tagged pointer as this.
-  ASSERT(raw_obj->IsHeapObject());
-  visitor->VisitPointers(raw_obj->from(), raw_obj->to());
-  return Closure::InstanceSize();
-}
-
-
 intptr_t RawStacktrace::VisitStacktracePointers(RawStacktrace* raw_obj,
                                                 ObjectPointerVisitor* visitor) {
   // Make sure that we got here with the tagged pointer as this.
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 8dffb94..89f3c7b 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -92,7 +92,6 @@
     V(JSRegExp)                                                                \
     V(WeakProperty)                                                            \
     V(DartFunction)                                                            \
-    V(Closure)                                                                 \
 
 #define CLASS_LIST(V)                                                          \
   V(Object)                                                                    \
@@ -1433,21 +1432,6 @@
 };
 
 
-class RawClosure : public RawInstance {
-  RAW_HEAP_OBJECT_IMPLEMENTATION(Closure);
-
-  RawObject** from() {
-    return reinterpret_cast<RawObject**>(&ptr()->type_arguments_);
-  }
-  RawAbstractTypeArguments* type_arguments_;
-  RawFunction* function_;
-  RawContext* context_;
-  // TODO(iposva): Remove this temporary hack.
-  RawInteger* smrck_;
-  RawObject** to() { return reinterpret_cast<RawObject**>(&ptr()->smrck_); }
-};
-
-
 // VM type for capturing stacktraces when exceptions are thrown,
 // Currently we don't have any interface that this object is supposed
 // to implement so we just support the 'toString' method which
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 0f4c529..55a8e97 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -39,21 +39,16 @@
       (kind == Snapshot::kScript && !RawObject::IsCreatedFromSnapshot(tags))) {
     // Read in the base information.
     intptr_t class_id = reader->ReadIntptrValue();
-    bool is_signature_class = reader->Read<bool>();
 
     // Allocate class object of specified kind.
     if (kind == Snapshot::kFull) {
-      cls = reader->NewClass(class_id, is_signature_class);
+      cls = reader->NewClass(class_id);
     } else {
       if (class_id < kNumPredefinedCids) {
         ASSERT((class_id >= kInstanceCid) && (class_id <= kDartFunctionCid));
         cls = reader->isolate()->class_table()->At(class_id);
       } else {
-        if (is_signature_class) {
-          cls = New<Closure>(kIllegalCid);
-        } else {
-          cls = New<Instance>(kIllegalCid);
-        }
+        cls = New<Instance>(kIllegalCid);
       }
     }
     reader->AddBackRef(object_id, &cls, kIsDeserialized);
@@ -101,7 +96,6 @@
     // Write out all the non object pointer fields.
     // NOTE: cpp_vtable_ is not written.
     writer->WriteIntptrValue(ptr()->id_);
-    writer->Write<bool>(Class::IsSignatureClass(this) ? true : false);
     writer->WriteIntptrValue(ptr()->instance_size_);
     writer->WriteIntptrValue(ptr()->type_arguments_instance_field_offset_);
     writer->WriteIntptrValue(ptr()->next_field_offset_);
@@ -2206,22 +2200,6 @@
 }
 
 
-RawClosure* Closure::ReadFrom(SnapshotReader* reader,
-                              intptr_t object_id,
-                              intptr_t tags,
-                              Snapshot::Kind kind) {
-  UNIMPLEMENTED();
-  return Closure::null();
-}
-
-
-void RawClosure::WriteTo(SnapshotWriter* writer,
-                         intptr_t object_id,
-                         Snapshot::Kind kind) {
-  UNIMPLEMENTED();
-}
-
-
 RawStacktrace* Stacktrace::ReadFrom(SnapshotReader* reader,
                                     intptr_t object_id,
                                     intptr_t tags,
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index 5f6f4b7..12aad9e 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -434,7 +434,7 @@
 }
 
 
-RawClass* SnapshotReader::NewClass(intptr_t class_id, bool is_signature_class) {
+RawClass* SnapshotReader::NewClass(intptr_t class_id) {
   ASSERT(kind_ == Snapshot::kFull);
   ASSERT(isolate()->no_gc_scope_depth() != 0);
   if (class_id < kNumPredefinedCids) {
@@ -444,13 +444,8 @@
   cls_ = Object::class_class();
   RawClass* obj = reinterpret_cast<RawClass*>(
       AllocateUninitialized(cls_, Class::InstanceSize()));
-  if (is_signature_class) {
-    Closure fake;
-    obj->ptr()->handle_vtable_ = fake.vtable();
-  } else {
-    Instance fake;
-    obj->ptr()->handle_vtable_ = fake.vtable();
-  }
+  Instance fake;
+  obj->ptr()->handle_vtable_ = fake.vtable();
   cls_ = obj;
   cls_.set_id(kIllegalCid);
   isolate()->class_table()->Register(cls_);
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index 205824d..44c19fe 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -243,7 +243,7 @@
   RawTypeArguments* NewTypeArguments(intptr_t len);
   RawTokenStream* NewTokenStream(intptr_t len);
   RawContext* NewContext(intptr_t num_variables);
-  RawClass* NewClass(intptr_t class_id, bool is_signature_class);
+  RawClass* NewClass(intptr_t class_id);
   RawMint* NewMint(int64_t value);
   RawBigint* NewBigint(const char* hex_string);
   RawDouble* NewDouble(double value);
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index 56f8c02..6f59c3e 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -1376,7 +1376,7 @@
     uword tags = 0;
     tags = RawObject::SizeTag::update(closure_size, tags);
     tags = RawObject::ClassIdTag::update(cls.id(), tags);
-    __ movl(Address(EAX, Closure::tags_offset()), Immediate(tags));
+    __ movl(Address(EAX, Instance::tags_offset()), Immediate(tags));
 
     // Initialize the function field in the object.
     // EAX: new closure object.
@@ -1427,8 +1427,6 @@
     __ movl(EDX, Address(ESP, kTypeArgumentsOffset));
     __ movl(Address(EAX, Closure::type_arguments_offset()), EDX);
 
-    __ movl(Address(EAX, Closure::smrck_offset()), raw_null);
-
     // Done allocating and initializing the instance.
     // EAX: new object.
     __ addl(EAX, Immediate(kHeapObjectTag));
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index 6d21c43..1e81cfe 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -1358,7 +1358,7 @@
     uword tags = 0;
     tags = RawObject::SizeTag::update(closure_size, tags);
     tags = RawObject::ClassIdTag::update(cls.id(), tags);
-    __ movq(Address(RAX, Closure::tags_offset()), Immediate(tags));
+    __ movq(Address(RAX, Instance::tags_offset()), Immediate(tags));
 
     // Initialize the function field in the object.
     // RAX: new closure object.
@@ -1410,8 +1410,6 @@
     __ movq(R10, Address(RSP, kTypeArgumentsOffset));
     __ movq(Address(RAX, Closure::type_arguments_offset()), R10);
 
-    __ movq(Address(RAX, Closure::smrck_offset()), raw_null);
-
     // Done allocating and initializing the instance.
     // RAX: new object.
     __ addq(RAX, Immediate(kHeapObjectTag));
diff --git a/runtime/vm/version.h b/runtime/vm/version.h
new file mode 100644
index 0000000..dee350b
--- /dev/null
+++ b/runtime/vm/version.h
@@ -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.
+
+#ifndef VM_VERSION_H_
+#define VM_VERSION_H_
+
+#include "vm/allocation.h"
+
+namespace dart {
+
+class Version : public AllStatic {
+ public:
+  static const char* String() { return str_; }
+
+ private:
+  static const char* str_;
+};
+
+}  // namespace dart
+
+#endif  // VM_VERSION_H_
diff --git a/runtime/vm/version_in.cc b/runtime/vm/version_in.cc
new file mode 100644
index 0000000..d479d9f
--- /dev/null
+++ b/runtime/vm/version_in.cc
@@ -0,0 +1,11 @@
+// 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/version.h"
+
+namespace dart {
+
+const char* Version::str_ = "{{VERSION_STR}} ({{BUILD_TIME}})";
+
+}  // namespace dart
diff --git a/tests/co19/co19-dart2dart.status b/tests/co19/co19-dart2dart.status
index e649ec4..a15d037 100644
--- a/tests/co19/co19-dart2dart.status
+++ b/tests/co19/co19-dart2dart.status
@@ -5,79 +5,7 @@
 [ $compiler == dart2dart ]
 LibTest/isolate/isolate_api/port_A01_t01: Skip # Times out.
 
-Language/10_Expressions/01_Constants_A05_t03: Fail # TRIAGE
-Language/10_Expressions/05_Strings/1_String_Interpolation_A01_t04: Fail # TRIAGE
-Language/10_Expressions/05_Strings/1_String_Interpolation_A01_t05: Fail # TRIAGE
-Language/10_Expressions/05_Strings/1_String_Interpolation_A01_t06: Fail # TRIAGE
-Language/10_Expressions/11_Instance_Creation/1_New_A06_t06: Fail # TRIAGE
-Language/10_Expressions/11_Instance_Creation/1_New_A07_t01: Fail # TRIAGE
-Language/10_Expressions/11_Instance_Creation/1_New_A11_t01: Fail # TRIAGE
-Language/10_Expressions/11_Instance_Creation/1_New_A12_t01: Fail # TRIAGE
-Language/10_Expressions/11_Instance_Creation/1_New_A12_t02: Fail # TRIAGE
 Language/10_Expressions/11_Instance_Creation/1_New_A13_t02: Fail # TRIAGE
-Language/10_Expressions/11_Instance_Creation/1_New_A13_t04: Fail # TRIAGE
-Language/10_Expressions/11_Instance_Creation/1_New_A14_t01: Fail # TRIAGE
-Language/10_Expressions/13_Property_Extraction_A01_t01: Fail # TRIAGE
-Language/10_Expressions/19_Conditional_A01_t10: Fail # TRIAGE
-Language/10_Expressions/19_Conditional_A01_t11: Fail # TRIAGE
-Language/10_Expressions/19_Conditional_A01_t12: Fail # TRIAGE
-Language/10_Expressions/19_Conditional_A01_t13: Fail # TRIAGE
-Language/10_Expressions/19_Conditional_A01_t14: Fail # TRIAGE
-Language/10_Expressions/19_Conditional_A01_t15: Fail # TRIAGE
-Language/10_Expressions/20_Logical_Boolean_Expressions_A01_t11: Fail # TRIAGE
-Language/10_Expressions/20_Logical_Boolean_Expressions_A01_t13: Fail # TRIAGE
-Language/10_Expressions/20_Logical_Boolean_Expressions_A01_t14: Fail # TRIAGE
-Language/10_Expressions/21_Bitwise_Expressions_A01_t13: Fail # TRIAGE
-Language/10_Expressions/21_Bitwise_Expressions_A01_t15: Fail # TRIAGE
-Language/10_Expressions/21_Bitwise_Expressions_A01_t16: Fail # TRIAGE
-Language/10_Expressions/21_Bitwise_Expressions_A01_t17: Fail # TRIAGE
-Language/10_Expressions/21_Relational_Expressions_A01_t19: Fail # TRIAGE
-Language/10_Expressions/21_Relational_Expressions_A01_t21: Fail # TRIAGE
-Language/10_Expressions/21_Relational_Expressions_A01_t22: Fail # TRIAGE
-Language/10_Expressions/21_Relational_Expressions_A01_t23: Fail # TRIAGE
-Language/10_Expressions/22_Equality_A01_t23: Fail # TRIAGE
-Language/10_Expressions/22_Equality_A01_t24: Fail # TRIAGE
-Language/10_Expressions/22_Equality_A03_t02: Fail # TRIAGE
-Language/10_Expressions/22_Shift_A01_t10: Fail # TRIAGE
-Language/10_Expressions/22_Shift_A01_t12: Fail # TRIAGE
-Language/10_Expressions/22_Shift_A01_t13: Fail # TRIAGE
-Language/10_Expressions/22_Shift_A01_t14: Fail # TRIAGE
-Language/10_Expressions/23_Additive_Expressions_A01_t08: Fail # TRIAGE
-Language/10_Expressions/23_Additive_Expressions_A01_t11: Fail # TRIAGE
-Language/10_Expressions/23_Additive_Expressions_A01_t12: Fail # TRIAGE
-Language/10_Expressions/23_Additive_Expressions_A01_t13: Fail # TRIAGE
-Language/10_Expressions/23_Additive_Expressions_A01_t14: Fail # TRIAGE
-Language/10_Expressions/24_Multiplicative_Expressions_A01_t11: Fail # TRIAGE
-Language/10_Expressions/24_Multiplicative_Expressions_A01_t14: Fail # TRIAGE
-Language/10_Expressions/24_Multiplicative_Expressions_A01_t15: Fail # TRIAGE
-Language/10_Expressions/24_Multiplicative_Expressions_A01_t16: Fail # TRIAGE
-Language/10_Expressions/24_Multiplicative_Expressions_A01_t17: Fail # TRIAGE
-Language/10_Expressions/25_Unary_Expressions_A01_t02: Fail # TRIAGE
-Language/10_Expressions/25_Unary_Expressions_A01_t04: Fail # TRIAGE
-Language/10_Expressions/25_Unary_Expressions_A01_t05: Fail # TRIAGE
-Language/10_Expressions/25_Unary_Expressions_A01_t17: Fail # TRIAGE
-Language/10_Expressions/25_Unary_Expressions_A01_t18: Fail # TRIAGE
-Language/10_Expressions/25_Unary_Expressions_A01_t19: Fail # TRIAGE
-Language/10_Expressions/25_Unary_Expressions_A01_t20: Fail # TRIAGE
-Language/10_Expressions/25_Unary_Expressions_A01_t21: Fail # TRIAGE
-Language/10_Expressions/25_Unary_Expressions_A01_t22: Fail # TRIAGE
-Language/10_Expressions/26_Postfix_Expressions_A01_t02: Fail # TRIAGE
-Language/10_Expressions/26_Postfix_Expressions_A01_t03: Fail # TRIAGE
-Language/10_Expressions/26_Postfix_Expressions_A01_t05: Fail # TRIAGE
-Language/10_Expressions/27_Assignable_Expressions_A01_t06: Fail # TRIAGE
-Language/10_Expressions/27_Assignable_Expressions_A01_t08: Fail # TRIAGE
-Language/10_Expressions/27_Assignable_Expressions_A01_t09: Fail # TRIAGE
-Language/10_Expressions/28_Identifier_Reference_A04_t01: Fail # TRIAGE
-Language/10_Expressions/28_Identifier_Reference_A04_t03: Fail # TRIAGE
-Language/10_Expressions/28_Identifier_Reference_A04_t06: Fail # TRIAGE
-Language/10_Expressions/29_Type_Test_A01_t04: Fail # TRIAGE
-Language/13_Libraries_and_Scripts/2_Imports_A01_t49: Fail # TRIAGE
-Language/13_Libraries_and_Scripts/2_Imports_A02_t12: Fail # TRIAGE
-Language/13_Libraries_and_Scripts/2_Imports_A02_t13: Fail # TRIAGE
-Language/13_Libraries_and_Scripts/2_Imports_A02_t15: Fail # TRIAGE
-Language/13_Libraries_and_Scripts/2_Imports_A02_t19: Fail # TRIAGE
-
-Language/10_Expressions/05_Strings_A12_t01: Fail # TRIAGE
 
 Language/03_Overview/1_Scoping_A01_t39: Fail # http://dartbug.com/5519
 Language/03_Overview/1_Scoping_A01_t40: Fail # http://dartbug.com/5519
@@ -257,6 +185,7 @@
 Language/10_Expressions/01_Constants_A03_t05: Fail # http://dartbug.com/5519
 Language/10_Expressions/01_Constants_A05_t01: Fail # inherited from VM
 Language/10_Expressions/01_Constants_A05_t02: Fail # http://dartbug.com/5519
+Language/10_Expressions/01_Constants_A05_t03: Fail # http://dartbug.com/5810
 Language/10_Expressions/01_Constants_A05_t04: Fail # http://dartbug.com/5519
 Language/10_Expressions/01_Constants_A06_t01: Fail # inherited from VM
 Language/10_Expressions/01_Constants_A08_t02: Fail # http://dartbug.com/5519
@@ -301,6 +230,9 @@
 Language/10_Expressions/01_Constants_A19_t02: Fail # inherited from VM
 Language/10_Expressions/01_Constants_A19_t03: Fail # inherited from VM
 Language/10_Expressions/01_Constants_A19_t04: Fail # http://dartbug.com/5519
+Language/10_Expressions/05_Strings/1_String_Interpolation_A01_t04: Fail # Inherited from dart2js
+Language/10_Expressions/05_Strings/1_String_Interpolation_A01_t05: Fail # Inherited from dart2js
+Language/10_Expressions/05_Strings/1_String_Interpolation_A01_t06: Fail # Inherited from dart2js
 Language/10_Expressions/05_Strings/1_String_Interpolation_A01_t09: Fail, OK # co19 issue 210
 Language/10_Expressions/05_Strings/1_String_Interpolation_A03_t02: Fail # inherited from VM
 Language/10_Expressions/05_Strings/1_String_Interpolation_A04_t02: Fail # inherited from VM
@@ -314,6 +246,7 @@
 Language/10_Expressions/05_Strings_A02_t47: Fail # inherited from VM
 Language/10_Expressions/05_Strings_A02_t48: Fail # inherited from VM
 Language/10_Expressions/05_Strings_A02_t49: Fail # inherited from VM
+Language/10_Expressions/05_Strings_A12_t01: Fail # Inherited from dart2js
 Language/10_Expressions/05_Strings_A20_t01: Fail # inherited from VM
 Language/10_Expressions/06_Lists_A03_t01: Fail # http://dartbug.com/5519
 Language/10_Expressions/06_Lists_A03_t02: Fail # http://dartbug.com/5519
@@ -335,11 +268,19 @@
 Language/10_Expressions/11_Instance_Creation/1_New_A02_t05: Fail # inherited from dart2js
 Language/10_Expressions/11_Instance_Creation/1_New_A02_t06: Fail # inherited from dart2js
 Language/10_Expressions/11_Instance_Creation/1_New_A02_t07: Fail # inherited from dart2js
+Language/10_Expressions/11_Instance_Creation/1_New_A06_t06: Fail # Inherited from dart2js
+Language/10_Expressions/11_Instance_Creation/1_New_A07_t01: Fail # Inherited from dart2js
 Language/10_Expressions/11_Instance_Creation/1_New_A09_t09: Fail # inherited from VM
+Language/10_Expressions/11_Instance_Creation/1_New_A11_t01: Fail # Inherited from VM
+Language/10_Expressions/11_Instance_Creation/1_New_A12_t01: Fail # co19 issue 255: unmatched bracket (same behavior in dart2js)
+Language/10_Expressions/11_Instance_Creation/1_New_A12_t02: Fail # Inherited from VM
+Language/10_Expressions/11_Instance_Creation/1_New_A13_t04: Fail # Inherited from VM
+Language/10_Expressions/11_Instance_Creation/1_New_A14_t01: Fail # Inherited from dart2js
 Language/10_Expressions/11_Instance_Creation/2_Const_A01_t02: Fail # http://dartbug.com/5519
 Language/10_Expressions/11_Instance_Creation/2_Const_A06_t01: Fail # http://dartbug.com/5519
 Language/10_Expressions/11_Instance_Creation/2_Const_A06_t02: Fail # http://dartbug.com/5519
 Language/10_Expressions/11_Instance_Creation/2_Const_A10_t01: Fail # inherited from VM
+Language/10_Expressions/13_Property_Extraction_A01_t01: Fail # co19 issue 255: unmatched bracket (same behavior in dart2js)
 Language/10_Expressions/14_Function_Invocation/2_Binding_Actuals_to_Formals_A04_t01: Fail # http://dartbug.com/5519
 Language/10_Expressions/14_Function_Invocation/3_Unqualified_Invocation_A01_t03: Fail # inherited from VM
 Language/10_Expressions/14_Function_Invocation/3_Unqualified_Invocation_A01_t04: Fail  # co19 issue 166
@@ -365,12 +306,12 @@
 Language/10_Expressions/15_Method_Invocation/4_Super_Invocation_A02_t04: Fail # co19 issue 251 or issue 5732
 Language/10_Expressions/15_Method_Invocation/4_Super_Invocation_A03_t02: Fail # co19 issue 251 or issue 5732
 Language/10_Expressions/15_Method_Invocation/4_Super_Invocation_A03_t03: Fail # co19 issue 251 or issue 5732
-Language/10_Expressions/15_Method_Invocation/4_Super_Invocation_A07_t01: Fail # co19 issue 251 or issue 5732
-Language/10_Expressions/15_Method_Invocation/4_Super_Invocation_A08_t02: Fail # co19 issue 251 or issue 5732
 Language/10_Expressions/15_Method_Invocation/4_Super_Invocation_A04_t01: Fail # inherited from VM
 Language/10_Expressions/15_Method_Invocation/4_Super_Invocation_A04_t02: Fail # inherited from VM
 Language/10_Expressions/15_Method_Invocation/4_Super_Invocation_A04_t03: Fail # inherited from VM
 Language/10_Expressions/15_Method_Invocation/4_Super_Invocation_A04_t04: Fail # inherited from VM
+Language/10_Expressions/15_Method_Invocation/4_Super_Invocation_A07_t01: Fail # co19 issue 251 or issue 5732
+Language/10_Expressions/15_Method_Invocation/4_Super_Invocation_A08_t02: Fail # co19 issue 251 or issue 5732
 Language/10_Expressions/17_Getter_Invocation_A01_t03: Fail # inherited from VM
 Language/10_Expressions/17_Getter_Invocation_A02_t01: Fail # inherited from VM
 Language/10_Expressions/17_Getter_Invocation_A02_t02: Fail # inherited from VM
@@ -378,34 +319,86 @@
 Language/10_Expressions/18_Assignment_A05_t04: Fail # inherited from VM
 Language/10_Expressions/18_Assignment_A05_t05: Fail # inherited from VM
 Language/10_Expressions/18_Assignment_A08_t04: Fail # inherited from VM
+Language/10_Expressions/19_Conditional_A01_t10: Fail # Inherited from dart2js
+Language/10_Expressions/19_Conditional_A01_t11: Fail # Inherited from dart2js
+Language/10_Expressions/19_Conditional_A01_t12: Fail # Inherited from dart2js
+Language/10_Expressions/19_Conditional_A01_t13: Fail # Inherited from dart2js
+Language/10_Expressions/19_Conditional_A01_t14: Fail # Inherited from dart2js
+Language/10_Expressions/19_Conditional_A01_t15: Fail # Inherited from dart2js
 Language/10_Expressions/20_Logical_Boolean_Expressions_A01_t01: Fail # inherited from VM
+Language/10_Expressions/20_Logical_Boolean_Expressions_A01_t11: Fail # Inherited from dart2js
 Language/10_Expressions/20_Logical_Boolean_Expressions_A01_t12: Fail # http://dartbug.com/5519
+Language/10_Expressions/20_Logical_Boolean_Expressions_A01_t13: Fail # Inherited from dart2js
+Language/10_Expressions/20_Logical_Boolean_Expressions_A01_t14: Fail # Inherited from dart2js
 Language/10_Expressions/21_Bitwise_Expressions_A01_t01: Fail # inherited from VM
+Language/10_Expressions/21_Bitwise_Expressions_A01_t13: Fail # Inherited from dart2js
 Language/10_Expressions/21_Bitwise_Expressions_A01_t14: Fail # http://dartbug.com/5519
-Language/10_Expressions/22_Equality_A01_t01: Fail # inherited from VM
-Language/10_Expressions/22_Equality_A01_t15: Fail # http://dartbug.com/5519
-Language/10_Expressions/22_Equality_A01_t16: Fail # http://dartbug.com/5519
-Language/10_Expressions/22_Equality_A01_t19: Fail # http://dartbug.com/5519
-Language/10_Expressions/22_Equality_A02_t03: Fail # inherited from VM
-Language/10_Expressions/22_Equality_A03_t01: Fail # inherited from VM
-Language/10_Expressions/22_Equality_A03_t03: Fail # inherited from VM
-Language/10_Expressions/22_Equality_A05_t01: Fail # inherited from VM
+Language/10_Expressions/21_Bitwise_Expressions_A01_t15: Fail # Inherited from dart2js
+Language/10_Expressions/21_Bitwise_Expressions_A01_t16: Fail # Inherited from dart2js
+Language/10_Expressions/21_Bitwise_Expressions_A01_t17: Fail # Inherited from dart2js
 Language/10_Expressions/21_Relational_Expressions_A01_t01: Fail # inherited from VM
 Language/10_Expressions/21_Relational_Expressions_A01_t10: Fail # http://dartbug.com/5519
 Language/10_Expressions/21_Relational_Expressions_A01_t11: Fail # http://dartbug.com/5519
 Language/10_Expressions/21_Relational_Expressions_A01_t12: Fail # http://dartbug.com/5519
 Language/10_Expressions/21_Relational_Expressions_A01_t13: Fail # http://dartbug.com/5519
+Language/10_Expressions/21_Relational_Expressions_A01_t19: Fail # Inherited from dart2js
 Language/10_Expressions/21_Relational_Expressions_A01_t20: Fail # http://dartbug.com/5519
+Language/10_Expressions/21_Relational_Expressions_A01_t21: Fail # Inherited from dart2js
+Language/10_Expressions/21_Relational_Expressions_A01_t22: Fail # Inherited from dart2js
+Language/10_Expressions/21_Relational_Expressions_A01_t23: Fail # Inherited from dart2js
+Language/10_Expressions/22_Equality_A01_t01: Fail # inherited from VM
+Language/10_Expressions/22_Equality_A01_t15: Fail # http://dartbug.com/5519
+Language/10_Expressions/22_Equality_A01_t16: Fail # http://dartbug.com/5519
+Language/10_Expressions/22_Equality_A01_t19: Fail # http://dartbug.com/5519
+Language/10_Expressions/22_Equality_A01_t23: Fail # Inherited from dart2js
+Language/10_Expressions/22_Equality_A01_t24: Fail # Inherited from dart2js
+Language/10_Expressions/22_Equality_A02_t03: Fail # inherited from VM
+Language/10_Expressions/22_Equality_A03_t01: Fail # inherited from VM
+Language/10_Expressions/22_Equality_A03_t02: Fail # Inherited from dart2js
+Language/10_Expressions/22_Equality_A03_t03: Fail # inherited from VM
+Language/10_Expressions/22_Equality_A05_t01: Fail # inherited from VM
 Language/10_Expressions/22_Shift_A01_t01: Fail # inherited from VM
+Language/10_Expressions/22_Shift_A01_t10: Fail # Inherited from dart2js
 Language/10_Expressions/22_Shift_A01_t11: Fail # http://dartbug.com/5519
+Language/10_Expressions/22_Shift_A01_t12: Fail # Inherited from dart2js
+Language/10_Expressions/22_Shift_A01_t13: Fail # Inherited from dart2js
+Language/10_Expressions/22_Shift_A01_t14: Fail # Inherited from dart2js
+Language/10_Expressions/23_Additive_Expressions_A01_t08: Fail # Inherited from dart2js
+Language/10_Expressions/23_Additive_Expressions_A01_t11: Fail # Inherited from dart2js
+Language/10_Expressions/23_Additive_Expressions_A01_t12: Fail # Inherited from dart2js
+Language/10_Expressions/23_Additive_Expressions_A01_t13: Fail # Inherited from dart2js
+Language/10_Expressions/23_Additive_Expressions_A01_t14: Fail # Inherited from dart2js
+Language/10_Expressions/24_Multiplicative_Expressions_A01_t11: Fail # Inherited from dart2js
+Language/10_Expressions/24_Multiplicative_Expressions_A01_t14: Fail # Inherited from dart2js
+Language/10_Expressions/24_Multiplicative_Expressions_A01_t15: Fail # Inherited from dart2js
+Language/10_Expressions/24_Multiplicative_Expressions_A01_t16: Fail # Inherited from dart2js
+Language/10_Expressions/24_Multiplicative_Expressions_A01_t17: Fail # Inherited from dart2js
 Language/10_Expressions/25_Unary_Expressions_A01_t01: Fail # inherited from VM
+Language/10_Expressions/25_Unary_Expressions_A01_t02: Fail # Inherited from dart2js
+Language/10_Expressions/25_Unary_Expressions_A01_t04: Fail # Inherited from dart2js
+Language/10_Expressions/25_Unary_Expressions_A01_t05: Fail # Inherited from dart2js
 Language/10_Expressions/25_Unary_Expressions_A01_t10: Fail # inherited from VM
+Language/10_Expressions/25_Unary_Expressions_A01_t17: Fail # Inherited from dart2js
+Language/10_Expressions/25_Unary_Expressions_A01_t18: Fail # Inherited from dart2js
+Language/10_Expressions/25_Unary_Expressions_A01_t19: Fail # Inherited from dart2js
+Language/10_Expressions/25_Unary_Expressions_A01_t20: Fail # Inherited from dart2js
+Language/10_Expressions/25_Unary_Expressions_A01_t21: Fail # Inherited from dart2js
+Language/10_Expressions/25_Unary_Expressions_A01_t22: Fail # Inherited from dart2js
 Language/10_Expressions/25_Unary_Expressions_A06_t01: Fail # inherited from VM
 Language/10_Expressions/25_Unary_Expressions_A08_t01: Fail # inherited from VM
 Language/10_Expressions/26_Postfix_Expressions_A01_t01: Fail # inherited from VM
+Language/10_Expressions/26_Postfix_Expressions_A01_t02: Fail # Inherited from dart2js
+Language/10_Expressions/26_Postfix_Expressions_A01_t03: Fail # Inherited from dart2js
+Language/10_Expressions/26_Postfix_Expressions_A01_t05: Fail # Inherited from dart2js
+Language/10_Expressions/27_Assignable_Expressions_A01_t06: Fail # Inherited from dart2js
+Language/10_Expressions/27_Assignable_Expressions_A01_t08: Fail # Inherited from dart2js
+Language/10_Expressions/27_Assignable_Expressions_A01_t09: Fail # Inherited from dart2js
 Language/10_Expressions/27_Assignable_Expressions_A01_t26: Fail # inherited from VM
 Language/10_Expressions/27_Assignable_Expressions_A01_t27: Fail # inherited from VM
 Language/10_Expressions/28_Identifier_Reference_A02_t01: Fail # Pseudo keyword "abstract".
+Language/10_Expressions/28_Identifier_Reference_A04_t01: Fail # Inherited from dart2js
+Language/10_Expressions/28_Identifier_Reference_A04_t03: Fail # Inherited from dart2js
+Language/10_Expressions/28_Identifier_Reference_A04_t06: Fail # Inherited from dart2js
 Language/10_Expressions/28_Identifier_Reference_A04_t07: Fail, OK # co19 issue 184
 Language/10_Expressions/28_Identifier_Reference_A05_t09: Fail # inherited from VM
 Language/10_Expressions/28_Identifier_Reference_A06_t07: Fail # inherited from VM
@@ -421,6 +414,7 @@
 Language/10_Expressions/28_Identifier_Reference_A08_t32: Fail # inherited from dart2js
 Language/10_Expressions/28_Identifier_Reference_A08_t38: Fail, Pass # co19 issue 218
 Language/10_Expressions/29_Type_Test_A01_t02: Fail # http://dartbug.com/5519
+Language/10_Expressions/29_Type_Test_A01_t04: Fail # Inherited from dart2js
 Language/10_Expressions/29_Type_Test_A04_t01: Fail # inherited from dart2js
 Language/10_Expressions/30_Type_Cast_A01_t04: Fail # http://dartbug.com/5519
 Language/10_Expressions/30_Type_Cast_A03_t01: Fail # http://dartbug.com/5029
@@ -477,23 +471,18 @@
 Language/11_Statements/15_Assert_A01_t05: Fail # http://dartbug.com/5519
 Language/13_Libraries_and_Scripts/13_Libraries_and_Scripts_A05_t04: Fail # inherited from VM
 Language/13_Libraries_and_Scripts/2_Imports_A01_t39: Fail # inherited from VM
-Language/13_Libraries_and_Scripts/2_Imports_A01_t40: Fail # inherited from VM
 Language/13_Libraries_and_Scripts/2_Imports_A02_t01: Fail # inherited from VM
 Language/13_Libraries_and_Scripts/2_Imports_A02_t02: Fail # inherited from VM
-Language/13_Libraries_and_Scripts/2_Imports_A02_t11: Fail # inherited from VM
-Language/13_Libraries_and_Scripts/2_Imports_A02_t14: Fail # inherited from VM
 Language/13_Libraries_and_Scripts/2_Imports_A02_t16: Fail # inherited from VM
 Language/13_Libraries_and_Scripts/2_Imports_A02_t17: Fail # inherited from VM
 Language/13_Libraries_and_Scripts/2_Imports_A02_t18: Fail # inherited from VM
+Language/13_Libraries_and_Scripts/2_Imports_A02_t19: Fail # Inherited from VM
 Language/13_Libraries_and_Scripts/2_Imports_A02_t28: Fail # inherited from dart2js
 Language/13_Libraries_and_Scripts/2_Imports_A03_t02: Fail # inherited from VM
-Language/13_Libraries_and_Scripts/2_Imports_A03_t04: Fail # inherited from dart2js
 Language/13_Libraries_and_Scripts/2_Imports_A03_t06: Fail # inherited from dart2js
 Language/13_Libraries_and_Scripts/2_Imports_A03_t12: Fail # inherited from VM
-Language/13_Libraries_and_Scripts/2_Imports_A03_t14: Fail # inherited from VM
 Language/13_Libraries_and_Scripts/2_Imports_A03_t16: Fail # co19 issue 226
 Language/13_Libraries_and_Scripts/2_Imports_A03_t22: Fail # inherited from VM
-Language/13_Libraries_and_Scripts/2_Imports_A03_t24: Fail # inherited from VM
 Language/13_Libraries_and_Scripts/2_Imports_A03_t26: Fail # co19 issue 226
 Language/13_Libraries_and_Scripts/2_Imports_A06_t01: Fail # inherited from dart2js
 Language/13_Libraries_and_Scripts/3_Includes_A01_t01: Fail # inherited from dart2js
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index a9b3884..d43d6e2 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -123,10 +123,6 @@
 Language/10_Expressions/29_Type_Test_A01_t02: Fail # TODO(ahe): Please triage this failure.
 Language/10_Expressions/29_Type_Test_A01_t04: Fail # TODO(ahe): Please triage this failure.
 Language/11_Statements/09_Try_A01_t18: Fail # TODO(ahe): Please triage this failure.
-Language/13_Libraries_and_Scripts/2_Imports_A01_t49: Fail # TODO(ahe): Please triage this failure.
-Language/13_Libraries_and_Scripts/2_Imports_A02_t12: Fail # TODO(ahe): Please triage this failure.
-Language/13_Libraries_and_Scripts/2_Imports_A02_t13: Fail # TODO(ahe): Please triage this failure.
-Language/13_Libraries_and_Scripts/2_Imports_A02_t15: Fail # TODO(ahe): Please triage this failure.
 Language/13_Libraries_and_Scripts/2_Imports_A02_t19: Fail # TODO(ahe): Please triage this failure.
 Language/13_Libraries_and_Scripts/2_Imports_A02_t28: Fail # TODO(ahe): Please triage this failure.
 Language/15_Reference/1_Lexical_Rules/1_Reserved_Words_A30_t05: Fail # TODO(ahe): Please triage this failure.
@@ -420,6 +416,7 @@
 
 Language/13_Libraries_and_Scripts/2_Imports_A06_t01: Fail, OK # co19 issue 250
 
+Language/13_Libraries_and_Scripts/2_Imports_A01_t39: Fail # co19 issue 253: Show combinators are intersections.
 
 [ $compiler == dart2js && $runtime == d8 ]
 LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A04_t01: Fail, Pass # issue 3333
@@ -721,14 +718,7 @@
 Language/14_Types/5_Function_Types_A01_t22: Fail # http://dartbug.com/5022
 Language/14_Types/5_Function_Types_A01_t23: Fail # http://dartbug.com/5022
 
-Language/13_Libraries_and_Scripts/2_Imports_A01_t39: Fail # http://dartbug.com/4050. Combinators not implemented yet.
-Language/13_Libraries_and_Scripts/2_Imports_A01_t40: Fail # http://dartbug.com/4050. Combinators not implemented yet.
-Language/13_Libraries_and_Scripts/2_Imports_A02_t11: Fail # http://dartbug.com/4050. Combinators not implemented yet.
-Language/13_Libraries_and_Scripts/2_Imports_A02_t14: Fail # http://dartbug.com/4050. Combinators not implemented yet.
-Language/13_Libraries_and_Scripts/2_Imports_A02_t18: Fail # http://dartbug.com/4050. Combinators not implemented yet.
-Language/13_Libraries_and_Scripts/2_Imports_A03_t04: Fail # http://dartbug.com/4050. Combinators not implemented yet.
-Language/13_Libraries_and_Scripts/2_Imports_A03_t14: Fail # http://dartbug.com/4050. Combinators not implemented yet.
-Language/13_Libraries_and_Scripts/2_Imports_A03_t24: Fail # http://dartbug.com/4050. Combinators not implemented yet.
+Language/13_Libraries_and_Scripts/2_Imports_A02_t18: Fail # http://dartbug.com/3970. Redirecting factory constructors not implemented yet.
 
 Language/13_Libraries_and_Scripts/4_Scripts_A03_t01: Fail # http://dartbug.com/5683
 Language/13_Libraries_and_Scripts/4_Scripts_A03_t03: Fail # http://dartbug.com/5683
diff --git a/tests/compiler/dart2js/compiler_helper.dart b/tests/compiler/dart2js/compiler_helper.dart
index 6bc228c..057a3aa 100644
--- a/tests/compiler/dart2js/compiler_helper.dart
+++ b/tests/compiler/dart2js/compiler_helper.dart
@@ -18,9 +18,11 @@
 #import("parser_helper.dart");
 
 String compile(String code, [String entry = 'main',
-                             bool enableTypeAssertions = false]) {
+                             bool enableTypeAssertions = false,
+                             bool minify = false]) {
   MockCompiler compiler =
-      new MockCompiler(enableTypeAssertions: enableTypeAssertions);
+      new MockCompiler(enableTypeAssertions: enableTypeAssertions,
+                       enableMinification: minify);
   compiler.parseScript(code);
   lego.Element element = compiler.mainApp.find(buildSourceString(entry));
   if (element === null) return null;
diff --git a/tests/compiler/dart2js/concrete_type_inference_test.dart b/tests/compiler/dart2js/concrete_type_inference_test.dart
index 99ad0f4..9c303165 100644
--- a/tests/compiler/dart2js/concrete_type_inference_test.dart
+++ b/tests/compiler/dart2js/concrete_type_inference_test.dart
@@ -50,22 +50,22 @@
 
 void testBasicTypes() {
   checkPrintType('true', (compiler, type) {
-    Expect.identical(compiler.boolClass, type);
+    Expect.identical(compiler.boolClass, type.getUniqueType());
   });
   checkPrintType('1.0', (compiler, type) {
-    Expect.identical(compiler.doubleClass, type);
+    Expect.identical(compiler.doubleClass, type.getUniqueType());
   });
   checkPrintType('1', (compiler, type) {
-    Expect.identical(compiler.intClass, type);
+    Expect.identical(compiler.intClass, type.getUniqueType());
   });
   checkPrintType('[]', (compiler, type) {
-    Expect.identical(compiler.listClass, type);
+    Expect.identical(compiler.listClass, type.getUniqueType());
   });
   checkPrintType('null', (compiler, type) {
-    Expect.identical(compiler.nullClass, type);
+    Expect.identical(compiler.nullClass, type.getUniqueType());
   });
   checkPrintType('"foo"', (compiler, type) {
-    Expect.identical(compiler.stringClass, type);
+    Expect.identical(compiler.stringClass, type.getUniqueType());
   });
 }
 
@@ -82,7 +82,8 @@
           fiskElement.computeSignature(compiler).optionalParameters.tail.head;
         Expect.identical(
             compiler.intClass,
-            compiler.typesTask.getGuaranteedTypeOfElement(firstParameter));
+            compiler.typesTask.getGuaranteedTypeOfElement(firstParameter)
+                .getUniqueType());
         Expect.isNull(
             compiler.typesTask.getGuaranteedTypeOfElement(secondParameter));
         Expect.isNull(
diff --git a/tests/compiler/dart2js/dart2js.status b/tests/compiler/dart2js/dart2js.status
index 6aab1df..f63da2e 100644
--- a/tests/compiler/dart2js/dart2js.status
+++ b/tests/compiler/dart2js/dart2js.status
@@ -2,6 +2,8 @@
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
 
+link_test: Fail # TODO(ahe): I'm fixing this.
+
 constant_folding_string_test: Fail
 redundant_phi_eliminator_test: Fail # Fails because of hack to allow aborting loops.
 pretty_parameter_test: Fail # TODO(floitsch): investigate.
diff --git a/tests/compiler/dart2js/minify_many_locals_test.dart b/tests/compiler/dart2js/minify_many_locals_test.dart
new file mode 100644
index 0000000..e25b249
--- /dev/null
+++ b/tests/compiler/dart2js/minify_many_locals_test.dart
@@ -0,0 +1,40 @@
+// 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.
+// Test that parameters keep their names in the output.
+
+#import("compiler_helper.dart");
+
+main() {
+  var buffer = new StringBuffer();
+  buffer.add("var foo(");
+  for (int i = 0; i < 2000; i++) {
+    buffer.add("x$i, ");
+  }
+  buffer.add("x) { int i = ");
+  for (int i = 0; i < 2000; i++) {
+    buffer.add("x$i+");
+  }
+  buffer.add("2000; return i; }");
+  var generated = compile(buffer.toString(), 'foo', minify: true);
+  RegExp re = const RegExp(r"\(a,b,c");
+  Expect.isTrue(re.hasMatch(generated));
+
+  re = const RegExp(r"x,y,z,A,B,C");
+  Expect.isTrue(re.hasMatch(generated));
+  
+  re = const RegExp(r"Y,Z,a0,a1,a2,a3,a4,a5,a6");
+  Expect.isTrue(re.hasMatch(generated));
+
+  re = const RegExp(r"g8,g9,h0,h1");
+  Expect.isTrue(re.hasMatch(generated));
+
+  re = const RegExp(r"Z8,Z9,aa0,aa1,aa2");
+  Expect.isTrue(re.hasMatch(generated));
+
+  re = const RegExp(r"aa9,ab0,ab1");
+  Expect.isTrue(re.hasMatch(generated));
+
+  re = const RegExp(r"aZ9,ba0,ba1");
+  Expect.isTrue(re.hasMatch(generated));
+}
diff --git a/tests/compiler/dart2js/mock_compiler.dart b/tests/compiler/dart2js/mock_compiler.dart
index 1ed2b03..a3aa2df 100644
--- a/tests/compiler/dart2js/mock_compiler.dart
+++ b/tests/compiler/dart2js/mock_compiler.dart
@@ -77,10 +77,12 @@
   MockCompiler([String coreSource = DEFAULT_CORELIB,
                 String helperSource = DEFAULT_HELPERLIB,
                 String interceptorsSource = DEFAULT_INTERCEPTORSLIB,
-                bool enableTypeAssertions = false])
+                bool enableTypeAssertions = false,
+                bool enableMinification = false])
       : warnings = [], errors = [],
         sourceFiles = new Map<String, SourceFile>(),
-        super(enableTypeAssertions: enableTypeAssertions) {
+        super(enableTypeAssertions: enableTypeAssertions,
+              enableMinification: enableMinification) {
     coreLibrary = createLibrary("core", coreSource);
     // We need to set the assert method to avoid calls with a 'null'
     // target being interpreted as a call to assert.
diff --git a/tests/compiler/dart2js/unparser_test.dart b/tests/compiler/dart2js/unparser_test.dart
index ddf2b6b..af53532 100644
--- a/tests/compiler/dart2js/unparser_test.dart
+++ b/tests/compiler/dart2js/unparser_test.dart
@@ -243,6 +243,11 @@
   testUnparseMember("external const factory Foo() = prefix.Bar<T>.baz;");
 }
 
+testClassDeclarations() {
+  testUnparseTopLevelWithMetadata('class Foo{}');
+  testUnparseTopLevelWithMetadata('abstract class Foo{}');
+}
+
 main() {
   testSignedConstants();
   testGenericTypes();
@@ -261,4 +266,5 @@
   testPartOf();
   testCombinators();
   testRedirectingFactoryConstructors();
+  testClassDeclarations();
 }
diff --git a/tests/compiler/dart2js_extra/dart2js_extra.status b/tests/compiler/dart2js_extra/dart2js_extra.status
index 28c4887..9d53c1c 100644
--- a/tests/compiler/dart2js_extra/dart2js_extra.status
+++ b/tests/compiler/dart2js_extra/dart2js_extra.status
@@ -10,6 +10,9 @@
 inline_position_crash_test: Fail # http://www.dartbug.com/3905
 constant_javascript_semantics3_test: Fail # http://www.dartbug.com/5581
 
+[ $compiler == dart2js && $runtime == ff && $system == windows ]
+regress/4740_test: Fail
+
 [ $compiler == dart2js && $checked ]
 parameter_bailout_test: Fail, OK
 variable_type_test/03: Fail, OK
diff --git a/tests/language/abstract_runtime_error_test.dart b/tests/language/abstract_runtime_error_test.dart
new file mode 100644
index 0000000..ceb973c
--- /dev/null
+++ b/tests/language/abstract_runtime_error_test.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test various conditions around instantiating an abstract class.
+
+// From The Dart Programming Langauge Specification, 11.11.1 "New":
+//   If q is a constructor of an abstract class then an
+//   AbstractClassInstantiation- Error is thrown.
+
+
+abstract class Interface {
+  void foo();
+}
+
+abstract class AbstractClass {
+  toString() => 'AbstractClass';
+}
+
+class ConcreteSubclass extends AbstractClass {
+  toString() => 'ConcreteSubclass';
+}
+
+class NonAbstractClass implements Interface {
+  toString() => 'NonAbstractClass';
+}
+
+Interface interface() => new Interface();
+
+AbstractClass abstractClass() => new AbstractClass();
+
+bool isAbstractClassInstantiationError(e) {
+  return e is AbstractClassInstantiationError;
+}
+
+void main() {
+  Expect.throws(interface, isAbstractClassInstantiationError,
+                "expected AbstractClassInstantiationError");
+  Expect.throws(abstractClass, isAbstractClassInstantiationError,
+                "expected AbstractClassInstantiationError");
+  Expect.stringEquals('ConcreteSubclass', '${new ConcreteSubclass()}');
+  Expect.stringEquals('NonAbstractClass', '${new NonAbstractClass()}');
+}
diff --git a/tests/language/first_class_types_lib1.dart b/tests/language/first_class_types_lib1.dart
new file mode 100644
index 0000000..baadc66
--- /dev/null
+++ b/tests/language/first_class_types_lib1.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library lib1;
+
+class A {}
diff --git a/tests/language/first_class_types_lib2.dart b/tests/language/first_class_types_lib2.dart
new file mode 100644
index 0000000..de943b7
--- /dev/null
+++ b/tests/language/first_class_types_lib2.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library lib2;
+
+class A {}
diff --git a/tests/language/first_class_types_libraries_test.dart b/tests/language/first_class_types_libraries_test.dart
new file mode 100644
index 0000000..b04c572
--- /dev/null
+++ b/tests/language/first_class_types_libraries_test.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'first_class_types_lib1.dart' as lib1;
+import 'first_class_types_lib2.dart' as lib2;
+
+class C<X> {}
+
+sameType(a, b) {
+  Expect.identical(a.runtimeType, b.runtimeType);
+}
+
+differentType(a, b) {
+  print("a: ${a.runtimeType}");
+  print("b: ${b.runtimeType}");
+  Expect.isFalse(identical(a.runtimeType, b.runtimeType));
+}
+
+main() {
+  sameType(new lib1.A(), new lib1.A());
+  differentType(new lib1.A(), new lib2.A());
+  differentType(new C<lib1.A>(), new C<lib2.A>());
+}
diff --git a/tests/language/language.status b/tests/language/language.status
index 70649bb..456875a 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -218,13 +218,13 @@
 import_combinators_test: Fail
 export_test: Fail # Issue 5785
 export_cyclic_test: Fail # Issue 5785
-call_test: Fail # Issue 5797
+first_class_types_libraries_test: Fail # Issue 2264
 
 [ $runtime == dartium ]
 import_combinators_test: Fail
 
 
-[ $runtime == vm ]
+[ $runtime == vm || ($runtime == drt && $compiler == none) ]
 call_test: Fail # Issue 1604
 
 [ $runtime == chrome ]
@@ -308,7 +308,6 @@
 static_field3_test/03: Fail # http://dartbug.com/5519
 static_field3_test/04: Fail # http://dartbug.com/5519
 
-import_combinators_test: Fail
 throw_expr_test: Fail
 metadata_test: Fail
 # Fails in conservative mode, issue 4935, passes in minifinying mode.
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 16ffb2c..cf021ae 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -58,6 +58,7 @@
 compile_time_constant_checked3_test/06: Fail, OK
 
 [ $compiler == dart2js ]
+abstract_runtime_error_test: Fail # http://dartbug.com/4737
 bad_constructor_test/04: Fail # http://dartbug.com/5519
 bad_constructor_test/05: Fail # http://dartbug.com/5519
 bad_constructor_test/06: Fail # http://dartbug.com/5519
@@ -79,7 +80,6 @@
 
 execute_finally8_test: Fail # http://dartbug.com/5643
 
-import_combinators_test: Fail
 throw_expr_test: Fail
 metadata_test: Fail # Metadata on type parameters not supported.
 infinity_test: Fail # Issue 4984
@@ -153,7 +153,6 @@
 get_set_syntax_test/15: Fail # Fixed by https://chromiumcodereview.appspot.com/10915111
 get_set_syntax_test/16: Fail # Fixed by https://chromiumcodereview.appspot.com/10915111
 implicit_scope_test: Fail # duplicate definition of a="bar"
-lazy_static2_test: Fail # Issue 3559:  No support for closures in lazy initializers.
 library_prefixes_test: Fail # other is not a type
 local_function_test: Fail # TypeError: Object #<Closure> has no method '$call$2' (bad exception mapping).
 many_generic_instanceof_test: Fail # cannot resolve type T
@@ -362,3 +361,5 @@
 export_test: Fail # Issue 5785
 export_cyclic_test: Fail # Issue 5785
 generic_creation_test: Fail # Issue 5785l
+import_combinators_test: Fail # Issue 3454
+first_class_types_libraries_test: Fail
diff --git a/tests/language/lazy_static2_test.dart b/tests/language/lazy_static2_test.dart
index e422c30..b06db04 100644
--- a/tests/language/lazy_static2_test.dart
+++ b/tests/language/lazy_static2_test.dart
@@ -7,4 +7,4 @@
 main() {
   Expect.equals(499, x(498));
   Expect.equals(42, x(41));
-}
\ No newline at end of file
+}
diff --git a/tests/language/lazy_static6_src.dart b/tests/language/lazy_static6_src.dart
new file mode 100644
index 0000000..779d3d8
--- /dev/null
+++ b/tests/language/lazy_static6_src.dart
@@ -0,0 +1,27 @@
+// 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 lot of comments to make sure that the lazy initialization code has a
+ * position that does not fit into lazy_static6_test.dart file.
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+ */
+
+final x = (t) => (u) => t + u;
+
+main() {
+  Expect.equals(499, x(498)(1));
+  Expect.equals(42, x(39)(3));
+}
diff --git a/tests/language/lazy_static6_test.dart b/tests/language/lazy_static6_test.dart
new file mode 100644
index 0000000..0dec5dc
--- /dev/null
+++ b/tests/language/lazy_static6_test.dart
@@ -0,0 +1,5 @@
+// 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("lazy_static6_test");
+#source("lazy_static6_src.dart");
diff --git a/tests/standalone/byte_array_test.dart b/tests/standalone/byte_array_test.dart
index 2f60f29..1565488 100644
--- a/tests/standalone/byte_array_test.dart
+++ b/tests/standalone/byte_array_test.dart
@@ -78,11 +78,54 @@
   Expect.equals(-1, list.indexOf(20.0));
 }
 
+void testSubArray() {
+  var list = new Uint8List(10);
+  var array = list.asByteArray();
+  Expect.equals(0, array.subByteArray(0, 0).lengthInBytes());
+  Expect.equals(0, array.subByteArray(5, 0).lengthInBytes());
+  Expect.equals(0, array.subByteArray(10, 0).lengthInBytes());
+  Expect.equals(0, array.subByteArray(10).lengthInBytes());
+  Expect.equals(0, array.subByteArray(10, null).lengthInBytes());
+  Expect.equals(5, array.subByteArray(0, 5).lengthInBytes());
+  Expect.equals(5, array.subByteArray(5, 5).lengthInBytes());
+  Expect.equals(5, array.subByteArray(5).lengthInBytes());
+  Expect.equals(5, array.subByteArray(5, null).lengthInBytes());
+  Expect.equals(10, array.subByteArray(0, 10).lengthInBytes());
+  Expect.equals(10, array.subByteArray(0).lengthInBytes());
+  Expect.equals(10, array.subByteArray(0, null).lengthInBytes());
+  Expect.equals(10, array.subByteArray().lengthInBytes());
+  testThrowsIndex(function) {
+    Expect.throws(function, (e) => e is IndexOutOfRangeException);
+  }
+  testThrowsIndex(() => array.subByteArray(0, -1));
+  testThrowsIndex(() => array.subByteArray(1, -1));
+  testThrowsIndex(() => array.subByteArray(10, -1));
+  testThrowsIndex(() => array.subByteArray(-1, 0));
+  testThrowsIndex(() => array.subByteArray(-1));
+  testThrowsIndex(() => array.subByteArray(-1, null));
+  testThrowsIndex(() => array.subByteArray(11, 0));
+  testThrowsIndex(() => array.subByteArray(11));
+  testThrowsIndex(() => array.subByteArray(11, null));
+  testThrowsIndex(() => array.subByteArray(6, 5));
+
+  bool checkedMode = false;
+  assert(checkedMode = true);
+  if (!checkedMode) {
+    // In checked mode these will necessarily throw a TypeError.
+    Expect.throws(() => array.subByteArray(0, "5"), (e) => e is ArgumentError);
+    Expect.throws(() => array.subByteArray("0", 5), (e) => e is ArgumentError);
+    Expect.throws(() => array.subByteArray("0"), (e) => e is ArgumentError);
+  }
+  Expect.throws(() => array.subByteArray(null), (e) => e is ArgumentError);
+}
+
 main() {
   for (int i = 0; i < 2000; i++) {
     testCreateByteArray();
     testSetRange();
     testIndexOutOfRange();
     testIndexOf();
+    testSubArray();
   }
 }
+
diff --git a/tests/standalone/float_array_test.dart b/tests/standalone/float_array_test.dart
index dab3734..41b4f7e 100644
--- a/tests/standalone/float_array_test.dart
+++ b/tests/standalone/float_array_test.dart
@@ -9,7 +9,7 @@
 

 #import('dart:scalarlist');

 

-void testCreateFloatArray() {

+void testCreateFloat32Array() {

   Float32List floatArray;

 

   floatArray = new Float32List(0);

@@ -22,7 +22,7 @@
   }

 }

 

-void testSetRange() {

+void testSetRange32() {

   Float32List floatArray = new Float32List(3);

 

   List<num> list = [10.0, 11.0, 12.0];

@@ -39,13 +39,14 @@
     Expect.equals(20 + i, list[i]);

   }

 

-  floatArray.setRange(1, 2, const [8.0, 9.0]);

+  // 4.0e40 is larger than the largest representable float.

+  floatArray.setRange(1, 2, const [8.0, 4.0e40]);

   Expect.equals(20, floatArray[0]);

   Expect.equals(8, floatArray[1]);

-  Expect.equals(9, floatArray[2]);

+  Expect.equals(double.INFINITY, floatArray[2]);

 }

 

-void testIndexOutOfRange() {

+void testIndexOutOfRange32() {

   Float32List floatArray = new Float32List(3);

   List<num> list = const [0.0, 1.0, 2.0, 3.0];

 

@@ -61,7 +62,7 @@
   });

 }

 

-void testIndexOf() {

+void testIndexOf32() {

   var list = new Float32List(10);

   for (int i = 0; i < list.length; i++) {

     list[i] = i + 10.0;

@@ -81,11 +82,90 @@
   Expect.equals(-1, list.indexOf(20.0));

 }

 

+void testCreateFloat64Array() {

+  Float64List floatArray;

+

+  floatArray = new Float64List(0);

+  Expect.equals(0, floatArray.length);

+

+  floatArray = new Float64List(10);

+  Expect.equals(10, floatArray.length);

+  for (int i = 0; i < 10; i++) {

+    Expect.equals(0.0, floatArray[i]);

+  }

+}

+

+void testSetRange64() {

+  Float64List floatArray = new Float64List(3);

+

+  List<num> list = [10.0, 11.0, 12.0];

+  floatArray.setRange(0, 3, list);

+  for (int i = 0; i < 3; i++) {

+    Expect.equals(10 + i, floatArray[i]);

+  }

+

+  floatArray[0] = 20.0;

+  floatArray[1] = 21.0;

+  floatArray[2] = 22.0;

+  list.setRange(0, 3, floatArray);

+  for (int i = 0; i < 3; i++) {

+    Expect.equals(20 + i, list[i]);

+  }

+

+  // Unlike Float32Array we can properly represent 4.0e40

+  floatArray.setRange(1, 2, const [8.0, 4.0e40]);

+  Expect.equals(20, floatArray[0]);

+  Expect.equals(8, floatArray[1]);

+  Expect.equals(4.0e40, floatArray[2]);

+}

+

+void testIndexOutOfRange64() {

+  Float64List floatArray = new Float64List(3);

+  List<num> list = const [0.0, 1.0, 2.0, 3.0];

+

+  Expect.throws(() {

+    floatArray[5] = 2.0;

+  });

+  Expect.throws(() {

+    floatArray.setRange(0, 4, list);

+  });

+

+  Expect.throws(() {

+    floatArray.setRange(3, 1, list);

+  });

+}

+

+void testIndexOf64() {

+  var list = new Float64List(10);

+  for (int i = 0; i < list.length; i++) {

+    list[i] = i + 10.0;

+  }

+  Expect.equals(0, list.indexOf(10));

+  Expect.equals(5, list.indexOf(15));

+  Expect.equals(9, list.indexOf(19));

+  Expect.equals(-1, list.indexOf(20));

+

+  list = new Float64List(10);

+  for (int i = 0; i < list.length; i++) {

+    list[i] = i + 10.0;

+  }

+  Expect.equals(0, list.indexOf(10.0));

+  Expect.equals(5, list.indexOf(15.0));

+  Expect.equals(9, list.indexOf(19.0));

+  Expect.equals(-1, list.indexOf(20.0));

+}

+

 main() {

   for (int i = 0; i < 2000; i++) {

-    testCreateFloatArray();

-    testSetRange();

-    testIndexOutOfRange();

-    testIndexOf();

+    testCreateFloat32Array();

+    testSetRange32();

+    testIndexOutOfRange32();

+    testIndexOf32();

+  }

+  for (int i = 0; i < 2000; i++) {

+    testCreateFloat64Array();

+    testSetRange64();

+    testIndexOutOfRange64();

+    testIndexOf64();

   }

 }

diff --git a/tools/VERSION b/tools/VERSION
index bf439ec..82ee775 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
 MAJOR 0
 MINOR 1
-BUILD 1
+BUILD 3
 PATCH 0
diff --git a/tools/testing/dart/version.dart b/tools/release/version.dart
similarity index 73%
rename from tools/testing/dart/version.dart
rename to tools/release/version.dart
index dba3be3..5197f75 100644
--- a/tools/testing/dart/version.dart
+++ b/tools/release/version.dart
@@ -35,7 +35,9 @@
   int BUILD;
   int PATCH;
 
-  Version(String this._versionFileName);
+  Version(Path versionFile) {
+    _versionFileName = versionFile.toNativePath();
+  }
 
   /**
    * Get the version number for this specific build using the version info
@@ -95,14 +97,14 @@
         if (!c.future.isComplete) {
           getRevision().then((revision) {
             REVISION = revision;
-            getUserName().then((username) {
-              USERNAME = username;
-              if (username != '') username = "_$username";
-              var revisionString = "";
-              if (revision != 0) revisionString = "_r$revision";
-              c.complete("$MAJOR.$MINOR.$BUILD.$PATCH$revisionString$username");
-              return;
-            });
+            USERNAME = getUserName();
+            var userNameString = "";
+            if (USERNAME != '') userNameString = "_$USERNAME";
+            var revisionString = "";
+            if (revision != 0) revisionString = "_r$revision";
+            c.complete(
+                "$MAJOR.$MINOR.$BUILD.$PATCH$revisionString$userNameString");
+            return;
           });
         }
       };
@@ -110,40 +112,62 @@
     return c.future;
   }
 
+  String getExecutableSuffix() {
+    if (Platform.operatingSystem == 'windows') {
+      return '.bat';
+    }
+    return '';
+  }
+
+  int getRevisionFromSvnInfo(String info) {
+    if (info == null || info == '') return 0;
+    var lines = info.split("\n");
+    RegExp exp = const RegExp(r"Revision: (\d*)");
+    for (var line in lines) {
+      if (exp.hasMatch(line)) {
+        String revisionString = (exp.firstMatch(line).group(1));
+        try {
+          return int.parse(revisionString);
+        } catch(e) {
+          return 0;
+        }
+      }
+    }
+    return 0;
+  }
+
   Future<int> getRevision() {
     if (repositoryType == RepositoryType.UNKNOWN) {
       return new Future.immediate(0);
     }
     var isSvn = repositoryType == RepositoryType.SVN;
     var command = isSvn ? "svn" : "git";
+    command = "$command${getExecutableSuffix()}";
     var arguments = isSvn ? ["info"] : ["svn", "info"];
     return Process.run(command, arguments).transform((result) {
       if (result.exitCode != 0) {
         return 0;
       }
-      // If anything goes wrong parsing the revision we simply return 0.
-      try {
-        // Extract the revision. It's located at the 8th line,
-        // 18 characters in.
-        String revisionString = result.stdout.split("\n")[8].substring(18);
-        return int.parse(revisionString);
-      } catch (e) {
-        return 0;
-      }
+      return getRevisionFromSvnInfo(result.stdout);
     });
   }
 
-  Future<String> getUserName() {
+  bool isProductionBuild(String username) {
+    return username == "chrome-bot";
+  }
+
+  String getUserName() {
     // TODO(ricow): Don't add this on the buildbot.
-    // If we can't get the username simple return "" (e.g. on windows).
-    return Process.run("whoami", []).transform((result) {
-      if (result.exitCode != 0) {
-        return "";
-      }
-      return result.stdout;
-    }).transformException((e) {
-      return "";
-    });
+    var key = "USER";
+    if (Platform.operatingSystem == 'windows') {
+      key = "USERNAME";
+    }
+    if (!Platform.environment.containsKey(key)) return "";
+    var username = Platform.environment[key];
+    // If this is a production build, i.e., this is something we are shipping,
+    // don't suffix  the version with the username.
+    if (isProductionBuild(username)) return "";
+    return username;
   }
 
   RepositoryType get repositoryType {
diff --git a/tools/test.py b/tools/test.py
index bd16393..3ab247b 100755
--- a/tools/test.py
+++ b/tools/test.py
@@ -15,11 +15,6 @@
 def Main():
   args = sys.argv[1:]
   tools_dir = os.path.dirname(os.path.realpath(__file__))
-  dart_binary_prefix = os.path.join(tools_dir, 'testing', 'bin')
-  if utils.IsWindows():
-    dart_binary = os.path.join(dart_binary_prefix, 'windows', 'dart.exe')
-  else:
-    dart_binary = os.path.join(dart_binary_prefix, utils.GuessOS(), 'dart')
   current_directory = os.path.abspath('');
   client = os.path.abspath(os.path.join(tools_dir, '..'));
   if current_directory == os.path.join(client, 'runtime'):
@@ -27,7 +22,7 @@
   else:
     dart_script_name = 'test.dart'
   dart_test_script = string.join([tools_dir, dart_script_name], os.sep)
-  command = [dart_binary, dart_test_script] + args
+  command = [utils.DartBinary(), dart_test_script] + args
   exit_code = subprocess.call(command)
   utils.DiagnoseExitCode(exit_code, command)
   return exit_code
diff --git a/tools/touch_version.py b/tools/touch_version.py
new file mode 100644
index 0000000..98841fe
--- /dev/null
+++ b/tools/touch_version.py
@@ -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.
+#
+# This python script "touches" the tools/VERSION file.
+
+import os
+import sys
+
+# Change into the dart directory as we want to be able to access the VERSION file
+# from a simple path.
+runtime_src = os.path.join(os.path.dirname(sys.argv[0]), os.pardir)
+os.chdir(runtime_src)
+
+if __name__ == '__main__':
+  print 'Touching tools/VERSION.'
+  os.utime(os.path.join('tools', 'VERSION'), None)
+  sys.exit(0)
diff --git a/tools/utils.py b/tools/utils.py
index 1c6ef7f..2ae3821 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -297,6 +297,15 @@
     os.utime(name, None)
 
 
+def DartBinary():
+  tools_dir = os.path.dirname(os.path.realpath(__file__))
+  dart_binary_prefix = os.path.join(tools_dir, 'testing', 'bin')
+  if IsWindows():
+    return os.path.join(dart_binary_prefix, 'windows', 'dart.exe')
+  else:
+    return os.path.join(dart_binary_prefix, GuessOS(), 'dart')
+
+
 if __name__ == "__main__":
   import sys
   Main(sys.argv)
diff --git a/tools/version.dart b/tools/version.dart
index e08091c..0b4254c 100644
--- a/tools/version.dart
+++ b/tools/version.dart
@@ -1,11 +1,14 @@
+#!/usr/bin/env dart
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-#import("testing/dart/version.dart");
+import "dart:io";
+import "release/version.dart";
 
 void main() {
-  Version version = new Version("tools/VERSION");
+  Path scriptPath = new Path(new Options().script).directoryPath;
+  Version version = new Version(scriptPath.append("VERSION"));
   Future f = version.getVersion();
   f.then((currentVersion) {
     print(currentVersion);