Version 1.11.0-dev.5.0

Merge commit '7230007d526205d371bebddf69ee0167edc7569d' into dev
diff --git a/DEPS b/DEPS
index b6de9ff..5fb385f 100644
--- a/DEPS
+++ b/DEPS
@@ -38,7 +38,7 @@
 
   # Revisions of /third_party/* dependencies.
   "7zip_rev" : "@19997",
-  "analyzer_cli_tag" : "@1.0.1",
+  "analyzer_cli_rev" : "@090c4859a2f88e62ae71a11583ba31e9999c74f6",
   "args_tag": "@0.13.0",
   "barback_rev" : "@29ee90dbcf77cfd64632fa2797a4c8a4f29a4b51",
   "charcode_tag": "@1.1.0",
@@ -65,7 +65,7 @@
   "intl_rev": "@32047558bd220a53c1f4d93a26d54b83533b1475",
   "jinja2_rev": "@2222b31554f03e62600cd7e383376a7c187967a1",
   "json_rpc_2_rev": "@a38eefd116d910199de205f962af92fed87c164c",
-  "linter_tag": "@0.0.2+3",
+  "linter_tag": "@0.1.0",
   "logging_rev": "@85d83e002670545e9039ad3985f0018ab640e597",
   "markdown_rev": "@56b0fd6c018d6103862d07e8e27407b9ea3b963d",
   "matcher_tag": "@0.12.0",
@@ -82,7 +82,7 @@
   "ply_rev": "@604b32590ffad5cbb82e4afef1d305512d06ae93",
   "plugin_tag": "@0.1.0",
   "pool_rev": "@22e12aeb16ad0b626900dbe79e4a25391ddfb28c",
-  "pub_rev": "@f6d3dceb51789b6ba7ae28e87b667663792a7aa9",
+  "pub_rev": "@6f8ae035883550bfaa690be3aa96f0d2dd8787d7",
   "pub_semver_tag": "@1.2.1",
   "scheduled_test_tag": "@0.11.8+1",
   "shelf_rev": "@1e87b79b21ac5e6fa2f93576d6c06eaa65285ef4",
@@ -174,8 +174,8 @@
       (Var("github_mirror") % "dart-services") +
       Var("dart_services_rev"),
 
-  Var("dart_root") + "/third_party/pkg_tested/analyzer_cli":
-      (Var("github_mirror") % "analyzer_cli") + Var("analyzer_cli_tag"),
+  Var("dart_root") + "/third_party/pkg/analyzer_cli":
+      (Var("github_mirror") % "analyzer_cli") + Var("analyzer_cli_rev"),
   Var("dart_root") + "/third_party/pkg/args":
       (Var("github_mirror") % "args") + Var("args_tag"),
   Var("dart_root") + "/third_party/pkg/async_await":
diff --git a/pkg/analysis_server/lib/src/get_handler.dart b/pkg/analysis_server/lib/src/get_handler.dart
index 776f38a..983f689 100644
--- a/pkg/analysis_server/lib/src/get_handler.dart
+++ b/pkg/analysis_server/lib/src/get_handler.dart
@@ -30,6 +30,7 @@
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_general.dart';
+import 'package:analyzer/task/model.dart' as newTask;
 import 'package:plugin/plugin.dart';
 
 /**
@@ -262,6 +263,9 @@
           (StringBuffer buffer) {
         buffer.write('<h3>Analysis Performance</h3>');
 
+        //
+        // Write performance tags.
+        //
         {
           buffer.write('<p><b>Time spent in each phase of analysis</b></p>');
           buffer.write(
@@ -288,30 +292,74 @@
           buffer.write('</table>');
         }
 
-        Map<DataDescriptor, Map<CacheState, int>> transitionMap =
-            SourceEntry.transitionMap;
-        buffer.write(
-            '<p><b>Number of times a state transitioned to VALID (grouped by descriptor)</b></p>');
-        if (transitionMap.isEmpty) {
-          buffer.write('<p>none</p>');
-        } else {
-          List<DataDescriptor> descriptors = transitionMap.keys.toList();
-          descriptors.sort((DataDescriptor first, DataDescriptor second) =>
+        //
+        // Write new task model timing information.
+        //
+        if (AnalysisEngine.instance.useTaskModel) {
+          buffer.write('<p><b>Task performace data</b></p>');
+          buffer.write(
+              '<table style="border-collapse: separate; border-spacing: 10px 5px;">');
+          _writeRow(buffer, [
+            'Task Name',
+            'Count',
+            'Total Time (in ms)',
+            'Average Time (in ms)'
+          ], header: true);
+
+          Map<Type, int> countMap = newTask.AnalysisTask.countMap;
+          Map<Type, Stopwatch> stopwatchMap = newTask.AnalysisTask.stopwatchMap;
+          List<Type> taskClasses = stopwatchMap.keys.toList();
+          taskClasses.sort((Type first, Type second) =>
               first.toString().compareTo(second.toString()));
-          for (DataDescriptor key in descriptors) {
-            Map<CacheState, int> countMap = transitionMap[key];
-            List<CacheState> oldStates = countMap.keys.toList();
-            oldStates.sort((CacheState first, CacheState second) =>
-                first.toString().compareTo(second.toString()));
-            buffer.write('<p>${key.toString()}</p>');
-            buffer.write(
-                '<table style="border-collapse: separate; border-spacing: 10px 5px;">');
-            _writeRow(buffer, ['Count', 'Previous State'], header: true);
-            for (CacheState state in oldStates) {
-              _writeRow(buffer, [countMap[state], state.toString()],
-                  classes: ["right", null]);
+          int totalTime = 0;
+          taskClasses.forEach((Type taskClass) {
+            int count = countMap[taskClass];
+            if (count == null) {
+              count = 0;
             }
-            buffer.write('</table>');
+            int taskTime = stopwatchMap[taskClass].elapsedMilliseconds;
+            totalTime += taskTime;
+            _writeRow(buffer, [
+              taskClass.toString(),
+              count,
+              taskTime,
+              count <= 0 ? '-' : (taskTime / count).toStringAsFixed(3)
+            ], classes: [null, "right", "right", "right"]);
+          });
+          _writeRow(buffer, ['Total', '-', totalTime, '-'],
+              classes: [null, "right", "right", "right"]);
+          buffer.write('</table>');
+        }
+
+        //
+        // Write old task model transition information.
+        //
+        {
+          Map<DataDescriptor, Map<CacheState, int>> transitionMap =
+              SourceEntry.transitionMap;
+          buffer.write(
+              '<p><b>Number of times a state transitioned to VALID (grouped by descriptor)</b></p>');
+          if (transitionMap.isEmpty) {
+            buffer.write('<p>none</p>');
+          } else {
+            List<DataDescriptor> descriptors = transitionMap.keys.toList();
+            descriptors.sort((DataDescriptor first, DataDescriptor second) =>
+                first.toString().compareTo(second.toString()));
+            for (DataDescriptor key in descriptors) {
+              Map<CacheState, int> countMap = transitionMap[key];
+              List<CacheState> oldStates = countMap.keys.toList();
+              oldStates.sort((CacheState first, CacheState second) =>
+                  first.toString().compareTo(second.toString()));
+              buffer.write('<p>${key.toString()}</p>');
+              buffer.write(
+                  '<table style="border-collapse: separate; border-spacing: 10px 5px;">');
+              _writeRow(buffer, ['Count', 'Previous State'], header: true);
+              for (CacheState state in oldStates) {
+                _writeRow(buffer, [countMap[state], state.toString()],
+                    classes: ["right", null]);
+              }
+              buffer.write('</table>');
+            }
           }
         }
       });
diff --git a/pkg/analysis_server/lib/src/operation/operation_analysis.dart b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
index 6ac3935..918deb8 100644
--- a/pkg/analysis_server/lib/src/operation/operation_analysis.dart
+++ b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
@@ -326,8 +326,12 @@
   @override
   void perform(AnalysisServer server) {
     ServerPerformanceStatistics.indexOperation.makeCurrentWhile(() {
-      Index index = server.index;
-      index.indexUnit(context, unit);
+      try {
+        Index index = server.index;
+        index.indexUnit(context, unit);
+      } catch (exception, stackTrace) {
+        server.sendServerErrorNotification(exception, stackTrace);
+      }
     });
   }
 }
diff --git a/pkg/analysis_server/lib/src/protocol_server.dart b/pkg/analysis_server/lib/src/protocol_server.dart
index 071b678..f9e48c58 100644
--- a/pkg/analysis_server/lib/src/protocol_server.dart
+++ b/pkg/analysis_server/lib/src/protocol_server.dart
@@ -87,19 +87,14 @@
   String elementTypeParameters = _getTypeParametersString(element);
   String elementParameters = _getParametersString(element);
   String elementReturnType = _getReturnTypeString(element);
-  ElementKind kind = newElementKind_fromEngine(element.kind);
-  // TODO(danrubel) this check should be in newElementKind_fromEngine
-  if (element is engine.ClassElement && element.isEnum) {
-    kind = ElementKind.ENUM;
-  }
-  return new Element(kind, name, Element
-          .makeFlags(
-              isPrivate: element.isPrivate,
-              isDeprecated: element.isDeprecated,
-              isAbstract: _isAbstract(element),
-              isConst: _isConst(element),
-              isFinal: _isFinal(element),
-              isStatic: _isStatic(element)),
+  ElementKind kind = newElementKind_fromEngineElement(element);
+  return new Element(kind, name, Element.makeFlags(
+          isPrivate: element.isPrivate,
+          isDeprecated: element.isDeprecated,
+          isAbstract: _isAbstract(element),
+          isConst: _isConst(element),
+          isFinal: _isFinal(element),
+          isStatic: _isStatic(element)),
       location: newLocation_fromElement(element),
       typeParameters: elementTypeParameters,
       parameters: elementParameters,
@@ -108,10 +103,13 @@
 
 /**
  * Construct based on a value from the analyzer engine.
+ * This does not take into account that 
+ * instances of ClassElement can be an enum and
+ * instances of FieldElement can be an enum constant.
+ * Use [newElementKind_fromEngineElement] where possible.
  */
 ElementKind newElementKind_fromEngine(engine.ElementKind kind) {
   if (kind == engine.ElementKind.CLASS) {
-    // TODO(danrubel) check if element.isEnum and return ElementKind.ENUM
     return ElementKind.CLASS;
   }
   if (kind == engine.ElementKind.COMPILATION_UNIT) {
@@ -163,6 +161,29 @@
 }
 
 /**
+ * Construct based on a value from the analyzer engine.
+ */
+ElementKind newElementKind_fromEngineElement(engine.Element element) {
+  if (element is engine.ClassElement && element.isEnum) {
+    return ElementKind.ENUM;
+  }
+  if (element is engine.FieldElement && element.isEnumConstant &&
+      // MyEnum.values and MyEnum.one.index return isEnumConstant = true
+      // so these additional checks are necessary.
+      // TODO(danrubel) MyEnum.values is constant, but is a list
+      // so should it return isEnumConstant = true?
+      // MyEnum.one.index is final but *not* constant
+      // so should it return isEnumConstant = true?
+      // Or should we return ElementKind.ENUM_CONSTANT here
+      // in either or both of these cases?
+      element.type != null &&
+      element.type.element == element.enclosingElement) {
+    return ElementKind.ENUM_CONSTANT;
+  }
+  return newElementKind_fromEngine(element.kind);
+}
+
+/**
  * Create a Location based on an [engine.Element].
  */
 Location newLocation_fromElement(engine.Element element) {
diff --git a/pkg/analysis_server/lib/src/services/completion/local_reference_contributor.dart b/pkg/analysis_server/lib/src/services/completion/local_reference_contributor.dart
index 598a58a..7eca2b5 100644
--- a/pkg/analysis_server/lib/src/services/completion/local_reference_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/local_reference_contributor.dart
@@ -357,48 +357,28 @@
   @override
   void declaredClass(ClassDeclaration declaration) {
     if (optype.includeTypeNameSuggestions) {
-      bool deprecated = isDeprecated(declaration);
-      CompletionSuggestion suggestion = _addSuggestion(
-          declaration.name, NO_RETURN_TYPE, deprecated, DART_RELEVANCE_DEFAULT);
-      if (suggestion != null) {
-        suggestion.element = createElement(
-            protocol.ElementKind.CLASS, declaration.name,
-            returnType: NO_RETURN_TYPE,
-            isAbstract: declaration.isAbstract,
-            isDeprecated: deprecated);
-      }
+      _addSuggestion(
+          declaration.name, NO_RETURN_TYPE, protocol.ElementKind.CLASS,
+          isAbstract: declaration.isAbstract,
+          isDeprecated: isDeprecated(declaration));
     }
   }
 
   @override
   void declaredClassTypeAlias(ClassTypeAlias declaration) {
     if (optype.includeTypeNameSuggestions) {
-      bool deprecated = isDeprecated(declaration);
-      CompletionSuggestion suggestion = _addSuggestion(
-          declaration.name, NO_RETURN_TYPE, deprecated, DART_RELEVANCE_DEFAULT);
-      if (suggestion != null) {
-        suggestion.element = createElement(
-            protocol.ElementKind.CLASS_TYPE_ALIAS, declaration.name,
-            returnType: NO_RETURN_TYPE,
-            isAbstract: true,
-            isDeprecated: deprecated);
-      }
+      _addSuggestion(declaration.name, NO_RETURN_TYPE,
+          protocol.ElementKind.CLASS_TYPE_ALIAS,
+          isAbstract: true, isDeprecated: isDeprecated(declaration));
     }
   }
 
   @override
   void declaredEnum(EnumDeclaration declaration) {
-    SimpleIdentifier enumId = declaration.name;
-    if (enumId != null) {
-      bool deprecated = isDeprecated(declaration);
-      if (optype.includeTypeNameSuggestions) {
-        CompletionSuggestion suggestion = _addSuggestion(
-            enumId, NO_RETURN_TYPE, deprecated, DART_RELEVANCE_DEFAULT);
-        if (suggestion != null) {
-          suggestion.element = createElement(protocol.ElementKind.ENUM, enumId,
-              returnType: NO_RETURN_TYPE, isDeprecated: deprecated);
-        }
-      }
+    if (optype.includeTypeNameSuggestions) {
+      _addSuggestion(
+          declaration.name, NO_RETURN_TYPE, protocol.ElementKind.ENUM,
+          isDeprecated: isDeprecated(declaration));
     }
   }
 
@@ -417,56 +397,40 @@
   void declaredFunction(FunctionDeclaration declaration) {
     if (optype.includeReturnValueSuggestions ||
         optype.includeVoidReturnSuggestions) {
-      TypeName returnType = declaration.returnType;
-      bool deprecated = isDeprecated(declaration);
-      protocol.ElementKind kind;
-      int defaultRelevance = DART_RELEVANCE_DEFAULT;
+      TypeName typeName = declaration.returnType;
+      protocol.ElementKind elemKind;
+      int relevance = DART_RELEVANCE_DEFAULT;
       if (declaration.isGetter) {
-        kind = protocol.ElementKind.GETTER;
-        defaultRelevance = DART_RELEVANCE_LOCAL_ACCESSOR;
+        elemKind = protocol.ElementKind.GETTER;
+        relevance = DART_RELEVANCE_LOCAL_ACCESSOR;
       } else if (declaration.isSetter) {
         if (!optype.includeVoidReturnSuggestions) {
           return;
         }
-        kind = protocol.ElementKind.SETTER;
-        returnType = NO_RETURN_TYPE;
-        defaultRelevance = DART_RELEVANCE_LOCAL_ACCESSOR;
+        elemKind = protocol.ElementKind.SETTER;
+        typeName = NO_RETURN_TYPE;
+        relevance = DART_RELEVANCE_LOCAL_ACCESSOR;
       } else {
-        if (!optype.includeVoidReturnSuggestions && _isVoid(returnType)) {
+        if (!optype.includeVoidReturnSuggestions && _isVoid(typeName)) {
           return;
         }
-        kind = protocol.ElementKind.FUNCTION;
-        defaultRelevance = DART_RELEVANCE_LOCAL_FUNCTION;
+        elemKind = protocol.ElementKind.FUNCTION;
+        relevance = DART_RELEVANCE_LOCAL_FUNCTION;
       }
-      CompletionSuggestion suggestion = _addSuggestion(
-          declaration.name, returnType, deprecated, defaultRelevance);
-      if (suggestion != null) {
-        FormalParameterList param = declaration.functionExpression.parameters;
-        suggestion.element = createElement(kind, declaration.name,
-            parameters: param != null ? param.toSource() : null,
-            returnType: returnType,
-            isDeprecated: deprecated);
-        if (kind == protocol.ElementKind.FUNCTION) {
-          _addParameterInfo(
-              suggestion, declaration.functionExpression.parameters);
-        }
-      }
+      _addSuggestion(declaration.name, typeName, elemKind,
+          isDeprecated: isDeprecated(declaration),
+          param: declaration.functionExpression.parameters,
+          relevance: relevance);
     }
   }
 
   @override
   void declaredFunctionTypeAlias(FunctionTypeAlias declaration) {
     if (optype.includeTypeNameSuggestions) {
-      bool deprecated = isDeprecated(declaration);
-      TypeName returnType = declaration.returnType;
-      CompletionSuggestion suggestion = _addSuggestion(
-          declaration.name, returnType, deprecated, DART_RELEVANCE_DEFAULT);
-      if (suggestion != null) {
-        // TODO (danrubel) determine parameters and return type
-        suggestion.element = createElement(
-            protocol.ElementKind.FUNCTION_TYPE_ALIAS, declaration.name,
-            returnType: returnType, isAbstract: true, isDeprecated: deprecated);
-      }
+      // TODO (danrubel) determine parameters and return type
+      _addSuggestion(declaration.name, declaration.returnType,
+          protocol.ElementKind.FUNCTION_TYPE_ALIAS,
+          isAbstract: true, isDeprecated: isDeprecated(declaration));
     }
   }
 
@@ -476,14 +440,10 @@
   }
 
   @override
-  void declaredLocalVar(SimpleIdentifier name, TypeName type) {
+  void declaredLocalVar(SimpleIdentifier id, TypeName typeName) {
     if (optype.includeReturnValueSuggestions) {
-      CompletionSuggestion suggestion =
-          _addSuggestion(name, type, false, DART_RELEVANCE_LOCAL_VARIABLE);
-      if (suggestion != null) {
-        suggestion.element = createElement(
-            protocol.ElementKind.LOCAL_VARIABLE, name, returnType: type);
-      }
+      _addSuggestion(id, typeName, protocol.ElementKind.LOCAL_VARIABLE,
+          relevance: DART_RELEVANCE_LOCAL_VARIABLE);
     }
   }
 
@@ -491,55 +451,43 @@
   void declaredMethod(MethodDeclaration declaration) {
     if (optype.includeReturnValueSuggestions ||
         optype.includeVoidReturnSuggestions) {
-      protocol.ElementKind kind;
-      String parameters;
-      TypeName returnType = declaration.returnType;
-      int defaultRelevance = DART_RELEVANCE_DEFAULT;
+      protocol.ElementKind elemKind;
+      FormalParameterList param;
+      TypeName typeName = declaration.returnType;
+      int relevance = DART_RELEVANCE_DEFAULT;
       if (declaration.isGetter) {
-        kind = protocol.ElementKind.GETTER;
-        parameters = null;
-        defaultRelevance = DART_RELEVANCE_LOCAL_ACCESSOR;
+        elemKind = protocol.ElementKind.GETTER;
+        param = null;
+        relevance = DART_RELEVANCE_LOCAL_ACCESSOR;
       } else if (declaration.isSetter) {
         if (!optype.includeVoidReturnSuggestions) {
           return;
         }
-        kind = protocol.ElementKind.SETTER;
-        returnType = NO_RETURN_TYPE;
-        defaultRelevance = DART_RELEVANCE_LOCAL_ACCESSOR;
+        elemKind = protocol.ElementKind.SETTER;
+        typeName = NO_RETURN_TYPE;
+        relevance = DART_RELEVANCE_LOCAL_ACCESSOR;
       } else {
-        if (!optype.includeVoidReturnSuggestions && _isVoid(returnType)) {
+        if (!optype.includeVoidReturnSuggestions && _isVoid(typeName)) {
           return;
         }
-        kind = protocol.ElementKind.METHOD;
-        parameters = declaration.parameters.toSource();
-        defaultRelevance = DART_RELEVANCE_LOCAL_METHOD;
+        elemKind = protocol.ElementKind.METHOD;
+        param = declaration.parameters;
+        relevance = DART_RELEVANCE_LOCAL_METHOD;
       }
-      bool deprecated = isDeprecated(declaration);
-      CompletionSuggestion suggestion = _addSuggestion(
-          declaration.name, returnType, deprecated, defaultRelevance,
-          classDecl: declaration.parent);
-      if (suggestion != null) {
-        suggestion.element = createElement(kind, declaration.name,
-            parameters: parameters,
-            returnType: returnType,
-            isAbstract: declaration.isAbstract,
-            isDeprecated: deprecated);
-        if (kind == protocol.ElementKind.METHOD) {
-          _addParameterInfo(suggestion, declaration.parameters);
-        }
-      }
+      _addSuggestion(declaration.name, typeName, elemKind,
+          isAbstract: declaration.isAbstract,
+          isDeprecated: isDeprecated(declaration),
+          classDecl: declaration.parent,
+          param: param,
+          relevance: relevance);
     }
   }
 
   @override
-  void declaredParam(SimpleIdentifier name, TypeName type) {
+  void declaredParam(SimpleIdentifier id, TypeName typeName) {
     if (optype.includeReturnValueSuggestions) {
-      CompletionSuggestion suggestion =
-          _addSuggestion(name, type, false, DART_RELEVANCE_PARAMETER);
-      if (suggestion != null) {
-        suggestion.element = createElement(protocol.ElementKind.PARAMETER, name,
-            returnType: type);
-      }
+      _addSuggestion(id, typeName, protocol.ElementKind.PARAMETER,
+          relevance: DART_RELEVANCE_PARAMETER);
     }
   }
 
@@ -547,14 +495,10 @@
   void declaredTopLevelVar(
       VariableDeclarationList varList, VariableDeclaration varDecl) {
     if (optype.includeReturnValueSuggestions) {
-      bool deprecated = isDeprecated(varList) || isDeprecated(varDecl);
-      CompletionSuggestion suggestion = _addSuggestion(varDecl.name,
-          varList.type, deprecated, DART_RELEVANCE_LOCAL_TOP_LEVEL_VARIABLE);
-      if (suggestion != null) {
-        suggestion.element = createElement(
-            protocol.ElementKind.TOP_LEVEL_VARIABLE, varDecl.name,
-            returnType: varList.type, isDeprecated: deprecated);
-      }
+      _addSuggestion(
+          varDecl.name, varList.type, protocol.ElementKind.TOP_LEVEL_VARIABLE,
+          isDeprecated: isDeprecated(varList) || isDeprecated(varDecl),
+          relevance: DART_RELEVANCE_LOCAL_TOP_LEVEL_VARIABLE);
     }
   }
 
@@ -594,14 +538,26 @@
         .any((FormalParameter param) => param.kind == ParameterKind.NAMED);
   }
 
-  CompletionSuggestion _addSuggestion(SimpleIdentifier id, TypeName returnType,
-      bool isDeprecated, int defaultRelevance, {ClassDeclaration classDecl}) {
+  void _addSuggestion(
+      SimpleIdentifier id, TypeName typeName, protocol.ElementKind elemKind,
+      {bool isAbstract: false, bool isDeprecated: false,
+      ClassDeclaration classDecl, FormalParameterList param,
+      int relevance: DART_RELEVANCE_DEFAULT}) {
     CompletionSuggestion suggestion = createSuggestion(
-        id, isDeprecated, defaultRelevance, returnType, classDecl: classDecl);
+        id, isDeprecated, relevance, typeName, classDecl: classDecl);
     if (suggestion != null) {
       request.addSuggestion(suggestion);
+      suggestion.element = createElement(elemKind, id,
+          isAbstract: isAbstract,
+          isDeprecated: isDeprecated,
+          parameters: param != null ? param.toSource() : null,
+          returnType: typeName);
+      if ((elemKind == protocol.ElementKind.METHOD ||
+              elemKind == protocol.ElementKind.FUNCTION) &&
+          param != null) {
+        _addParameterInfo(suggestion, param);
+      }
     }
-    return suggestion;
   }
 
   bool _isVoid(TypeName returnType) {
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index 9dc36d0..cb695b8 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -413,8 +413,12 @@
     if (node is SimpleStringLiteral && node.parent is PartDirective) {
       PartDirective directive = node.parent;
       Source partSource = directive.source;
-      CompilationUnit partUnit =
-          context.getResolvedCompilationUnit2(partSource, unitSource);
+      CompilationUnit partUnit;
+      if (AnalysisEngine.instance.useTaskModel) {
+        partUnit = context.getResolvedCompilationUnit2(partSource, partSource);
+      } else {
+        partUnit = context.getResolvedCompilationUnit2(partSource, unitSource);
+      }
       if (partUnit != null) {
         CorrectionUtils partUtils = new CorrectionUtils(partUnit);
         CorrectionUtils_InsertDesc desc = partUtils.getInsertDescTop();
diff --git a/pkg/analysis_server/lib/src/services/index/index_contributor.dart b/pkg/analysis_server/lib/src/services/index/index_contributor.dart
index 0143375..53ef464 100644
--- a/pkg/analysis_server/lib/src/services/index/index_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/index/index_contributor.dart
@@ -40,8 +40,13 @@
     return;
   }
   // do index
-  unit.accept(new _IndexContributor(store));
-  store.doneIndex();
+  try {
+    unit.accept(new _IndexContributor(store));
+    store.doneIndex();
+  } catch (e) {
+    store.cancelIndexDart();
+    rethrow;
+  }
 }
 
 /**
diff --git a/pkg/analysis_server/lib/src/services/index/index_store.dart b/pkg/analysis_server/lib/src/services/index/index_store.dart
index 1d61e7a..858d0ac 100644
--- a/pkg/analysis_server/lib/src/services/index/index_store.dart
+++ b/pkg/analysis_server/lib/src/services/index/index_store.dart
@@ -51,7 +51,14 @@
   bool aboutToIndexHtml(AnalysisContext context, HtmlElement htmlElement);
 
   /**
-   * Notifies that index store that the current Dart or HTML unit indexing is
+   * Notifies the index store that there was an error during the current Dart
+   * indexing, and all the information recorded after the last
+   * [aboutToIndexDart] invocation must be discarded.
+   */
+  void cancelIndexDart();
+
+  /**
+   * Notifies the index store that the current Dart or HTML unit indexing is
    * done.
    *
    * If this method is not invoked after corresponding "aboutToIndex*"
diff --git a/pkg/analysis_server/lib/src/services/index/store/split_store.dart b/pkg/analysis_server/lib/src/services/index/store/split_store.dart
index 1859a41..ee5c3b8 100644
--- a/pkg/analysis_server/lib/src/services/index/store/split_store.dart
+++ b/pkg/analysis_server/lib/src/services/index/store/split_store.dart
@@ -696,6 +696,21 @@
   }
 
   @override
+  void cancelIndexDart() {
+    if (_currentNode != null) {
+      // remove top-level information for the current node
+      for (Map<int, dynamic> nodeRelations in _topDeclarations.values) {
+        nodeRelations.remove(_currentNodeNameId);
+      }
+      // clear fields
+      _currentNodeName = null;
+      _currentNodeNameId = -1;
+      _currentNode = null;
+      _currentContextId = -1;
+    }
+  }
+
+  @override
   void clear() {
     _topDeclarations.clear();
     _nodeManager.clear();
diff --git a/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart b/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart
index 884b4b3..aabe616 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart
@@ -85,7 +85,7 @@
     // prepare "get" keyword
     Token getKeyword = null;
     {
-      AstNode node = element.node;
+      AstNode node = element.computeNode();
       if (node is MethodDeclaration) {
         getKeyword = node.propertyKeyword;
       } else if (node is FunctionDeclaration) {
diff --git a/pkg/analysis_server/lib/src/services/refactoring/convert_method_to_getter.dart b/pkg/analysis_server/lib/src/services/refactoring/convert_method_to_getter.dart
index 22adfa3..0bcf9c2 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/convert_method_to_getter.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/convert_method_to_getter.dart
@@ -93,7 +93,7 @@
     // prepare parameters
     FormalParameterList parameters;
     {
-      AstNode node = element.node;
+      AstNode node = element.computeNode();
       if (node is MethodDeclaration) {
         parameters = node.parameters;
       }
diff --git a/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart b/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart
index 8ae9b94..f0a345a 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart
@@ -74,7 +74,7 @@
         Element element = offsetNode.staticElement;
         if (element is LocalVariableElement) {
           _variableElement = element;
-          _variableNode = element.node;
+          _variableNode = element.computeNode();
         }
       }
     }
@@ -100,9 +100,8 @@
     for (SearchMatch reference in _references) {
       if (reference.kind != MatchKind.READ) {
         String message = format(
-            "Local variable '{0}' is assigned more than once.", [
-          _variableElement.displayName
-        ]);
+            "Local variable '{0}' is assigned more than once.",
+            [_variableElement.displayName]);
         return new RefactoringStatus.fatal(
             message, newLocation_fromMatch(reference));
       }
diff --git a/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart b/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
index f3100ef..35ba073 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
@@ -50,8 +50,8 @@
     List<Expression> arguments) {
   // prepare edits to replace parameters with arguments
   List<SourceEdit> edits = <SourceEdit>[];
-  part._parameters.forEach(
-      (ParameterElement parameter, List<_ParameterOccurrence> occurrences) {
+  part._parameters.forEach((ParameterElement parameter,
+      List<_ParameterOccurrence> occurrences) {
     // prepare argument
     Expression argument = null;
     for (Expression arg in arguments) {
@@ -344,7 +344,7 @@
     // class member
     bool isClassMember = element.enclosingElement is ClassElement;
     if (element is MethodElement || _isAccessor && isClassMember) {
-      MethodDeclaration methodDeclaration = element.node;
+      MethodDeclaration methodDeclaration = element.computeNode();
       _methodNode = methodDeclaration;
       _methodParameters = methodDeclaration.parameters;
       _methodBody = methodDeclaration.body;
@@ -357,7 +357,7 @@
     // unit member
     bool isUnitMember = element.enclosingElement is CompilationUnitElement;
     if (element is FunctionElement || _isAccessor && isUnitMember) {
-      FunctionDeclaration functionDeclaration = element.node;
+      FunctionDeclaration functionDeclaration = element.computeNode();
       _methodNode = functionDeclaration;
       _methodParameters = functionDeclaration.functionExpression.parameters;
       _methodBody = functionDeclaration.functionExpression.body;
diff --git a/pkg/analysis_server/test/analysis_server_test.dart b/pkg/analysis_server/test/analysis_server_test.dart
index f5ded0f..5a03f56 100644
--- a/pkg/analysis_server/test/analysis_server_test.dart
+++ b/pkg/analysis_server/test/analysis_server_test.dart
@@ -208,7 +208,7 @@
     File bar = resourceProvider.newFile('/bar/bar.dart', 'library lib;');
     Source barSource = bar.createSource();
     server.setAnalysisRoots('0', ['/foo', '/bar'], [], {});
-    return pumpEventQueue(50).then((_) {
+    return pumpEventQueue(200).then((_) {
       expect(server.statusAnalyzing, isFalse);
       // Make sure getAnalysisContext returns the proper context for each.
       AnalysisContext fooContext =
@@ -320,12 +320,12 @@
       subscriptions[service] = <String>[bar.path].toSet();
     }
     server.setAnalysisSubscriptions(subscriptions);
-    await pumpEventQueue(100);
+    await pumpEventQueue(200);
     expect(server.statusAnalyzing, isFalse);
     channel.notificationsReceived.clear();
     server.updateContent(
         '0', {bar.path: new AddContentOverlay('library bar; void f() {}')});
-    await pumpEventQueue(100);
+    await pumpEventQueue(200);
     expect(server.statusAnalyzing, isFalse);
     expect(channel.notificationsReceived, isNotEmpty);
     Set<String> notificationTypesReceived = new Set<String>();
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index 95a97b8..ba4210d 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -926,7 +926,7 @@
   /**
    * The analysis context that was created.
    */
-  AnalysisContextImpl currentContext;
+  AnalysisContext currentContext;
 
   /**
    * Map from context to the timestamp when the context was created.
@@ -970,7 +970,7 @@
     currentContextFilePaths[path] = <String, int>{};
     currentContextSources[path] = new HashSet<Source>();
     currentContextPackageUriResolvers[path] = packageUriResolver;
-    currentContext = new AnalysisContextImpl();
+    currentContext = AnalysisEngine.instance.createAnalysisContext();
     currentContext.sourceFactory = new SourceFactory(
         packageUriResolver == null ? [] : [packageUriResolver]);
     return currentContext;
diff --git a/pkg/analysis_server/test/domain_analysis_test.dart b/pkg/analysis_server/test/domain_analysis_test.dart
index 7941190..25b4d88 100644
--- a/pkg/analysis_server/test/domain_analysis_test.dart
+++ b/pkg/analysis_server/test/domain_analysis_test.dart
@@ -287,7 +287,7 @@
     }
   }
 
-  test_packageMapDependencies() {
+  test_packageMapDependencies() async {
     // Prepare a source file that has errors because it refers to an unknown
     // package.
     String pkgFile = '/packages/pkgA/libA.dart';
@@ -305,19 +305,18 @@
     packageMapProvider.dependencies.add(pkgDependency);
     // Create project and wait for analysis
     createProject();
-    return waitForTasksFinished().then((_) {
-      expect(filesErrors[testFile], isNotEmpty);
-      // Add the package to the package map and tickle the package dependency.
-      packageMapProvider.packageMap = {
-        'pkgA': [resourceProvider.getResource('/packages/pkgA')]
-      };
-      resourceProvider.modifyFile(pkgDependency, 'new contents');
-      // Let the server time to notice the file has changed, then let
-      // analysis omplete.  There should now be no error.
-      return pumpEventQueue().then((_) => waitForTasksFinished()).then((_) {
-        expect(filesErrors[testFile], isEmpty);
-      });
-    });
+    await waitForTasksFinished();
+    expect(filesErrors[testFile], isNotEmpty);
+    // Add the package to the package map and tickle the package dependency.
+    packageMapProvider.packageMap = {
+      'pkgA': [resourceProvider.getResource('/packages/pkgA')]
+    };
+    resourceProvider.modifyFile(pkgDependency, 'new contents');
+    // Give the server time to notice the file has changed, then let
+    // analysis complete. There should now be no error.
+    await pumpEventQueue();
+    await waitForTasksFinished();
+    expect(filesErrors[testFile], isEmpty);
   }
 
   test_setRoots_packages() {
diff --git a/pkg/analysis_server/test/integration/integration_tests.dart b/pkg/analysis_server/test/integration/integration_tests.dart
index 23592862..98e9860 100644
--- a/pkg/analysis_server/test/integration/integration_tests.dart
+++ b/pkg/analysis_server/test/integration/integration_tests.dart
@@ -428,6 +428,17 @@
   Stopwatch _time = new Stopwatch();
 
   /**
+   * The [currentElapseTime] at which the last communication was received from the server
+   * or `null` if no communication has been received.
+   */
+  double lastCommunicationTime;
+
+  /**
+   * The current elapse time (seconds) since the server was started.
+   */
+  double get currentElapseTime => _time.elapsedTicks / _time.frequency;
+
+  /**
    * Future that completes when the server process exits.
    */
   Future<int> get exitCode => _process.exitCode;
@@ -488,6 +499,7 @@
         .transform((new Utf8Codec()).decoder)
         .transform(new LineSplitter())
         .listen((String line) {
+      lastCommunicationTime = currentElapseTime;
       String trimmedLine = line.trim();
       _recordStdio('RECV: $trimmedLine');
       var message;
@@ -630,7 +642,7 @@
    * [debugStdio] has been called.
    */
   void _recordStdio(String line) {
-    double elapsedTime = _time.elapsedTicks / _time.frequency;
+    double elapsedTime = currentElapseTime;
     line = "$elapsedTime: $line";
     if (_debuggingStdio) {
       print(line);
diff --git a/pkg/analysis_server/test/performance/driver.dart b/pkg/analysis_server/test/performance/driver.dart
new file mode 100644
index 0000000..ca34e27
--- /dev/null
+++ b/pkg/analysis_server/test/performance/driver.dart
@@ -0,0 +1,176 @@
+library server.driver;
+
+import 'dart:async';
+
+import 'package:logging/logging.dart';
+
+import '../integration/integration_test_methods.dart';
+import '../integration/integration_tests.dart';
+import 'operation.dart';
+
+/**
+ * [Driver] launches and manages an instance of analysis server,
+ * reads a stream of operations, sends requests to analysis server
+ * based upon those operations, and evaluates the results.
+ */
+class Driver extends IntegrationTestMixin {
+  /**
+   * The amount of time to give the server to respond to a shutdown request
+   * before forcibly terminating it.
+   */
+  static const Duration SHUTDOWN_TIMEOUT = const Duration(seconds: 5);
+  
+  final Logger logger;
+
+  /**
+   * A flag indicating whether the server is running.
+   */
+  bool running = false;
+
+  @override
+  Server server;
+
+  /**
+   * The results collected while running analysis server.
+   */
+  final Results results = new Results();
+
+  /**
+   * The [Completer] for [runComplete].
+   */
+  Completer<Results> _runCompleter = new Completer<Results>();
+
+  Driver(this.logger);
+
+  /**
+   * Return a [Future] that completes with the [Results] of running
+   * the analysis server once all operations have been performed.
+   */
+  Future<Results> get runComplete => _runCompleter.future;
+
+  /**
+   * Perform the given operation.
+   * Return a [Future] that completes when the next operation can be performed,
+   * or `null` if the next operation can be performed immediately
+   */
+  Future perform(Operation op) {
+    return op.perform(this);
+  }
+
+  /**
+   * Send a command to the server.  An 'id' will be automatically assigned.
+   * The returned [Future] will be completed when the server acknowledges the
+   * command with a response.  If the server acknowledges the command with a
+   * normal (non-error) response, the future will be completed with the 'result'
+   * field from the response.  If the server acknowledges the command with an
+   * error response, the future will be completed with an error.
+   */
+  Future send(String method, Map<String, dynamic> params) {
+    return server.send(method, params);
+  }
+
+  /**
+   * Launch the analysis server.
+   * Return a [Future] that completes when analysis server has started.
+   */
+  Future startServer() async {
+    logger.log(Level.FINE, 'starting server');
+    initializeInttestMixin();
+    server = new Server();
+    Completer serverConnected = new Completer();
+    onServerConnected.listen((_) {
+      logger.log(Level.FINE, 'connected to server');
+      serverConnected.complete();
+    });
+    running = true;
+    return server.start(/*profileServer: true*/).then((params) {
+      server.listenToOutput(dispatchNotification);
+      server.exitCode.then((_) {
+        logger.log(Level.FINE, 'server stopped');
+        running = false;
+        _resultsReady();
+      });
+      return serverConnected.future;
+    });
+  }
+
+  /**
+   * Shutdown the analysis server if it is running.
+   */
+  Future stopServer() async {
+    if (running) {
+      logger.log(Level.FINE, 'requesting server shutdown');
+      // Give the server a short time to comply with the shutdown request; if it
+      // doesn't exit, then forcibly terminate it.
+      sendServerShutdown();
+      await server.exitCode.timeout(SHUTDOWN_TIMEOUT, onTimeout: () {
+        return server.kill();
+      });
+    }
+    _resultsReady();
+  }
+
+  /**
+   * If not already complete, signal the completer with the collected results.
+   */
+  void _resultsReady() {
+    if (!_runCompleter.isCompleted) {
+      _runCompleter.complete(results);
+    }
+  }
+}
+
+/**
+ * [Results] contains information gathered by [Driver]
+ * while running the analysis server
+ */
+class Results {
+  Map<String, Measurement> measurements = new Map<String, Measurement>();
+
+  /**
+   * Display results on stdout.
+   */
+  void printResults() {
+    print('==================================================================');
+    print('Results:');
+    for (String tag in measurements.keys.toList()..sort()) {
+      measurements[tag].printResults();
+    }
+  }
+
+  /**
+   * Record the elapsed time for the given operation.
+   */
+  void record(String tag, Duration elapsed) {
+    Measurement measurement = measurements[tag];
+    if (measurement == null) {
+      measurement = new Measurement(tag);
+      measurements[tag] = measurement;
+    }
+    measurement.record(elapsed);
+  }
+}
+
+/**
+ * [Measurement] tracks elapsed time for a given operation.
+ */
+class Measurement {
+  final String tag;
+  final List<Duration> elapsedTimes = new List<Duration>();
+  
+  Measurement(this.tag);
+
+  void record(Duration elapsed) {
+    elapsedTimes.add(elapsed);
+  }
+
+  void printResults() {
+    if (elapsedTimes.length == 0) {
+      return;
+    }
+    print('=== $tag');
+    for (Duration elapsed in elapsedTimes) {
+      print(elapsed);
+    }
+  }
+}
diff --git a/pkg/analysis_server/test/performance/input_converter.dart b/pkg/analysis_server/test/performance/input_converter.dart
new file mode 100644
index 0000000..d2167fb
--- /dev/null
+++ b/pkg/analysis_server/test/performance/input_converter.dart
@@ -0,0 +1,115 @@
+library input.transformer;
+
+import 'dart:convert';
+
+import 'instrumentation_input_converter.dart';
+import 'operation.dart';
+
+final int NINE = '9'.codeUnitAt(0);
+final int ZERO = '0'.codeUnitAt(0);
+
+/**
+ * [InputConverter] converts an input stream
+ * into a series of operations to be sent to the analysis server.
+ * The input stream can be either an instrumenation or log file.
+ */
+class InputConverter extends Converter<String, Operation> {
+
+  /**
+   * The number of lines read before the underlying converter was determined
+   * or the end of file was reached.
+   */
+  int headerLineCount = 0;
+
+  /**
+   * The underlying converter used to translate lines into operations
+   * or `null` if it has not yet been determined.
+   */
+  Converter<String, Operation> converter;
+
+  @override
+  Operation convert(String line) {
+    if (converter != null) {
+      return converter.convert(line);
+    }
+    if (headerLineCount == 20) {
+      throw 'Failed to determine input file format';
+    }
+    if (InstrumentationInputConverter.isFormat(line)) {
+      converter = new InstrumentationInputConverter();
+    } else if (LogFileInputConverter.isFormat(line)) {
+      converter = new LogFileInputConverter();
+    }
+    if (converter != null) {
+      return converter.convert(line);
+    }
+    print(line);
+    return null;
+  }
+
+  @override
+  _InputSink startChunkedConversion(outSink) {
+    return new _InputSink(this, outSink);
+  }
+}
+
+/**
+ * [LogFileInputConverter] converts a log file stream
+ * into a series of operations to be sent to the analysis server.
+ */
+class LogFileInputConverter extends Converter<String, Operation> {
+  @override
+  Operation convert(String line) {
+    throw 'not implemented yet';
+  }
+
+  /**
+   * Determine if the given line is from an instrumentation file.
+   * For example:
+   * `1428347977499 <= {"event":"server.connected","params":{"version":"1.6.0"}}`
+   */
+  static bool isFormat(String line) {
+    String timeStampString = _parseTimeStamp(line);
+    int start = timeStampString.length;
+    int end = start + 5;
+    return start > 10 &&
+        line.length > end &&
+        line.substring(start, end) == ' <= {"event":"server.connected"';
+  }
+
+  /**
+   * Parse the given line and return the millisecond timestamp or `null`
+   * if it cannot be determined.
+   */
+  static String _parseTimeStamp(String line) {
+    int index = 0;
+    while (index < line.length) {
+      int code = line.codeUnitAt(index);
+      if (code < ZERO || NINE < code) {
+        return line.substring(0, index);
+      }
+      ++index;
+    }
+    return line;
+  }
+}
+
+class _InputSink extends ChunkedConversionSink<String> {
+  final Converter<String, Operation> converter;
+  final outSink;
+
+  _InputSink(this.converter, this.outSink);
+
+  @override
+  void add(String line) {
+    Operation op = converter.convert(line);
+    if (op != null) {
+      outSink.add(op);
+    }
+  }
+
+  @override
+  void close() {
+    outSink.close();
+  }
+}
diff --git a/pkg/analysis_server/test/performance/instrumentation_input_converter.dart b/pkg/analysis_server/test/performance/instrumentation_input_converter.dart
new file mode 100644
index 0000000..4e027cf
--- /dev/null
+++ b/pkg/analysis_server/test/performance/instrumentation_input_converter.dart
@@ -0,0 +1,139 @@
+library input.transformer.instrumentation;
+
+import 'dart:convert';
+
+import 'package:logging/logging.dart';
+
+import 'operation.dart';
+
+final int COLON = ':'.codeUnitAt(0);
+
+/**
+ * [InstrumentationInputConverter] converts an instrumentation stream
+ * into a series of operations to be sent to the analysis server.
+ */
+class InstrumentationInputConverter extends Converter<String, Operation> {
+  final Logger logger = new Logger('InstrumentationInputConverter');
+  final Set<String> _codesSeen = new Set<String>();
+  final Set<String> _methodsSeen = new Set<String>();
+  final Set<String> _eventsSeen = new Set<String>();
+
+  @override
+  Operation convert(String line) {
+    try {
+      List<String> fields = _parseFields(line);
+      if (fields.length < 2) {
+        //return new InfoOperation('Ignored line:\n  $line');
+        return null;
+      }
+      // int timeStamp = int.parse(fields[0], onError: (_) => -1);
+      String opCode = fields[1];
+      if (opCode == 'Req') {
+        return convertRequest(line, fields);
+      }
+      if (opCode == 'Noti') {
+        return convertNotification(fields);
+      }
+      if (opCode == 'Ver') {
+        // 1433195174666:Ver:1421765742287333878467:org.dartlang.dartplugin:0.0.0:1.7.0:1.11.0-edge.131698
+        return new StartServerOperation();
+      }
+      if (_codesSeen.add(opCode)) {
+        logger.log(Level.INFO, 'Ignored op code: $opCode\n  $line');
+      }
+      return null;
+    } catch (e, s) {
+      throw 'Failed to parse line\n  $line\n$e\n$s';
+    }
+  }
+
+  /**
+   * Return an operation for the notification defined by [line] and [fields]
+   * or `null` if none.
+   */
+  Operation convertNotification(List<String> fields) {
+    //1433344448533:Noti:{"event"::"server.status","params"::{"analysis"::{"isAnalyzing"::false}}}
+    Map<String, dynamic> json = JSON.decode(fields[2]);
+    String event = json['event'];
+    if (event == 'server.status') {
+      Map<String, dynamic> params = json['params'];
+      if (params != null) {
+        Map<String, dynamic> analysis = params['analysis'];
+        if (analysis != null && analysis['isAnalyzing'] == false) {
+          return new WaitForAnalysisCompleteOperation();
+        }
+      }
+    }
+    if (event == 'server.connected') {
+      // Handled by the driver
+      return null;
+    }
+    if (_eventsSeen.add(event)) {
+      logger.log(Level.INFO, 'Ignored notification: $event');
+    }
+    return null;
+  }
+
+  /**
+   * Return an operation for the request defined by [line] and [fields]
+   * or `null` if none.
+   */
+  Operation convertRequest(String line, List<String> fields) {
+    Map<String, dynamic> json = JSON.decode(fields[2]);
+    String method = json['method'];
+    if (method == 'analysis.setAnalysisRoots') {
+      // 1433343174749:Req:{"id"::"3","method"::"analysis.setAnalysisRoots","params"::{"included"::["/usr/local/google/home/danrubel/work/git/dart_sdk/sdk/pkg/analysis_server","/usr/local/google/home/danrubel/work/git/dart_sdk/sdk/pkg/analyzer"],"excluded"::[],"packageRoots"::{}},"clientRequestTime"::1433343174702}
+      return new RequestOperation(json);
+    }
+    if (method == 'server.setSubscriptions') {
+      // 1433343174741:Req:{"id"::"1","method"::"server.setSubscriptions","params"::{"subscriptions"::["STATUS"]},"clientRequestTime"::1433343172679}
+      return new RequestOperation(json);
+    }
+    if (_methodsSeen.add(method)) {
+      logger.log(Level.INFO, 'Ignored request: $method\n  $line');
+    }
+    return null;
+  }
+
+  /**
+   * Determine if the given line is from an instrumentation file.
+   * For example:
+   * `1433175833005:Ver:1421765742287333878467:org.dartlang.dartplugin:0.0.0:1.6.2:1.11.0-edge.131698`
+   */
+  static bool isFormat(String line) {
+    List<String> fields = _parseFields(line);
+    int timeStamp = int.parse(fields[0], onError: (_) => -1);
+    String opCode = fields[1];
+    return timeStamp > 0 && opCode == 'Ver';
+  }
+
+  /**
+   * Extract fields from the given [line].
+   */
+  static List<String> _parseFields(String line) {
+    List<String> fields = new List<String>();
+    int index = 0;
+    StringBuffer sb = new StringBuffer();
+    while (index < line.length) {
+      int code = line.codeUnitAt(index);
+      if (code == COLON) {
+        // Embedded colons are doubled
+        int next = index + 1;
+        if (next < line.length && line.codeUnitAt(next) == COLON) {
+          sb.write(':');
+          ++index;
+        } else {
+          fields.add(sb.toString());
+          sb.clear();
+        }
+      } else {
+        sb.writeCharCode(code);
+      }
+      ++index;
+    }
+    if (sb.isNotEmpty) {
+      fields.add(sb.toString());
+    }
+    return fields;
+  }
+}
diff --git a/pkg/analysis_server/test/performance/main.dart b/pkg/analysis_server/test/performance/main.dart
new file mode 100644
index 0000000..8604876
--- /dev/null
+++ b/pkg/analysis_server/test/performance/main.dart
@@ -0,0 +1,120 @@
+library server.performance;
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:args/args.dart';
+import 'package:logging/logging.dart';
+
+import 'driver.dart';
+import 'input_converter.dart';
+import 'operation.dart';
+
+/**
+ * Launch and interact with the analysis server.
+ */
+main(List<String> rawArgs) {
+  Logger logger = new Logger('Performance Measurement Client');
+  logger.onRecord.listen((LogRecord rec) {
+    print(rec.message);
+  });
+  Driver driver = new Driver(logger);
+
+  ArgResults args = parseArgs(rawArgs);
+  Stream<Operation> stream = openInput(args);
+  StreamSubscription<Operation> subscription;
+  subscription = stream.listen((Operation op) {
+    Future future = driver.perform(op);
+    if (future != null) {
+      logger.log(Level.FINE, 'pausing operations for ${op.runtimeType}');
+      subscription.pause(future.then((_) {
+        logger.log(Level.FINE, 'resuming operations');
+      }));
+    }
+  }, onDone: () {
+    subscription.cancel();
+    driver.stopServer();
+  }, onError: (e, s) {
+    subscription.cancel();
+    logger.log(Level.WARNING, '$e\n$s');
+    driver.stopServer();
+    throw e;
+  });
+  driver.runComplete.then((Results results) {
+    results.printResults();
+  }).whenComplete(() {
+    return subscription.cancel();
+  });
+}
+
+const HELP_CMDLINE_OPTION = 'help';
+const INPUT_CMDLINE_OPTION = 'input';
+const VERBOSE_CMDLINE_OPTION = 'verbose';
+const VERY_VERBOSE_CMDLINE_OPTION = 'vv';
+
+/**
+ * Open and return the input stream specifying how this client
+ * should interact with the analysis server.
+ */
+Stream<Operation> openInput(ArgResults args) {
+  Stream<List<int>> inputRaw;
+  String inputPath = args[INPUT_CMDLINE_OPTION];
+  if (inputPath == null) {
+    return null;
+  }
+  if (inputPath == 'stdin') {
+    inputRaw = stdin;
+  } else {
+    inputRaw = new File(inputPath).openRead();
+  }
+  return inputRaw
+      .transform(SYSTEM_ENCODING.decoder)
+      .transform(new LineSplitter())
+      .transform(new InputConverter());
+}
+
+/**
+ * Parse the command line arguments.
+ */
+ArgResults parseArgs(List<String> rawArgs) {
+  ArgParser parser = new ArgParser();
+
+  parser.addOption(INPUT_CMDLINE_OPTION,
+      abbr: 'i',
+      help: 'The input file specifying how this client should interact '
+      'with the server. If the input file name is "stdin", '
+      'then the instructions are read from standard input.');
+  parser.addFlag(VERBOSE_CMDLINE_OPTION,
+      abbr: 'v', help: 'Verbose logging', negatable: false);
+  parser.addFlag(VERY_VERBOSE_CMDLINE_OPTION,
+      help: 'Extra verbose logging', negatable: false);
+  parser.addFlag(HELP_CMDLINE_OPTION,
+      abbr: 'h', help: 'Print this help information', negatable: false);
+
+  ArgResults args = parser.parse(rawArgs);
+  bool showHelp = args[HELP_CMDLINE_OPTION] || args.rest.isNotEmpty;
+
+  if (args[INPUT_CMDLINE_OPTION] == null ||
+      args[INPUT_CMDLINE_OPTION].isEmpty) {
+    print('missing "input" argument');
+    showHelp = true;
+  }
+  
+  if (args[VERY_VERBOSE_CMDLINE_OPTION] || rawArgs.contains('-vv')) {
+    Logger.root.level = Level.FINE;
+  } else if (args[VERBOSE_CMDLINE_OPTION]) {
+    Logger.root.level = Level.INFO;
+  } else {
+    Logger.root.level = Level.WARNING;
+  }
+
+  if (showHelp) {
+    print('');
+    print('Launch and interact with the AnalysisServer');
+    print(parser.usage);
+    exit(1);
+  }
+
+  return args;
+}
diff --git a/pkg/analysis_server/test/performance/operation.dart b/pkg/analysis_server/test/performance/operation.dart
new file mode 100644
index 0000000..0e30aea
--- /dev/null
+++ b/pkg/analysis_server/test/performance/operation.dart
@@ -0,0 +1,105 @@
+library server.operation;
+
+import 'dart:async';
+
+import 'package:analysis_server/src/protocol.dart';
+import 'package:logging/logging.dart';
+
+import 'driver.dart';
+
+class InfoOperation extends Operation {
+  final String message;
+
+  InfoOperation(this.message);
+
+  @override
+  Future perform(Driver driver) {
+    driver.logger.log(Level.INFO, message);
+    return null;
+  }
+}
+
+/**
+ * An [Operation] represents an action such as sending a request to the server.
+ */
+abstract class Operation {
+  Future perform(Driver driver);
+}
+
+/**
+ * A [RequestOperation] sends a [JSON] request to the server.
+ */
+class RequestOperation extends Operation {
+  final Map<String, dynamic> json;
+
+  RequestOperation(this.json);
+
+  @override
+  Future perform(Driver driver) {
+    String method = json['method'];
+    driver.logger.log(Level.FINE, 'Sending request: $method\n  $json');
+    driver.send(method, json['params']).then((response) {
+      driver.logger.log(Level.FINE, 'Response received: $method : $response');
+    }).catchError((e, s) {
+      driver.logger.log(Level.WARNING, 'Request failed: $method\n  $e\n$s');
+      throw 'Send request failed: $e';
+    });
+    return null;
+  }
+}
+
+class StartServerOperation extends Operation {
+  @override
+  Future perform(Driver driver) {
+    return driver.startServer();
+  }
+}
+
+class WaitForAnalysisCompleteOperation extends Operation {
+  @override
+  Future perform(Driver driver) {
+    DateTime start = new DateTime.now();
+    driver.logger.log(Level.FINE, 'waiting for analysis to complete');
+    StreamSubscription<ServerStatusParams> subscription;
+    Timer timer;
+    Completer completer = new Completer();
+    bool isAnalyzing = false;
+    subscription = driver.onServerStatus.listen((ServerStatusParams params) {
+      // TODO (danrubel) ensure that server.setSubscriptions STATUS is set
+      if (params.analysis != null) {
+        if (params.analysis.isAnalyzing) {
+          isAnalyzing = true;
+        } else {
+          subscription.cancel();
+          timer.cancel();
+          DateTime end = new DateTime.now();
+          Duration delta = end.difference(start);
+          driver.logger.log(Level.FINE, 'analysis complete after $delta');
+          completer.complete();
+          driver.results.record('analysis complete', delta);
+        }
+      }
+    });
+    timer = new Timer.periodic(new Duration(milliseconds: 20), (_) {
+      if (!isAnalyzing) {
+        // TODO (danrubel) revisit this once source change requests are implemented
+        subscription.cancel();
+        timer.cancel();
+        driver.logger.log(Level.INFO, 'analysis never started');
+        completer.complete();
+        return;
+      }
+      // Timeout if no communcation received within the last 10 seconds.
+      double currentTime = driver.server.currentElapseTime;
+      double lastTime = driver.server.lastCommunicationTime;
+      if (currentTime - lastTime > 10) {
+        subscription.cancel();
+        timer.cancel();
+        String message = 'gave up waiting for analysis to complete';
+        driver.logger.log(Level.WARNING, message);
+        completer.completeError(message);
+      }
+    });
+    return completer.future;
+  }
+}
diff --git a/pkg/analysis_server/test/protocol_server_test.dart b/pkg/analysis_server/test/protocol_server_test.dart
index 129c8cc..fca8b53 100644
--- a/pkg/analysis_server/test/protocol_server_test.dart
+++ b/pkg/analysis_server/test/protocol_server_test.dart
@@ -267,6 +267,130 @@
     expect(element.flags, 0);
   }
 
+  void test_fromElement_ENUM() {
+    engine.Source source = addSource('/test.dart', '''
+@deprecated
+enum _E1 { one, two }
+enum E2 { three, four }''');
+    engine.CompilationUnit unit = resolveLibraryUnit(source);
+    {
+      engine.ClassElement engineElement = findElementInUnit(unit, '_E1');
+      // TODO (danrubel) determine why enum is not deprecated
+      expect(engineElement.isDeprecated, isFalse);
+      // create notification Element
+      Element element = newElement_fromEngine(engineElement);
+      expect(element.kind, ElementKind.ENUM);
+      expect(element.name, '_E1');
+      expect(element.typeParameters, isNull);
+      {
+        Location location = element.location;
+        expect(location.file, '/test.dart');
+        expect(location.offset, 17);
+        expect(location.length, '_E1'.length);
+        expect(location.startLine, 2);
+        expect(location.startColumn, 6);
+      }
+      expect(element.parameters, isNull);
+      expect(element.flags,
+          (engineElement.isDeprecated ? Element.FLAG_DEPRECATED : 0) |
+              Element.FLAG_PRIVATE);
+    }
+    {
+      engine.ClassElement engineElement = findElementInUnit(unit, 'E2');
+      // create notification Element
+      Element element = newElement_fromEngine(engineElement);
+      expect(element.kind, ElementKind.ENUM);
+      expect(element.name, 'E2');
+      expect(element.typeParameters, isNull);
+      expect(element.flags, 0);
+    }
+  }
+
+  void test_fromElement_ENUM_CONSTANT() {
+    engine.Source source = addSource('/test.dart', '''
+@deprecated
+enum _E1 { one, two }
+enum E2 { three, four }''');
+    engine.CompilationUnit unit = resolveLibraryUnit(source);
+    {
+      engine.FieldElement engineElement = findElementInUnit(unit, 'one');
+      // create notification Element
+      Element element = newElement_fromEngine(engineElement);
+      expect(element.kind, ElementKind.ENUM_CONSTANT);
+      expect(element.name, 'one');
+      {
+        Location location = element.location;
+        expect(location.file, '/test.dart');
+        expect(location.offset, 23);
+        expect(location.length, 'one'.length);
+        expect(location.startLine, 2);
+        expect(location.startColumn, 12);
+      }
+      expect(element.parameters, isNull);
+      expect(element.returnType, '_E1');
+      // TODO(danrubel) determine why enum constant is not marked as deprecated
+      engine.ClassElement classElement = engineElement.enclosingElement;
+      expect(element.flags,
+          (classElement.isDeprecated ? Element.FLAG_DEPRECATED : 0) |
+              Element.FLAG_CONST |
+              Element.FLAG_STATIC);
+    }
+    {
+      engine.FieldElement engineElement = findElementInUnit(unit, 'three');
+      // create notification Element
+      Element element = newElement_fromEngine(engineElement);
+      expect(element.kind, ElementKind.ENUM_CONSTANT);
+      expect(element.name, 'three');
+      {
+        Location location = element.location;
+        expect(location.file, '/test.dart');
+        expect(location.offset, 44);
+        expect(location.length, 'three'.length);
+        expect(location.startLine, 3);
+        expect(location.startColumn, 11);
+      }
+      expect(element.parameters, isNull);
+      expect(element.returnType, 'E2');
+      expect(element.flags, Element.FLAG_CONST | Element.FLAG_STATIC);
+    }
+    {
+      engine.FieldElement engineElement = findElementInUnit(unit, 'index');
+      // create notification Element
+      Element element = newElement_fromEngine(engineElement);
+      expect(element.kind, ElementKind.FIELD);
+      expect(element.name, 'index');
+      {
+        Location location = element.location;
+        expect(location.file, '/test.dart');
+        expect(location.offset, -1);
+        expect(location.length, 'index'.length);
+        expect(location.startLine, 1);
+        expect(location.startColumn, 0);
+      }
+      expect(element.parameters, isNull);
+      expect(element.returnType, 'int');
+      expect(element.flags, Element.FLAG_FINAL);
+    }
+    {
+      engine.FieldElement engineElement = findElementInUnit(unit, 'values');
+      // create notification Element
+      Element element = newElement_fromEngine(engineElement);
+      expect(element.kind, ElementKind.FIELD);
+      expect(element.name, 'values');
+      {
+        Location location = element.location;
+        expect(location.file, '/test.dart');
+        expect(location.offset, -1);
+        expect(location.length, 'values'.length);
+        expect(location.startLine, 1);
+        expect(location.startColumn, 0);
+      }
+      expect(element.parameters, isNull);
+      expect(element.returnType, 'List<E2>');
+      expect(element.flags, Element.FLAG_CONST | Element.FLAG_STATIC);
+    }
+  }
+
   void test_fromElement_FIELD() {
     engine.Source source = addSource('/test.dart', '''
 class A {
diff --git a/pkg/analysis_server/test/services/completion/completion_test_util.dart b/pkg/analysis_server/test/services/completion/completion_test_util.dart
index 83ca4e5..249e1c0 100644
--- a/pkg/analysis_server/test/services/completion/completion_test_util.dart
+++ b/pkg/analysis_server/test/services/completion/completion_test_util.dart
@@ -567,9 +567,7 @@
     CompletionSuggestion suggestion =
         assertSuggest(completion, isDeprecated: isDeprecated);
     expect(suggestion.isDeprecated, isDeprecated);
-    // TODO(danrubel) : Perhaps should be protocol.ElementKind.ENUM_CONST
-    // but element model represents them as FIELD
-    expect(suggestion.element.kind, protocol.ElementKind.FIELD);
+    expect(suggestion.element.kind, protocol.ElementKind.ENUM_CONSTANT);
     return suggestion;
   }
 
diff --git a/pkg/analysis_server/test/services/correction/fix_test.dart b/pkg/analysis_server/test/services/correction/fix_test.dart
index 0778532..4bbaeb1 100644
--- a/pkg/analysis_server/test/services/correction/fix_test.dart
+++ b/pkg/analysis_server/test/services/correction/fix_test.dart
@@ -276,6 +276,7 @@
 library my.lib;
 part 'part.dart';
 ''');
+    _performAnalysis();
     AnalysisError error = _findErrorToFix();
     fix = _assertHasFix(DartFixKind.ADD_PART_OF, error);
     change = fix.change;
@@ -3915,4 +3916,8 @@
     }
     return positions;
   }
+
+  void _performAnalysis() {
+    while (context.performAnalysisTask().hasMoreWork);
+  }
 }
diff --git a/pkg/analysis_server/test/services/index/store/split_store_test.dart b/pkg/analysis_server/test/services/index/store/split_store_test.dart
index 02fa3fe..b954996 100644
--- a/pkg/analysis_server/test/services/index/store/split_store_test.dart
+++ b/pkg/analysis_server/test/services/index/store/split_store_test.dart
@@ -666,6 +666,22 @@
     expect(store.aboutToIndexHtml(contextA, htmlElementA), isFalse);
   }
 
+  test_cancelIndexDart() {
+    LocationImpl locationA = mockLocation(indexableA);
+    LocationImpl locationB = mockLocation(indexableA);
+    store.aboutToIndexDart(contextA, unitElementA);
+    store.recordRelationship(indexableA, relationship, locationA);
+    store.recordRelationship(indexableA, relationship, locationB);
+    store.recordTopLevelDeclaration(elementA);
+    store.cancelIndexDart();
+    return store
+        .getRelationships(indexableA, relationship)
+        .then((List<LocationImpl> locations) {
+      assertLocations(locations, []);
+      expect(store.getTopLevelDeclarations((name) => true), isEmpty);
+    });
+  }
+
   void test_clear() {
     LocationImpl locationA = mockLocation(indexableA);
     store.aboutToIndexDart(contextA, unitElementA);
diff --git a/pkg/analysis_server/test/services/search/search_engine_test.dart b/pkg/analysis_server/test/services/search/search_engine_test.dart
index ed71610..7eaf70b 100644
--- a/pkg/analysis_server/test/services/search/search_engine_test.dart
+++ b/pkg/analysis_server/test/services/search/search_engine_test.dart
@@ -352,8 +352,8 @@
     LibraryElement element = testLibraryElement;
     CompilationUnitElement elementA = element.parts[0];
     CompilationUnitElement elementB = element.parts[1];
-    index.indexUnit(context, elementA.node);
-    index.indexUnit(context, elementB.node);
+    index.indexUnit(context, elementA.computeNode());
+    index.indexUnit(context, elementB.computeNode());
     var expected = [
       new ExpectedMatch(elementA, MatchKind.REFERENCE,
           codeA.indexOf('lib; // A'), 'lib'.length),
diff --git a/pkg/analysis_server/tool/spec/codegen_analysis_server.dart b/pkg/analysis_server/tool/spec/codegen_analysis_server.dart
index db90acc..8b3c897 100644
--- a/pkg/analysis_server/tool/spec/codegen_analysis_server.dart
+++ b/pkg/analysis_server/tool/spec/codegen_analysis_server.dart
@@ -38,7 +38,7 @@
     writeln('package com.google.dart.server.generated;');
     writeln();
     writeln('import com.google.dart.server.*;');
-    writeln('import com.google.dart.server.generated.types.*;');
+    writeln('import org.dartlang.analysis.server.protocol.*;');
     writeln();
     writeln('import java.util.List;');
     writeln('import java.util.Map;');
diff --git a/pkg/analysis_server/tool/spec/codegen_java_types.dart b/pkg/analysis_server/tool/spec/codegen_java_types.dart
index b6915b1..2dec54c 100644
--- a/pkg/analysis_server/tool/spec/codegen_java_types.dart
+++ b/pkg/analysis_server/tool/spec/codegen_java_types.dart
@@ -131,7 +131,7 @@
 
   void emitType(TypeDecl type, dom.Element html) {
     outputHeader(javaStyle: true);
-    writeln('package com.google.dart.server.generated.types;');
+    writeln('package org.dartlang.analysis.server.protocol;');
     writeln();
     if (type is TypeObject) {
       _writeTypeObject(type, html);
diff --git a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
index 1132dd8..dff7552 100644
--- a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
+++ b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
@@ -17,7 +17,7 @@
 package com.google.dart.server.generated;
 
 import com.google.dart.server.*;
-import com.google.dart.server.generated.types.*;
+import org.dartlang.analysis.server.protocol.*;
 
 import java.util.List;
 import java.util.Map;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/AddContentOverlay.java b/pkg/analysis_server/tool/spec/generated/java/types/AddContentOverlay.java
index 3ffc75f..9d9c428 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/AddContentOverlay.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/AddContentOverlay.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/AnalysisError.java b/pkg/analysis_server/tool/spec/generated/java/types/AnalysisError.java
index c9b75e8..c85d882 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/AnalysisError.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/AnalysisError.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/AnalysisErrorFixes.java b/pkg/analysis_server/tool/spec/generated/java/types/AnalysisErrorFixes.java
index 1868fbd..6a53f63 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/AnalysisErrorFixes.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/AnalysisErrorFixes.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/AnalysisErrorSeverity.java b/pkg/analysis_server/tool/spec/generated/java/types/AnalysisErrorSeverity.java
index 6fbfabb..6396fc2 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/AnalysisErrorSeverity.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/AnalysisErrorSeverity.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 /**
  * An enumeration of the possible severities of analysis errors.
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/AnalysisErrorType.java b/pkg/analysis_server/tool/spec/generated/java/types/AnalysisErrorType.java
index eb45b09..d4ea8d7 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/AnalysisErrorType.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/AnalysisErrorType.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 /**
  * An enumeration of the possible types of analysis errors.
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/AnalysisOptions.java b/pkg/analysis_server/tool/spec/generated/java/types/AnalysisOptions.java
index 9ec191d..e46c4813 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/AnalysisOptions.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/AnalysisOptions.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/AnalysisService.java b/pkg/analysis_server/tool/spec/generated/java/types/AnalysisService.java
index eef2903..94c5418 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/AnalysisService.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/AnalysisService.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 /**
  * An enumeration of the services provided by the analysis domain.
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/AnalysisStatus.java b/pkg/analysis_server/tool/spec/generated/java/types/AnalysisStatus.java
index fcff703..d738660 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/AnalysisStatus.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/AnalysisStatus.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/ChangeContentOverlay.java b/pkg/analysis_server/tool/spec/generated/java/types/ChangeContentOverlay.java
index 468bb07..469e3dc 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/ChangeContentOverlay.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/ChangeContentOverlay.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java b/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java
index 922dbf4..a69eee1 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestionKind.java b/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestionKind.java
index 3e79fab..71f8761 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestionKind.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestionKind.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 /**
  * An enumeration of the kinds of elements that can be included in a completion suggestion.
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/Element.java b/pkg/analysis_server/tool/spec/generated/java/types/Element.java
index cbef7ea..51115ec 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/Element.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/Element.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/ElementKind.java b/pkg/analysis_server/tool/spec/generated/java/types/ElementKind.java
index ff0b4ee..7426bda 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/ElementKind.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/ElementKind.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 /**
  * An enumeration of the kinds of elements.
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/ExecutableFile.java b/pkg/analysis_server/tool/spec/generated/java/types/ExecutableFile.java
index 140984a..aee28ae 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/ExecutableFile.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/ExecutableFile.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/ExecutableKind.java b/pkg/analysis_server/tool/spec/generated/java/types/ExecutableKind.java
index a206c9c..3b3f1b8 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/ExecutableKind.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/ExecutableKind.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 /**
  * An enumeration of the kinds of executable files.
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/ExecutionService.java b/pkg/analysis_server/tool/spec/generated/java/types/ExecutionService.java
index 499982a..362368b 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/ExecutionService.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/ExecutionService.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 /**
  * An enumeration of the services provided by the execution domain.
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/ExtractLocalVariableFeedback.java b/pkg/analysis_server/tool/spec/generated/java/types/ExtractLocalVariableFeedback.java
index 8dc8afc..c329329 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/ExtractLocalVariableFeedback.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/ExtractLocalVariableFeedback.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/ExtractLocalVariableOptions.java b/pkg/analysis_server/tool/spec/generated/java/types/ExtractLocalVariableOptions.java
index 543d20db..4413dde 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/ExtractLocalVariableOptions.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/ExtractLocalVariableOptions.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/ExtractMethodFeedback.java b/pkg/analysis_server/tool/spec/generated/java/types/ExtractMethodFeedback.java
index 7e446a9..f6acccc 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/ExtractMethodFeedback.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/ExtractMethodFeedback.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/ExtractMethodOptions.java b/pkg/analysis_server/tool/spec/generated/java/types/ExtractMethodOptions.java
index 54b2a6b..d6b509e 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/ExtractMethodOptions.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/ExtractMethodOptions.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/FoldingKind.java b/pkg/analysis_server/tool/spec/generated/java/types/FoldingKind.java
index f48452c..4e72f1b 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/FoldingKind.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/FoldingKind.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 /**
  * An enumeration of the kinds of folding regions.
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/FoldingRegion.java b/pkg/analysis_server/tool/spec/generated/java/types/FoldingRegion.java
index 75b0736..3e63a4e 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/FoldingRegion.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/FoldingRegion.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/HighlightRegion.java b/pkg/analysis_server/tool/spec/generated/java/types/HighlightRegion.java
index 11b64e0..7a8e83c 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/HighlightRegion.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/HighlightRegion.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/HighlightRegionType.java b/pkg/analysis_server/tool/spec/generated/java/types/HighlightRegionType.java
index cf9d006..4927e4b 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/HighlightRegionType.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/HighlightRegionType.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 /**
  * An enumeration of the kinds of highlighting that can be applied to files.
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/HoverInformation.java b/pkg/analysis_server/tool/spec/generated/java/types/HoverInformation.java
index b203bcb..ac80ee8 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/HoverInformation.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/HoverInformation.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/InlineLocalVariableFeedback.java b/pkg/analysis_server/tool/spec/generated/java/types/InlineLocalVariableFeedback.java
index 4e8503b..89c3bff 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/InlineLocalVariableFeedback.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/InlineLocalVariableFeedback.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/InlineMethodFeedback.java b/pkg/analysis_server/tool/spec/generated/java/types/InlineMethodFeedback.java
index 6cd3e0c..c6842dd 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/InlineMethodFeedback.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/InlineMethodFeedback.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/InlineMethodOptions.java b/pkg/analysis_server/tool/spec/generated/java/types/InlineMethodOptions.java
index 707977e..938c664 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/InlineMethodOptions.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/InlineMethodOptions.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/LinkedEditGroup.java b/pkg/analysis_server/tool/spec/generated/java/types/LinkedEditGroup.java
index 06e1e26..7a495e8 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/LinkedEditGroup.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/LinkedEditGroup.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/LinkedEditSuggestion.java b/pkg/analysis_server/tool/spec/generated/java/types/LinkedEditSuggestion.java
index 4301ff1..4deb527 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/LinkedEditSuggestion.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/LinkedEditSuggestion.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/LinkedEditSuggestionKind.java b/pkg/analysis_server/tool/spec/generated/java/types/LinkedEditSuggestionKind.java
index 25343a2..cdcdfa5 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/LinkedEditSuggestionKind.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/LinkedEditSuggestionKind.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 /**
  * An enumeration of the kind of values that can be suggested for a linked edit.
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/Location.java b/pkg/analysis_server/tool/spec/generated/java/types/Location.java
index a0eac20..d52b5f7 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/Location.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/Location.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/MoveFileOptions.java b/pkg/analysis_server/tool/spec/generated/java/types/MoveFileOptions.java
index a24c3eb..d828d0d 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/MoveFileOptions.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/MoveFileOptions.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/NavigationRegion.java b/pkg/analysis_server/tool/spec/generated/java/types/NavigationRegion.java
index a968156..b42bdc7 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/NavigationRegion.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/NavigationRegion.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/NavigationTarget.java b/pkg/analysis_server/tool/spec/generated/java/types/NavigationTarget.java
index 9290862..217d091e 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/NavigationTarget.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/NavigationTarget.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/Occurrences.java b/pkg/analysis_server/tool/spec/generated/java/types/Occurrences.java
index db04138..894fc0a 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/Occurrences.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/Occurrences.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/Outline.java b/pkg/analysis_server/tool/spec/generated/java/types/Outline.java
index 5a6576f..7fd32a1 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/Outline.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/Outline.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/OverriddenMember.java b/pkg/analysis_server/tool/spec/generated/java/types/OverriddenMember.java
index 47c085f..720722a 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/OverriddenMember.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/OverriddenMember.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/OverrideMember.java b/pkg/analysis_server/tool/spec/generated/java/types/OverrideMember.java
index 6fb38e1..264185f 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/OverrideMember.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/OverrideMember.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/Position.java b/pkg/analysis_server/tool/spec/generated/java/types/Position.java
index f5c7acb..3eed81f 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/Position.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/Position.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/PubStatus.java b/pkg/analysis_server/tool/spec/generated/java/types/PubStatus.java
index c46b87a..27e2cfe 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/PubStatus.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/PubStatus.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/RefactoringFeedback.java b/pkg/analysis_server/tool/spec/generated/java/types/RefactoringFeedback.java
index c1864b7..c619daf 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/RefactoringFeedback.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/RefactoringFeedback.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/RefactoringKind.java b/pkg/analysis_server/tool/spec/generated/java/types/RefactoringKind.java
index 822770d..9c8d0a8 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/RefactoringKind.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/RefactoringKind.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 /**
  * An enumeration of the kinds of refactorings that can be created.
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/RefactoringMethodParameter.java b/pkg/analysis_server/tool/spec/generated/java/types/RefactoringMethodParameter.java
index d5f7dfe..532ecfb 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/RefactoringMethodParameter.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/RefactoringMethodParameter.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/RefactoringMethodParameterKind.java b/pkg/analysis_server/tool/spec/generated/java/types/RefactoringMethodParameterKind.java
index c7a059a..146617d 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/RefactoringMethodParameterKind.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/RefactoringMethodParameterKind.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 /**
  * An enumeration of the kinds of parameters.
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/RefactoringOptions.java b/pkg/analysis_server/tool/spec/generated/java/types/RefactoringOptions.java
index 05af2ff..16c4392 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/RefactoringOptions.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/RefactoringOptions.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/RefactoringProblem.java b/pkg/analysis_server/tool/spec/generated/java/types/RefactoringProblem.java
index da87988..3b8ec81 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/RefactoringProblem.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/RefactoringProblem.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/RefactoringProblemSeverity.java b/pkg/analysis_server/tool/spec/generated/java/types/RefactoringProblemSeverity.java
index 823eacc..01ef16f 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/RefactoringProblemSeverity.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/RefactoringProblemSeverity.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 /**
  * An enumeration of the severities of problems that can be returned by the refactoring requests.
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/RemoveContentOverlay.java b/pkg/analysis_server/tool/spec/generated/java/types/RemoveContentOverlay.java
index fb284da..b442848 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/RemoveContentOverlay.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/RemoveContentOverlay.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/RenameFeedback.java b/pkg/analysis_server/tool/spec/generated/java/types/RenameFeedback.java
index c94f2e6..cd31922 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/RenameFeedback.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/RenameFeedback.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/RenameOptions.java b/pkg/analysis_server/tool/spec/generated/java/types/RenameOptions.java
index e17d49e..5ec34ce 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/RenameOptions.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/RenameOptions.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/RequestError.java b/pkg/analysis_server/tool/spec/generated/java/types/RequestError.java
index 20c9b3a..598d83f 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/RequestError.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/RequestError.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/RequestErrorCode.java b/pkg/analysis_server/tool/spec/generated/java/types/RequestErrorCode.java
index 99f418a..d86609d 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/RequestErrorCode.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/RequestErrorCode.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 /**
  * An enumeration of the types of errors that can occur in the execution of the server.
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/SearchResult.java b/pkg/analysis_server/tool/spec/generated/java/types/SearchResult.java
index 19f4eac..6f44743 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/SearchResult.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/SearchResult.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/SearchResultKind.java b/pkg/analysis_server/tool/spec/generated/java/types/SearchResultKind.java
index 4cf530d..ddbe0ef 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/SearchResultKind.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/SearchResultKind.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 /**
  * An enumeration of the kinds of search results returned by the search domain.
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/ServerService.java b/pkg/analysis_server/tool/spec/generated/java/types/ServerService.java
index 4878287..54fb1b3 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/ServerService.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/ServerService.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 /**
  * An enumeration of the services provided by the server domain.
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/SourceChange.java b/pkg/analysis_server/tool/spec/generated/java/types/SourceChange.java
index 7d39be9..45bf4eb 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/SourceChange.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/SourceChange.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/SourceEdit.java b/pkg/analysis_server/tool/spec/generated/java/types/SourceEdit.java
index adcf771..50b6306 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/SourceEdit.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/SourceEdit.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/SourceFileEdit.java b/pkg/analysis_server/tool/spec/generated/java/types/SourceFileEdit.java
index d9d247d..5cfa8a1 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/SourceFileEdit.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/SourceFileEdit.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/TypeHierarchyItem.java b/pkg/analysis_server/tool/spec/generated/java/types/TypeHierarchyItem.java
index 2c14939..bfb0acc 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/TypeHierarchyItem.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/TypeHierarchyItem.java
@@ -14,7 +14,7 @@
  * This file has been automatically generated.  Please do not edit it manually.
  * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
  */
-package com.google.dart.server.generated.types;
+package org.dartlang.analysis.server.protocol;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/pkg/analyzer/lib/src/context/cache.dart b/pkg/analyzer/lib/src/context/cache.dart
index d9fada4..c8aa54d 100644
--- a/pkg/analyzer/lib/src/context/cache.dart
+++ b/pkg/analyzer/lib/src/context/cache.dart
@@ -425,6 +425,15 @@
    */
   /*<V>*/ void setValue(ResultDescriptor /*<V>*/ descriptor, dynamic /*V*/
       value, List<TargetedResult> dependedOn) {
+//    {
+//      String valueStr = '$value';
+//      if (valueStr.length > 20) {
+//        valueStr = valueStr.substring(0, 20) + '...';
+//      }
+//      valueStr = valueStr.replaceAll('\n', '\\n');
+//      print(
+//          'setValue $descriptor for $target value=$valueStr deps=$dependedOn');
+//    }
     _validateStateChange(descriptor, CacheState.VALID);
     TargetedResult thisResult = new TargetedResult(target, descriptor);
     if (_partition != null) {
@@ -464,6 +473,7 @@
    * invalidation to other results that depend on it.
    */
   void _invalidate(ResultDescriptor descriptor) {
+//    print('invalidate $descriptor for $target');
     ResultData thisData = _resultMap.remove(descriptor);
     if (thisData == null) {
       return;
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index 6eee8e9..4dcc143 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -254,7 +254,7 @@
     this._options.lint = options.lint;
     this._options.preserveComments = options.preserveComments;
     if (needsRecompute) {
-      _invalidateAllLocalResolutionInformation(false);
+      dartWorkManager.onAnalysisOptionsChanged();
     }
   }
 
@@ -350,6 +350,9 @@
   List<AnalysisTarget> get priorityTargets => prioritySources;
 
   @override
+  CachePartition get privateAnalysisCachePartition => _privatePartition;
+
+  @override
   SourceFactory get sourceFactory => _sourceFactory;
 
   @override
@@ -366,7 +369,7 @@
     factory.context = this;
     _sourceFactory = factory;
     _cache = createCacheFromSourceFactory(factory);
-    _invalidateAllLocalResolutionInformation(true);
+    dartWorkManager.onSourceFactoryChanged();
   }
 
   @override
@@ -767,38 +770,39 @@
 
   @override
   List<Source> getHtmlFilesReferencing(Source source) {
+    // TODO(brianwilkerson) Implement this.
     SourceKind sourceKind = getKindOf(source);
     if (sourceKind == null) {
       return Source.EMPTY_LIST;
     }
     List<Source> htmlSources = <Source>[];
-    while (true) {
-      if (sourceKind == SourceKind.PART) {
-        List<Source> librarySources = getLibrariesContaining(source);
-        for (Source source in _cache.sources) {
-          CacheEntry entry = _cache.get(source);
-          if (entry.getValue(SOURCE_KIND) == SourceKind.HTML) {
-            List<Source> referencedLibraries =
-                (entry as HtmlEntry).getValue(HtmlEntry.REFERENCED_LIBRARIES);
-            if (_containsAny(referencedLibraries, librarySources)) {
-              htmlSources.add(source);
-            }
-          }
-        }
-      } else {
-        for (Source source in _cache.sources) {
-          CacheEntry entry = _cache.get(source);
-          if (entry.getValue(SOURCE_KIND) == SourceKind.HTML) {
-            List<Source> referencedLibraries =
-                (entry as HtmlEntry).getValue(HtmlEntry.REFERENCED_LIBRARIES);
-            if (_contains(referencedLibraries, source)) {
-              htmlSources.add(source);
-            }
-          }
-        }
-      }
-      break;
-    }
+//    while (true) {
+//      if (sourceKind == SourceKind.PART) {
+//        List<Source> librarySources = getLibrariesContaining(source);
+//        for (Source source in _cache.sources) {
+//          CacheEntry entry = _cache.get(source);
+//          if (entry.getValue(SOURCE_KIND) == SourceKind.HTML) {
+//            List<Source> referencedLibraries =
+//                (entry as HtmlEntry).getValue(HtmlEntry.REFERENCED_LIBRARIES);
+//            if (_containsAny(referencedLibraries, librarySources)) {
+//              htmlSources.add(source);
+//            }
+//          }
+//        }
+//      } else {
+//        for (Source source in _cache.sources) {
+//          CacheEntry entry = _cache.get(source);
+//          if (entry.getValue(SOURCE_KIND) == SourceKind.HTML) {
+//            List<Source> referencedLibraries =
+//                (entry as HtmlEntry).getValue(HtmlEntry.REFERENCED_LIBRARIES);
+//            if (_contains(referencedLibraries, source)) {
+//              htmlSources.add(source);
+//            }
+//          }
+//        }
+//      }
+//      break;
+//    }
     if (htmlSources.isEmpty) {
       return Source.EMPTY_LIST;
     }
@@ -821,10 +825,8 @@
     SourceKind kind = getKindOf(source);
     if (kind == SourceKind.LIBRARY) {
       return <Source>[source];
-    } else if (kind == SourceKind.PART) {
-      return dartWorkManager.getLibrariesContainingPart(source);
     }
-    return Source.EMPTY_ARRAY;
+    return dartWorkManager.getLibrariesContainingPart(source);
   }
 
   @override
@@ -1176,8 +1178,8 @@
   @override
   void visitCacheItems(void callback(Source source, SourceEntry dartEntry,
       DataDescriptor rowDesc, CacheState state)) {
-    // TODO(brianwilkerson) Figure out where this is used and adjust the call
-    // sites to use CacheEntry's.
+    // TODO(brianwilkerson) Figure out where this is used and either remove it
+    // or adjust the call sites to use CacheEntry's.
 //    bool hintsEnabled = _options.hint;
 //    bool lintsEnabled = _options.lint;
 //    MapIterator<AnalysisTarget, cache.CacheEntry> iterator = _cache.iterator();
@@ -1545,36 +1547,6 @@
   }
 
   /**
-   * Invalidate all of the resolution results computed by this context. The flag
-   * [invalidateUris] should be `true` if the cached results of converting URIs
-   * to source files should also be invalidated.
-   */
-  void _invalidateAllLocalResolutionInformation(bool invalidateUris) {
-    HashMap<Source, List<Source>> oldPartMap =
-        new HashMap<Source, List<Source>>();
-    // TODO(brianwilkerson) Implement this
-//    MapIterator<AnalysisTarget, cache.CacheEntry> iterator =
-//        _privatePartition.iterator();
-//    while (iterator.moveNext()) {
-//      AnalysisTarget target = iterator.key;
-//      cache.CacheEntry entry = iterator.value;
-//      if (entry is HtmlEntry) {
-//        HtmlEntry htmlEntry = entry;
-//        htmlEntry.invalidateAllResolutionInformation(invalidateUris);
-//        iterator.value = htmlEntry;
-//        _workManager.add(target, SourcePriority.HTML);
-//      } else if (entry is DartEntry) {
-//        DartEntry dartEntry = entry;
-//        oldPartMap[target] = dartEntry.getValue(DartEntry.INCLUDED_PARTS);
-//        dartEntry.invalidateAllResolutionInformation(invalidateUris);
-//        iterator.value = dartEntry;
-//        _workManager.add(target, _computePriority(dartEntry));
-//      }
-//    }
-    _removeFromPartsUsingMap(oldPartMap);
-  }
-
-  /**
    * Log the given debugging [message].
    */
   void _logInformation(String message) {
@@ -1594,29 +1566,6 @@
   }
 
   /**
-   * Remove the given libraries that are keys in the given map from the list of
-   * containing libraries for each of the parts in the corresponding value.
-   */
-  void _removeFromPartsUsingMap(HashMap<Source, List<Source>> oldPartMap) {
-    // TODO(brianwilkerson) Figure out whether we still need this.
-//    oldPartMap.forEach((Source librarySource, List<Source> oldParts) {
-//      for (int i = 0; i < oldParts.length; i++) {
-//        Source partSource = oldParts[i];
-//        if (partSource != librarySource) {
-//          DartEntry partEntry = _getReadableDartEntry(partSource);
-//          if (partEntry != null) {
-//            partEntry.removeContainingLibrary(librarySource);
-//            if (partEntry.containingLibraries.length == 0 &&
-//                !exists(partSource)) {
-//              _cache.remove(partSource);
-//            }
-//          }
-//        }
-//      }
-//    });
-  }
-
-  /**
    * Remove the given [source] from the priority order if it is in the list.
    */
   void _removeFromPriorityOrder(Source source) {
diff --git a/pkg/analyzer/lib/src/generated/ast.dart b/pkg/analyzer/lib/src/generated/ast.dart
index 3a2822f..e6d8100 100644
--- a/pkg/analyzer/lib/src/generated/ast.dart
+++ b/pkg/analyzer/lib/src/generated/ast.dart
@@ -4676,7 +4676,7 @@
    * The last token in the token stream that was parsed to form this compilation
    * unit. This token should always have a type of [TokenType.EOF].
    */
-  final Token endToken;
+  Token endToken;
 
   /**
    * The element associated with this compilation unit, or `null` if the AST
diff --git a/pkg/analyzer/lib/src/generated/constant.dart b/pkg/analyzer/lib/src/generated/constant.dart
index fa5360b..499ce50 100644
--- a/pkg/analyzer/lib/src/generated/constant.dart
+++ b/pkg/analyzer/lib/src/generated/constant.dart
@@ -418,7 +418,10 @@
         }
       }
     } else if (constant is PotentiallyConstVariableElement) {
-      constant.constantInitializer.accept(referenceFinder);
+      Expression initializer = constant.constantInitializer;
+      if (initializer != null) {
+        initializer.accept(referenceFinder);
+      }
     } else if (constant is ConstructorElementImpl) {
       constant.isCycleFree = false;
       ConstructorElement redirectedConstructor =
diff --git a/pkg/analyzer/lib/src/generated/element.dart b/pkg/analyzer/lib/src/generated/element.dart
index 0fd8b81..9e7eeff 100644
--- a/pkg/analyzer/lib/src/generated/element.dart
+++ b/pkg/analyzer/lib/src/generated/element.dart
@@ -3367,8 +3367,8 @@
   List<FunctionElement> get functions;
 
   /**
-   * Return `true` if this executable element is abstract.
-   * Executable elements are abstract if they are not external and have no body.
+   * Return `true` if this executable element is abstract. Executable elements
+   * are abstract if they are not external and have no body.
    */
   bool get isAbstract;
 
@@ -3379,6 +3379,13 @@
   bool get isAsynchronous;
 
   /**
+   * Return `true` if this executable element is external. Executable elements
+   * are external if they are explicitly marked as such using the 'external'
+   * keyword.
+   */
+  bool get isExternal;
+
+  /**
    * Return `true` if this executable element has a body marked as being a
    * generator.
    */
@@ -3489,12 +3496,19 @@
   ExecutableElementImpl.forNode(Identifier name) : super.forNode(name);
 
   /**
-   * Set whether this method's body is asynchronous.
+   * Set whether this executable element's body is asynchronous.
    */
   void set asynchronous(bool isAsynchronous) {
     setModifier(Modifier.ASYNCHRONOUS, isAsynchronous);
   }
 
+  /**
+   * Set whether this executable element is external.
+   */
+  void set external(bool isExternal) {
+    setModifier(Modifier.EXTERNAL, isExternal);
+  }
+
   @override
   List<FunctionElement> get functions => _functions;
 
@@ -3523,6 +3537,9 @@
   bool get isAsynchronous => hasModifier(Modifier.ASYNCHRONOUS);
 
   @override
+  bool get isExternal => hasModifier(Modifier.EXTERNAL);
+
+  @override
   bool get isGenerator => hasModifier(Modifier.GENERATOR);
 
   @override
@@ -3681,6 +3698,9 @@
   bool get isAsynchronous => baseElement.isAsynchronous;
 
   @override
+  bool get isExternal => baseElement.isExternal;
+
+  @override
   bool get isGenerator => baseElement.isGenerator;
 
   @override
@@ -7968,80 +7988,85 @@
   static const Modifier ENUM = const Modifier('ENUM', 4);
 
   /**
+   * Indicates that a class element was defined by an enum declaration.
+   */
+  static const Modifier EXTERNAL = const Modifier('EXTERNAL', 5);
+
+  /**
    * Indicates that the modifier 'factory' was applied to the element.
    */
-  static const Modifier FACTORY = const Modifier('FACTORY', 5);
+  static const Modifier FACTORY = const Modifier('FACTORY', 6);
 
   /**
    * Indicates that the modifier 'final' was applied to the element.
    */
-  static const Modifier FINAL = const Modifier('FINAL', 6);
+  static const Modifier FINAL = const Modifier('FINAL', 7);
 
   /**
    * Indicates that an executable element has a body marked as being a
    * generator.
    */
-  static const Modifier GENERATOR = const Modifier('GENERATOR', 7);
+  static const Modifier GENERATOR = const Modifier('GENERATOR', 8);
 
   /**
    * Indicates that the pseudo-modifier 'get' was applied to the element.
    */
-  static const Modifier GETTER = const Modifier('GETTER', 8);
+  static const Modifier GETTER = const Modifier('GETTER', 9);
 
   /**
    * A flag used for libraries indicating that the defining compilation unit
    * contains at least one import directive whose URI uses the "dart-ext"
    * scheme.
    */
-  static const Modifier HAS_EXT_URI = const Modifier('HAS_EXT_URI', 9);
+  static const Modifier HAS_EXT_URI = const Modifier('HAS_EXT_URI', 10);
 
   /**
    * Indicates that a class can validly be used as a mixin.
    */
-  static const Modifier MIXIN = const Modifier('MIXIN', 10);
+  static const Modifier MIXIN = const Modifier('MIXIN', 11);
 
   /**
    * Indicates that a class is a mixin application.
    */
   static const Modifier MIXIN_APPLICATION =
-      const Modifier('MIXIN_APPLICATION', 11);
+      const Modifier('MIXIN_APPLICATION', 12);
 
   /**
    * Indicates that an error has reported explaining why this class is an
    * invalid mixin application.
    */
   static const Modifier MIXIN_ERRORS_REPORTED =
-      const Modifier('MIXIN_ERRORS_REPORTED', 12);
+      const Modifier('MIXIN_ERRORS_REPORTED', 13);
 
   /**
    * Indicates that the value of a parameter or local variable might be mutated
    * within the context.
    */
   static const Modifier POTENTIALLY_MUTATED_IN_CONTEXT =
-      const Modifier('POTENTIALLY_MUTATED_IN_CONTEXT', 13);
+      const Modifier('POTENTIALLY_MUTATED_IN_CONTEXT', 14);
 
   /**
    * Indicates that the value of a parameter or local variable might be mutated
    * within the scope.
    */
   static const Modifier POTENTIALLY_MUTATED_IN_SCOPE =
-      const Modifier('POTENTIALLY_MUTATED_IN_SCOPE', 14);
+      const Modifier('POTENTIALLY_MUTATED_IN_SCOPE', 15);
 
   /**
    * Indicates that a class contains an explicit reference to 'super'.
    */
   static const Modifier REFERENCES_SUPER =
-      const Modifier('REFERENCES_SUPER', 15);
+      const Modifier('REFERENCES_SUPER', 16);
 
   /**
    * Indicates that the pseudo-modifier 'set' was applied to the element.
    */
-  static const Modifier SETTER = const Modifier('SETTER', 16);
+  static const Modifier SETTER = const Modifier('SETTER', 17);
 
   /**
    * Indicates that the modifier 'static' was applied to the element.
    */
-  static const Modifier STATIC = const Modifier('STATIC', 17);
+  static const Modifier STATIC = const Modifier('STATIC', 18);
 
   /**
    * Indicates that the element does not appear in the source code but was
@@ -8049,7 +8074,7 @@
    * constructors, an implicit zero-argument constructor will be created and it
    * will be marked as being synthetic.
    */
-  static const Modifier SYNTHETIC = const Modifier('SYNTHETIC', 18);
+  static const Modifier SYNTHETIC = const Modifier('SYNTHETIC', 19);
 
   static const List<Modifier> values = const [
     ABSTRACT,
@@ -8057,6 +8082,7 @@
     CONST,
     DEFERRED,
     ENUM,
+    EXTERNAL,
     FACTORY,
     FINAL,
     GENERATOR,
diff --git a/pkg/analyzer/lib/src/generated/element_handle.dart b/pkg/analyzer/lib/src/generated/element_handle.dart
index 9b8c325..1cba143 100644
--- a/pkg/analyzer/lib/src/generated/element_handle.dart
+++ b/pkg/analyzer/lib/src/generated/element_handle.dart
@@ -521,6 +521,9 @@
   bool get isAsynchronous => actualElement.isAsynchronous;
 
   @override
+  bool get isExternal => actualElement.isExternal;
+
+  @override
   bool get isGenerator => actualElement.isGenerator;
 
   @override
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index dfbac68..ac74c02 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -1352,6 +1352,9 @@
   List<AnalysisTarget> get priorityTargets => prioritySources;
 
   @override
+  CachePartition get privateAnalysisCachePartition => _privatePartition;
+
+  @override
   SourceFactory get sourceFactory => _sourceFactory;
 
   @override
@@ -9059,6 +9062,14 @@
   List<AnalysisTarget> get priorityTargets;
 
   /**
+   * The partition that contains analysis results that are not shared with other
+   * contexts.
+   *
+   * TODO(scheglov) add the type, once we have only one cache.
+   */
+  dynamic get privateAnalysisCachePartition;
+
+  /**
    * A factory to override how [ResolverVisitor] is created.
    */
   ResolverVisitorFactory get resolverVisitorFactory;
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index a56496f..d4eee82 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -2064,10 +2064,6 @@
       sc.Token property = node.propertyKeyword;
       SimpleIdentifier methodName = node.name;
       String nameOfMethod = methodName.name;
-      if (nameOfMethod == sc.TokenType.MINUS.lexeme &&
-          node.parameters.parameters.length == 0) {
-        nameOfMethod = "unary-";
-      }
       if (property == null) {
         _enclosingExecutable = _findWithNameAndOffset(
             _enclosingClass.methods, nameOfMethod, methodName.offset);
@@ -2284,7 +2280,7 @@
   Element _findWithNameAndOffset(
       List<Element> elements, String name, int offset) {
     for (Element element in elements) {
-      if (element.displayName == name && element.nameOffset == offset) {
+      if (element.nameOffset == offset && element.displayName == name) {
         return element;
       }
     }
@@ -2536,6 +2532,9 @@
     SimpleIdentifier constructorName = node.name;
     ConstructorElementImpl element =
         new ConstructorElementImpl.forNode(constructorName);
+    if (node.externalKeyword != null) {
+      element.external = true;
+    }
     if (node.factoryKeyword != null) {
       element.factory = true;
     }
@@ -2695,6 +2694,9 @@
         SimpleIdentifier functionName = node.name;
         FunctionElementImpl element =
             new FunctionElementImpl.forNode(functionName);
+        if (node.externalKeyword != null) {
+          element.external = true;
+        }
         element.functions = holder.functions;
         element.labels = holder.labels;
         element.localVariables = holder.localVariables;
@@ -2734,6 +2736,9 @@
         if (node.isGetter) {
           PropertyAccessorElementImpl getter =
               new PropertyAccessorElementImpl.forNode(propertyNameNode);
+          if (node.externalKeyword != null) {
+            getter.external = true;
+          }
           getter.functions = holder.functions;
           getter.labels = holder.labels;
           getter.localVariables = holder.localVariables;
@@ -2753,6 +2758,9 @@
         } else {
           PropertyAccessorElementImpl setter =
               new PropertyAccessorElementImpl.forNode(propertyNameNode);
+          if (node.externalKeyword != null) {
+            setter.external = true;
+          }
           setter.functions = holder.functions;
           setter.labels = holder.labels;
           setter.localVariables = holder.localVariables;
@@ -2904,6 +2912,9 @@
         MethodElementImpl element =
             new MethodElementImpl(nameOfMethod, methodName.offset);
         element.abstract = node.isAbstract;
+        if (node.externalKeyword != null) {
+          element.external = true;
+        }
         element.functions = holder.functions;
         element.labels = holder.labels;
         element.localVariables = holder.localVariables;
@@ -2932,6 +2943,9 @@
         if (node.isGetter) {
           PropertyAccessorElementImpl getter =
               new PropertyAccessorElementImpl.forNode(propertyNameNode);
+          if (node.externalKeyword != null) {
+            getter.external = true;
+          }
           getter.functions = holder.functions;
           getter.labels = holder.labels;
           getter.localVariables = holder.localVariables;
@@ -2951,6 +2965,9 @@
         } else {
           PropertyAccessorElementImpl setter =
               new PropertyAccessorElementImpl.forNode(propertyNameNode);
+          if (node.externalKeyword != null) {
+            setter.external = true;
+          }
           setter.functions = holder.functions;
           setter.labels = holder.labels;
           setter.localVariables = holder.localVariables;
diff --git a/pkg/analyzer/lib/src/generated/testing/element_factory.dart b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
index 164a666..c648e03 100644
--- a/pkg/analyzer/lib/src/generated/testing/element_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
@@ -15,7 +15,9 @@
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/testing/ast_factory.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:path/path.dart';
 
@@ -516,8 +518,16 @@
 
   static TopLevelVariableElementImpl topLevelVariableElement3(
       String name, bool isConst, bool isFinal, DartType type) {
-    TopLevelVariableElementImpl variable =
-        new TopLevelVariableElementImpl(name, -1);
+    TopLevelVariableElementImpl variable;
+    if (isConst) {
+      ConstTopLevelVariableElementImpl constant =
+          new ConstTopLevelVariableElementImpl(AstFactory.identifier3(name));
+      constant.constantInitializer = AstFactory.instanceCreationExpression2(
+          Keyword.CONST, AstFactory.typeName(type.element));
+      variable = constant;
+    } else {
+      variable = new TopLevelVariableElementImpl(name, -1);
+    }
     variable.const3 = isConst;
     variable.final2 = isFinal;
     variable.synthetic = true;
diff --git a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
index fe0c24b..f24b96b 100644
--- a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
+++ b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
@@ -7,10 +7,14 @@
 
 library engine.testing.test_type_provider;
 
+import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/element.dart';
 import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/src/generated/testing/ast_factory.dart';
 import 'package:analyzer/src/generated/testing/element_factory.dart';
+import 'package:analyzer/src/generated/testing/token_factory.dart';
 
 /**
  * A type provider that can be used by tests without creating the element model
@@ -178,10 +182,13 @@
     if (_deprecatedType == null) {
       ClassElementImpl deprecatedElement =
           ElementFactory.classElement2("Deprecated");
-      deprecatedElement.constructors = <ConstructorElement>[
-        ElementFactory.constructorElement(
-            deprecatedElement, null, true, [stringType])
+      ConstructorElementImpl constructor = ElementFactory.constructorElement(
+          deprecatedElement, null, true, [stringType]);
+      constructor.constantInitializers = <ConstructorInitializer>[
+        AstFactory.constructorFieldInitializer(
+            true, 'expires', AstFactory.identifier3('expires'))
       ];
+      deprecatedElement.constructors = <ConstructorElement>[constructor];
       _deprecatedType = deprecatedElement.type;
     }
     return _deprecatedType;
@@ -369,9 +376,10 @@
     if (_objectType == null) {
       ClassElementImpl objectElement = ElementFactory.object;
       _objectType = objectElement.type;
-      objectElement.constructors = <ConstructorElement>[
-        ElementFactory.constructorElement2(objectElement, null)
-      ];
+      ConstructorElementImpl constructor =
+          ElementFactory.constructorElement(objectElement, null, true);
+      constructor.constantInitializers = <ConstructorInitializer>[];
+      objectElement.constructors = <ConstructorElement>[constructor];
       objectElement.methods = <MethodElement>[
         ElementFactory.methodElement("toString", stringType),
         ElementFactory.methodElement("==", boolType, [_objectType]),
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index 29ab152..f27614d 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -172,6 +172,15 @@
         'HINT_ERRORS', AnalysisError.NO_ERRORS);
 
 /**
+ * The sources representing the combined import/export closure of a library.
+ * The [Source]s include only library sources, not their units.
+ *
+ * The result is only available for [Source]s representing a library.
+ */
+final ListResultDescriptor<Source> IMPORT_EXPORT_SOURCE_CLOSURE =
+    new ListResultDescriptor<Source>('IMPORT_EXPORT_SOURCE_CLOSURE', null);
+
+/**
  * The sources representing the import closure of a library.
  * The [Source]s include only library sources, not their units.
  *
@@ -1322,38 +1331,42 @@
         Source partSource = partDirective.source;
         hasPartDirective = true;
         CompilationUnit partUnit = partUnitMap[partSource];
-        CompilationUnitElementImpl partElement = partUnit.element;
-        partElement.uriOffset = partUri.offset;
-        partElement.uriEnd = partUri.end;
-        partElement.uri = partDirective.uriContent;
-        //
-        // Validate that the part contains a part-of directive with the same
-        // name as the library.
-        //
-        String partLibraryName =
-            _getPartLibraryName(partSource, partUnit, directivesToResolve);
-        if (partLibraryName == null) {
-          errors.add(new AnalysisError(librarySource, partUri.offset,
-              partUri.length, CompileTimeErrorCode.PART_OF_NON_PART,
-              [partUri.toSource()]));
-        } else if (libraryNameNode == null) {
-          if (partsLibraryName == _UNKNOWN_LIBRARY_NAME) {
-            partsLibraryName = partLibraryName;
-          } else if (partsLibraryName != partLibraryName) {
-            partsLibraryName = null;
+        if (partUnit != null) {
+          CompilationUnitElementImpl partElement = partUnit.element;
+          partElement.uriOffset = partUri.offset;
+          partElement.uriEnd = partUri.end;
+          partElement.uri = partDirective.uriContent;
+          //
+          // Validate that the part contains a part-of directive with the same
+          // name as the library.
+          //
+          if (context.exists(partSource)) {
+            String partLibraryName =
+                _getPartLibraryName(partSource, partUnit, directivesToResolve);
+            if (partLibraryName == null) {
+              errors.add(new AnalysisError(librarySource, partUri.offset,
+                  partUri.length, CompileTimeErrorCode.PART_OF_NON_PART,
+                  [partUri.toSource()]));
+            } else if (libraryNameNode == null) {
+              if (partsLibraryName == _UNKNOWN_LIBRARY_NAME) {
+                partsLibraryName = partLibraryName;
+              } else if (partsLibraryName != partLibraryName) {
+                partsLibraryName = null;
+              }
+            } else if (libraryNameNode.name != partLibraryName) {
+              errors.add(new AnalysisError(librarySource, partUri.offset,
+                  partUri.length, StaticWarningCode.PART_OF_DIFFERENT_LIBRARY, [
+                libraryNameNode.name,
+                partLibraryName
+              ]));
+            }
           }
-        } else if (libraryNameNode.name != partLibraryName) {
-          errors.add(new AnalysisError(librarySource, partUri.offset,
-              partUri.length, StaticWarningCode.PART_OF_DIFFERENT_LIBRARY, [
-            libraryNameNode.name,
-            partLibraryName
-          ]));
+          if (entryPoint == null) {
+            entryPoint = _findEntryPoint(partElement);
+          }
+          directive.element = partElement;
+          sourcedCompilationUnits.add(partElement);
         }
-        if (entryPoint == null) {
-          entryPoint = _findEntryPoint(partElement);
-        }
-        directive.element = partElement;
-        sourcedCompilationUnits.add(partElement);
       }
     }
     if (hasPartDirective && libraryNameNode == null) {
@@ -1574,10 +1587,10 @@
    * The task descriptor describing this kind of task.
    */
   static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'BuildExportSourceClosureTask', createTask, buildInputs,
-      <ResultDescriptor>[
+      'BuildSourceClosuresTask', createTask, buildInputs, <ResultDescriptor>[
     IMPORT_SOURCE_CLOSURE,
     EXPORT_SOURCE_CLOSURE,
+    IMPORT_EXPORT_SOURCE_CLOSURE,
     IS_CLIENT
   ]);
 
@@ -1599,6 +1612,7 @@
     //
     outputs[IMPORT_SOURCE_CLOSURE] = importClosure;
     outputs[EXPORT_SOURCE_CLOSURE] = exportClosure;
+    outputs[IMPORT_EXPORT_SOURCE_CLOSURE] = importExportClosure;
     outputs[IS_CLIENT] = importExportClosure.contains(htmlSource);
   }
 
@@ -2577,6 +2591,12 @@
   static const String LINE_INFO_INPUT_NAME = 'LINE_INFO_INPUT_NAME';
 
   /**
+   * The name of the input whose value is the modification time of the file.
+   */
+  static const String MODIFICATION_TIME_INPUT_NAME =
+      'MODIFICATION_TIME_INPUT_NAME';
+
+  /**
    * The name of the input whose value is the token stream produced for the file.
    */
   static const String TOKEN_STREAM_INPUT_NAME = 'TOKEN_STREAM_INPUT_NAME';
@@ -2610,6 +2630,7 @@
   void internalPerform() {
     Source source = getRequiredSource();
     LineInfo lineInfo = getRequiredInput(LINE_INFO_INPUT_NAME);
+    int modificationTime = getRequiredInput(MODIFICATION_TIME_INPUT_NAME);
     Token tokenStream = getRequiredInput(TOKEN_STREAM_INPUT_NAME);
 
     RecordingErrorListener errorListener = new RecordingErrorListener();
@@ -2660,7 +2681,9 @@
     // Compute kind.
     //
     SourceKind sourceKind = SourceKind.LIBRARY;
-    if (!hasNonPartOfDirective && hasPartOfDirective) {
+    if (modificationTime == -1) {
+      sourceKind = SourceKind.UNKNOWN;
+    } else if (hasPartOfDirective && !hasNonPartOfDirective) {
       sourceKind = SourceKind.PART;
     }
     //
@@ -2691,6 +2714,7 @@
   static Map<String, TaskInput> buildInputs(Source source) {
     return <String, TaskInput>{
       LINE_INFO_INPUT_NAME: LINE_INFO.of(source),
+      MODIFICATION_TIME_INPUT_NAME: MODIFICATION_TIME.of(source),
       TOKEN_STREAM_INPUT_NAME: TOKEN_STREAM.of(source)
     };
   }
@@ -2821,11 +2845,11 @@
   static Map<String, TaskInput> buildInputs(Source libSource) {
     return <String, TaskInput>{
       LIBRARY_INPUT: LIBRARY_ELEMENT4.of(libSource),
-      'resolvedUnits': IMPORT_SOURCE_CLOSURE
+      'resolvedUnits': IMPORT_EXPORT_SOURCE_CLOSURE
           .of(libSource)
           .toMapOf(UNITS)
           .toFlattenList((Source library, Source unit) =>
-              RESOLVED_UNIT4.of(new LibrarySpecificUnit(library, unit)))
+              RESOLVED_UNIT4.of(new LibrarySpecificUnit(library, unit))),
     };
   }
 
diff --git a/pkg/analyzer/lib/src/task/dart_work_manager.dart b/pkg/analyzer/lib/src/task/dart_work_manager.dart
index 6d3e6eb..6700e1f 100644
--- a/pkg/analyzer/lib/src/task/dart_work_manager.dart
+++ b/pkg/analyzer/lib/src/task/dart_work_manager.dart
@@ -90,6 +90,13 @@
   AnalysisCache get analysisCache => context.analysisCache;
 
   /**
+   * The partition that contains analysis results that are not shared with other
+   * contexts.
+   */
+  CachePartition get privateAnalysisCachePartition =>
+      context.privateAnalysisCachePartition;
+
+  /**
    * Specifies that the client want the given [result] of the given [target]
    * to be computed with priority.
    */
@@ -243,8 +250,18 @@
     return WorkOrderPriority.NONE;
   }
 
-  void unitIncrementallyResolved(Source librarySource, Source unitSource) {
-    librarySourceQueue.add(librarySource);
+  /**
+   * Notifies the manager about analysis options changes.
+   */
+  void onAnalysisOptionsChanged() {
+    _invalidateAllLocalResolutionInformation(false);
+  }
+
+  /**
+   * Notifies the manager about [SourceFactory] changes.
+   */
+  void onSourceFactoryChanged() {
+    _invalidateAllLocalResolutionInformation(true);
   }
 
   @override
@@ -272,6 +289,7 @@
               partLibrariesMap.putIfAbsent(part, () => <Source>[]);
           if (!libraries.contains(library)) {
             libraries.add(library);
+            _invalidateContainingLibraries(part);
           }
         }
       }
@@ -309,6 +327,66 @@
     }
   }
 
+  void unitIncrementallyResolved(Source librarySource, Source unitSource) {
+    librarySourceQueue.add(librarySource);
+  }
+
+  /**
+   * Invalidate all of the resolution results computed by this context. The flag
+   * [invalidateUris] should be `true` if the cached results of converting URIs
+   * to source files should also be invalidated.
+   */
+  void _invalidateAllLocalResolutionInformation(bool invalidateUris) {
+    CachePartition partition = privateAnalysisCachePartition;
+    // Prepare targets and values to invalidate.
+    List<Source> dartSources = <Source>[];
+    List<LibrarySpecificUnit> unitTargets = <LibrarySpecificUnit>[];
+    MapIterator<AnalysisTarget, CacheEntry> iterator = partition.iterator();
+    while (iterator.moveNext()) {
+      AnalysisTarget target = iterator.key;
+      // Optionally gather Dart sources to invalidate URIs resolution.
+      if (invalidateUris && _isDartSource(target)) {
+        dartSources.add(target);
+      }
+      // LibrarySpecificUnit(s) are roots of Dart resolution.
+      // When one is invalidated, invalidation is propagated to all resolution.
+      if (target is LibrarySpecificUnit) {
+        unitTargets.add(target);
+        Source library = target.library;
+        if (context.exists(library)) {
+          librarySourceQueue.add(library);
+        }
+      }
+    }
+    // Invalidate targets and values.
+    unitTargets.forEach(partition.remove);
+    for (Source dartSource in dartSources) {
+      CacheEntry entry = partition.get(dartSource);
+      if (dartSource != null) {
+        // TODO(scheglov) we invalidate too much.
+        // Would be nice to invalidate just URLs resolution.
+        entry.setState(PARSED_UNIT, CacheState.INVALID);
+        entry.setState(IMPORTED_LIBRARIES, CacheState.INVALID);
+        entry.setState(EXPLICITLY_IMPORTED_LIBRARIES, CacheState.INVALID);
+        entry.setState(EXPORTED_LIBRARIES, CacheState.INVALID);
+        entry.setState(INCLUDED_PARTS, CacheState.INVALID);
+      }
+    }
+  }
+
+  /**
+   * Invalidate  [CONTAINING_LIBRARIES] for the given [source].
+   * [CONTAINING_LIBRARIES] does not have dependencies, so we manage it here.
+   * The [source] may be a part, or a library whose contents is updated so
+   * will be a part.
+   */
+  void _invalidateContainingLibraries(Source source) {
+    CacheEntry entry = analysisCache.get(source);
+    if (entry != null) {
+      entry.setState(CONTAINING_LIBRARIES, CacheState.INVALID);
+    }
+  }
+
   /**
    * Returns `true` if the given [result] of the given [target] needs
    * computing, i.e. it is not in the valid and not in the error state.
@@ -329,9 +407,11 @@
         List<Source> libraries = partLibrariesMap[part];
         if (libraries != null) {
           libraries.remove(library);
+          _invalidateContainingLibraries(part);
         }
       }
     }
+    _invalidateContainingLibraries(library);
   }
 
   static bool _isDartSource(AnalysisTarget target) {
diff --git a/pkg/analyzer/lib/src/task/driver.dart b/pkg/analyzer/lib/src/task/driver.dart
index 87929c0..36781f5 100644
--- a/pkg/analyzer/lib/src/task/driver.dart
+++ b/pkg/analyzer/lib/src/task/driver.dart
@@ -17,6 +17,9 @@
 import 'package:analyzer/src/task/manager.dart';
 import 'package:analyzer/task/model.dart';
 
+final PerformanceTag workOrderMoveNextPerfTag =
+    new PerformanceTag('WorkOrder.moveNext');
+
 /**
  * An object that is used to cause analysis to be performed until all of the
  * required analysis information has been computed.
@@ -123,6 +126,7 @@
       }
       // Create a new WorkOrder.
       TargetedResult request = highestManager.getNextResult();
+//      print('request: $request');
       if (request != null) {
         WorkOrder workOrder =
             createWorkOrderForResult(request.target, request.result);
@@ -716,29 +720,31 @@
 
   @override
   bool moveNext() {
-    if (currentItems != null && currentItems.length > 1) {
-      // Yield more items.
-      currentItems.removeLast();
-      return true;
-    } else {
-      // Get a new strongly connected component.
-      StronglyConnectedComponent<WorkItem> nextStronglyConnectedComponent =
-          _dependencyWalker.getNextStronglyConnectedComponent();
-      if (nextStronglyConnectedComponent == null) {
-        currentItems = null;
-        return false;
-      }
-      currentItems = nextStronglyConnectedComponent.nodes;
-      if (nextStronglyConnectedComponent.containsCycle) {
-        // A cycle has been found.
-        for (WorkItem item in currentItems) {
-          item.dependencyCycle = currentItems.toList();
-        }
+    return workOrderMoveNextPerfTag.makeCurrentWhile(() {
+      if (currentItems != null && currentItems.length > 1) {
+        // Yield more items.
+        currentItems.removeLast();
+        return true;
       } else {
-        assert(currentItems.length == 1);
+        // Get a new strongly connected component.
+        StronglyConnectedComponent<WorkItem> nextStronglyConnectedComponent =
+            _dependencyWalker.getNextStronglyConnectedComponent();
+        if (nextStronglyConnectedComponent == null) {
+          currentItems = null;
+          return false;
+        }
+        currentItems = nextStronglyConnectedComponent.nodes;
+        if (nextStronglyConnectedComponent.containsCycle) {
+          // A cycle has been found.
+          for (WorkItem item in currentItems) {
+            item.dependencyCycle = currentItems.toList();
+          }
+        } else {
+          assert(currentItems.length == 1);
+        }
+        return true;
       }
-      return true;
-    }
+    });
   }
 }
 
diff --git a/pkg/analyzer/lib/src/task/incremental_element_builder.dart b/pkg/analyzer/lib/src/task/incremental_element_builder.dart
index a01122d..4896b5d 100644
--- a/pkg/analyzer/lib/src/task/incremental_element_builder.dart
+++ b/pkg/analyzer/lib/src/task/incremental_element_builder.dart
@@ -13,35 +13,68 @@
 import 'package:analyzer/src/generated/source.dart';
 
 /**
+ * The change of a single [CompilationUnitElement].
+ */
+class CompilationUnitElementDelta {
+  /**
+   * One or more directives were added/removed.
+   */
+  bool hasDirectiveChange = false;
+
+  /**
+   * The list of added top-level element.
+   */
+  final List<Element> addedDeclarations = <Element>[];
+
+  /**
+   * The list of removed top-level elements.
+   */
+  final List<Element> removedDeclarations = <Element>[];
+}
+
+/**
  * Incrementally updates the existing [unitElement] and builds elements for
  * the [newUnit].
  */
 class IncrementalCompilationUnitElementBuilder {
-  final Source source;
+  final Source unitSource;
   final Source librarySource;
   final CompilationUnit oldUnit;
   final CompilationUnitElementImpl unitElement;
   final CompilationUnit newUnit;
   final ElementHolder holder = new ElementHolder();
 
-  IncrementalCompilationUnitElementBuilder(
-      CompilationUnit oldUnit, this.newUnit)
-      : oldUnit = oldUnit,
-        unitElement = oldUnit.element,
-        source = oldUnit.element.source,
-        librarySource = (oldUnit.element as CompilationUnitElementImpl).librarySource;
+  /**
+   * The change between element models of [oldUnit] and [newUnit].
+   */
+  final CompilationUnitElementDelta unitDelta =
+      new CompilationUnitElementDelta();
 
+  factory IncrementalCompilationUnitElementBuilder(
+      CompilationUnit oldUnit, CompilationUnit newUnit) {
+    CompilationUnitElementImpl unitElement = oldUnit.element;
+    return new IncrementalCompilationUnitElementBuilder._(unitElement.source,
+        unitElement.librarySource, oldUnit, newUnit, unitElement);
+  }
+
+  IncrementalCompilationUnitElementBuilder._(this.unitSource,
+      this.librarySource, this.oldUnit, this.newUnit, this.unitElement);
+
+  /**
+   * Updates [oldUnit] to have the same directives and declarations, in the
+   * same order as in [newUnit]. Existing resolution is kept where possible.
+   *
+   * Updates [unitElement] by adding/removing elements as needed.
+   *
+   * Fills [unitDelta] with added/remove elements.
+   */
   void build() {
     new CompilationUnitBuilder().buildCompilationUnit(
-        source, newUnit, librarySource);
+        unitSource, newUnit, librarySource);
     _processDirectives();
     _processUnitMembers();
     newUnit.element = unitElement;
-  }
-
-  void _addElementsToHolder(CompilationUnitMember node) {
-    List<Element> elements = _getElements(node);
-    elements.forEach(_addElementToHolder);
+    _replaceUnitContents(oldUnit, newUnit);
   }
 
   void _addElementToHolder(Element element) {
@@ -69,11 +102,13 @@
       oldDirectiveMap[code] = oldDirective;
     }
     // Replace new nodes with the identical old nodes.
+    Set<Directive> removedDirectives = oldUnit.directives.toSet();
     for (Directive newDirective in newUnit.directives) {
       String code = TokenUtils.getFullCode(newDirective);
       // Prepare an old directive.
       Directive oldDirective = oldDirectiveMap[code];
       if (oldDirective == null) {
+        unitDelta.hasDirectiveChange = true;
         continue;
       }
       // URI's must be resolved to the same sources.
@@ -85,6 +120,11 @@
       }
       // Do replacement.
       _replaceNode(newDirective, oldDirective);
+      removedDirectives.remove(oldDirective);
+    }
+    // If there are any directives left, then these directives were removed.
+    if (removedDirectives.isNotEmpty) {
+      unitDelta.hasDirectiveChange = true;
     }
   }
 
@@ -95,19 +135,32 @@
       String code = TokenUtils.getFullCode(oldNode);
       oldNodeMap[code] = oldNode;
     }
+    // Prepare all old top-level elements.
+    Set<Element> removedElements = new Set<Element>();
+    removedElements.addAll(unitElement.accessors);
+    removedElements.addAll(unitElement.enums);
+    removedElements.addAll(unitElement.functions);
+    removedElements.addAll(unitElement.functionTypeAliases);
+    removedElements.addAll(unitElement.types);
+    removedElements.addAll(unitElement.topLevelVariables);
     // Replace new nodes with the identical old nodes.
     for (CompilationUnitMember newNode in newUnit.declarations) {
       String code = TokenUtils.getFullCode(newNode);
       // Prepare an old node.
       CompilationUnitMember oldNode = oldNodeMap[code];
       if (oldNode == null) {
-        _addElementsToHolder(newNode);
+        List<Element> elements = _getElements(newNode);
+        elements.forEach(_addElementToHolder);
+        elements.forEach(unitDelta.addedDeclarations.add);
         continue;
       }
       // Do replacement.
       _replaceNode(newNode, oldNode);
-      _addElementsToHolder(oldNode);
+      List<Element> elements = _getElements(oldNode);
+      elements.forEach(_addElementToHolder);
+      elements.forEach(removedElements.remove);
     }
+    unitDelta.removedDeclarations.addAll(removedElements);
     // Update CompilationUnitElement.
     unitElement.accessors = holder.accessors;
     unitElement.enums = holder.enums;
@@ -177,6 +230,20 @@
     }
     return elements;
   }
+
+  /**
+   * Replaces contents of the [to] unit with the contenxts of the [from] unit.
+   */
+  static void _replaceUnitContents(CompilationUnit to, CompilationUnit from) {
+    to.directives.clear();
+    to.declarations.clear();
+    to.beginToken = from.beginToken;
+    to.scriptTag = from.scriptTag;
+    to.directives.addAll(from.directives);
+    to.declarations.addAll(from.declarations);
+    to.element = to.element;
+    to.lineInfo = from.lineInfo;
+  }
 }
 
 /**
diff --git a/pkg/analyzer/test/generated/all_the_rest_test.dart b/pkg/analyzer/test/generated/all_the_rest_test.dart
index 4937cc8..248ea3d 100644
--- a/pkg/analyzer/test/generated/all_the_rest_test.dart
+++ b/pkg/analyzer/test/generated/all_the_rest_test.dart
@@ -31,6 +31,7 @@
 import 'package:analyzer/src/generated/testing/element_factory.dart';
 import 'package:analyzer/src/generated/testing/html_factory.dart';
 import 'package:analyzer/src/generated/testing/test_type_provider.dart';
+import 'package:analyzer/src/generated/testing/token_factory.dart';
 import 'package:analyzer/src/generated/utilities_collection.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/task/dart.dart';
@@ -5154,6 +5155,30 @@
     expect(type.typeParameters[0].name, equals('T'));
   }
 
+  void test_visitConstructorDeclaration_external() {
+    ElementHolder holder = new ElementHolder();
+    ElementBuilder builder = new ElementBuilder(holder);
+    String className = "A";
+    ConstructorDeclaration constructorDeclaration = AstFactory
+        .constructorDeclaration2(null, null, AstFactory.identifier3(className),
+            null, AstFactory.formalParameterList(), null,
+            AstFactory.blockFunctionBody2());
+    constructorDeclaration.externalKeyword =
+        TokenFactory.tokenFromKeyword(Keyword.EXTERNAL);
+    constructorDeclaration.accept(builder);
+    List<ConstructorElement> constructors = holder.constructors;
+    expect(constructors, hasLength(1));
+    ConstructorElement constructor = constructors[0];
+    expect(constructor, isNotNull);
+    expect(constructor.isExternal, isTrue);
+    expect(constructor.isFactory, isFalse);
+    expect(constructor.name, "");
+    expect(constructor.functions, hasLength(0));
+    expect(constructor.labels, hasLength(0));
+    expect(constructor.localVariables, hasLength(0));
+    expect(constructor.parameters, hasLength(0));
+  }
+
   void test_visitConstructorDeclaration_factory() {
     ElementHolder holder = new ElementHolder();
     ElementBuilder builder = new ElementBuilder(holder);
@@ -5168,6 +5193,7 @@
     expect(constructors, hasLength(1));
     ConstructorElement constructor = constructors[0];
     expect(constructor, isNotNull);
+    expect(constructor.isExternal, isFalse);
     expect(constructor.isFactory, isTrue);
     expect(constructor.name, "");
     expect(constructor.functions, hasLength(0));
@@ -5189,6 +5215,7 @@
     expect(constructors, hasLength(1));
     ConstructorElement constructor = constructors[0];
     expect(constructor, isNotNull);
+    expect(constructor.isExternal, isFalse);
     expect(constructor.isFactory, isFalse);
     expect(constructor.name, "");
     expect(constructor.functions, hasLength(0));
@@ -5211,6 +5238,7 @@
     expect(constructors, hasLength(1));
     ConstructorElement constructor = constructors[0];
     expect(constructor, isNotNull);
+    expect(constructor.isExternal, isFalse);
     expect(constructor.isFactory, isFalse);
     expect(constructor.name, constructorName);
     expect(constructor.functions, hasLength(0));
@@ -5234,6 +5262,7 @@
     expect(constructors, hasLength(1));
     ConstructorElement constructor = constructors[0];
     expect(constructor, isNotNull);
+    expect(constructor.isExternal, isFalse);
     expect(constructor.isFactory, isFalse);
     expect(constructor.name, "");
     expect(constructor.functions, hasLength(0));
@@ -5343,6 +5372,27 @@
     expect(parameters[1].name, secondParameterName);
   }
 
+  void test_visitFunctionDeclaration_external() {
+    ElementHolder holder = new ElementHolder();
+    ElementBuilder builder = new ElementBuilder(holder);
+    String functionName = "f";
+    FunctionDeclaration declaration = AstFactory.functionDeclaration(null, null,
+        functionName, AstFactory.functionExpression2(
+            AstFactory.formalParameterList(), AstFactory.blockFunctionBody2()));
+    declaration.externalKeyword =
+        TokenFactory.tokenFromKeyword(Keyword.EXTERNAL);
+    declaration.accept(builder);
+    List<FunctionElement> functions = holder.functions;
+    expect(functions, hasLength(1));
+    FunctionElement function = functions[0];
+    expect(function, isNotNull);
+    expect(function.name, functionName);
+    expect(declaration.element, same(function));
+    expect(declaration.functionExpression.element, same(function));
+    expect(function.isExternal, isTrue);
+    expect(function.isSynthetic, isFalse);
+  }
+
   void test_visitFunctionDeclaration_getter() {
     ElementHolder holder = new ElementHolder();
     ElementBuilder builder = new ElementBuilder(holder);
@@ -5359,6 +5409,7 @@
     expect(declaration.element, same(accessor));
     expect(declaration.functionExpression.element, same(accessor));
     expect(accessor.isGetter, isTrue);
+    expect(accessor.isExternal, isFalse);
     expect(accessor.isSetter, isFalse);
     expect(accessor.isSynthetic, isFalse);
     PropertyInducingElement variable = accessor.variable;
@@ -5382,6 +5433,7 @@
     expect(function.name, functionName);
     expect(declaration.element, same(function));
     expect(declaration.functionExpression.element, same(function));
+    expect(function.isExternal, isFalse);
     expect(function.isSynthetic, isFalse);
   }
 
@@ -5401,6 +5453,7 @@
     expect(declaration.element, same(accessor));
     expect(declaration.functionExpression.element, same(accessor));
     expect(accessor.isGetter, isFalse);
+    expect(accessor.isExternal, isFalse);
     expect(accessor.isSetter, isTrue);
     expect(accessor.isSynthetic, isFalse);
     PropertyInducingElement variable = accessor.variable;
@@ -5502,6 +5555,32 @@
     expect(method.localVariables, hasLength(0));
     expect(method.parameters, hasLength(0));
     expect(method.isAbstract, isTrue);
+    expect(method.isExternal, isFalse);
+    expect(method.isStatic, isFalse);
+    expect(method.isSynthetic, isFalse);
+  }
+
+  void test_visitMethodDeclaration_external() {
+    ElementHolder holder = new ElementHolder();
+    ElementBuilder builder = new ElementBuilder(holder);
+    String methodName = "m";
+    MethodDeclaration methodDeclaration = AstFactory.methodDeclaration2(null,
+        null, null, null, AstFactory.identifier3(methodName),
+        AstFactory.formalParameterList(), AstFactory.emptyFunctionBody());
+    methodDeclaration.externalKeyword =
+        TokenFactory.tokenFromKeyword(Keyword.EXTERNAL);
+    methodDeclaration.accept(builder);
+    List<MethodElement> methods = holder.methods;
+    expect(methods, hasLength(1));
+    MethodElement method = methods[0];
+    expect(method, isNotNull);
+    expect(method.name, methodName);
+    expect(method.functions, hasLength(0));
+    expect(method.labels, hasLength(0));
+    expect(method.localVariables, hasLength(0));
+    expect(method.parameters, hasLength(0));
+    expect(method.isAbstract, isFalse);
+    expect(method.isExternal, isTrue);
     expect(method.isStatic, isFalse);
     expect(method.isSynthetic, isFalse);
   }
@@ -5524,6 +5603,7 @@
     PropertyAccessorElement getter = field.getter;
     expect(getter, isNotNull);
     expect(getter.isAbstract, isFalse);
+    expect(getter.isExternal, isFalse);
     expect(getter.isGetter, isTrue);
     expect(getter.isSynthetic, isFalse);
     expect(getter.name, methodName);
@@ -5552,6 +5632,7 @@
     PropertyAccessorElement getter = field.getter;
     expect(getter, isNotNull);
     expect(getter.isAbstract, isTrue);
+    expect(getter.isExternal, isFalse);
     expect(getter.isGetter, isTrue);
     expect(getter.isSynthetic, isFalse);
     expect(getter.name, methodName);
@@ -5569,6 +5650,8 @@
     MethodDeclaration methodDeclaration = AstFactory.methodDeclaration(null,
         null, Keyword.GET, null, AstFactory.identifier3(methodName),
         AstFactory.formalParameterList());
+    methodDeclaration.externalKeyword =
+        TokenFactory.tokenFromKeyword(Keyword.EXTERNAL);
     methodDeclaration.accept(builder);
     List<FieldElement> fields = holder.fields;
     expect(fields, hasLength(1));
@@ -5580,6 +5663,7 @@
     PropertyAccessorElement getter = field.getter;
     expect(getter, isNotNull);
     expect(getter.isAbstract, isFalse);
+    expect(getter.isExternal, isTrue);
     expect(getter.isGetter, isTrue);
     expect(getter.isSynthetic, isFalse);
     expect(getter.name, methodName);
@@ -5608,6 +5692,7 @@
     expect(method.localVariables, hasLength(0));
     expect(method.parameters, hasLength(0));
     expect(method.isAbstract, isFalse);
+    expect(method.isExternal, isFalse);
     expect(method.isStatic, isFalse);
     expect(method.isSynthetic, isFalse);
   }
@@ -5632,6 +5717,7 @@
     expect(method.localVariables, hasLength(0));
     expect(method.parameters, hasLength(1));
     expect(method.isAbstract, isFalse);
+    expect(method.isExternal, isFalse);
     expect(method.isStatic, isFalse);
     expect(method.isSynthetic, isFalse);
   }
@@ -5654,6 +5740,7 @@
     PropertyAccessorElement setter = field.setter;
     expect(setter, isNotNull);
     expect(setter.isAbstract, isFalse);
+    expect(setter.isExternal, isFalse);
     expect(setter.isSetter, isTrue);
     expect(setter.isSynthetic, isFalse);
     expect(setter.name, "$methodName=");
@@ -5683,6 +5770,7 @@
     PropertyAccessorElement setter = field.setter;
     expect(setter, isNotNull);
     expect(setter.isAbstract, isTrue);
+    expect(setter.isExternal, isFalse);
     expect(setter.isSetter, isTrue);
     expect(setter.isSynthetic, isFalse);
     expect(setter.name, "$methodName=");
@@ -5701,6 +5789,8 @@
     MethodDeclaration methodDeclaration = AstFactory.methodDeclaration(null,
         null, Keyword.SET, null, AstFactory.identifier3(methodName),
         AstFactory.formalParameterList());
+    methodDeclaration.externalKeyword =
+        TokenFactory.tokenFromKeyword(Keyword.EXTERNAL);
     methodDeclaration.accept(builder);
     List<FieldElement> fields = holder.fields;
     expect(fields, hasLength(1));
@@ -5712,6 +5802,7 @@
     PropertyAccessorElement setter = field.setter;
     expect(setter, isNotNull);
     expect(setter.isAbstract, isFalse);
+    expect(setter.isExternal, isTrue);
     expect(setter.isSetter, isTrue);
     expect(setter.isSynthetic, isFalse);
     expect(setter.name, "$methodName=");
@@ -5741,6 +5832,7 @@
     expect(method.localVariables, hasLength(0));
     expect(method.parameters, hasLength(0));
     expect(method.isAbstract, isFalse);
+    expect(method.isExternal, isFalse);
     expect(method.isStatic, isTrue);
     expect(method.isSynthetic, isFalse);
   }
@@ -5772,6 +5864,7 @@
     expect(method, isNotNull);
     expect(method.name, methodName);
     expect(method.isAbstract, isFalse);
+    expect(method.isExternal, isFalse);
     expect(method.isStatic, isFalse);
     expect(method.isSynthetic, isFalse);
     List<VariableElement> parameters = method.parameters;
@@ -7788,7 +7881,7 @@
 
 @reflectiveTest
 class HtmlUnitBuilderTest extends EngineTestCase {
-  AnalysisContextImpl _context;
+  InternalAnalysisContext _context;
   @override
   void setUp() {
     _context = AnalysisContextFactory.contextWithCore();
@@ -7917,14 +8010,9 @@
 @reflectiveTest
 class HtmlWarningCodeTest extends EngineTestCase {
   /**
-   * The source factory used to create the sources to be resolved.
-   */
-  SourceFactory _sourceFactory;
-
-  /**
    * The analysis context used to resolve the HTML files.
    */
-  AnalysisContextImpl _context;
+  InternalAnalysisContext _context;
 
   /**
    * The contents of the 'test.html' file.
@@ -7937,14 +8025,11 @@
   List<AnalysisError> _errors;
   @override
   void setUp() {
-    _sourceFactory = new SourceFactory([new FileUriResolver()]);
-    _context = new AnalysisContextImpl();
-    _context.sourceFactory = _sourceFactory;
+    _context = AnalysisContextFactory.contextWithCore();
   }
 
   @override
   void tearDown() {
-    _sourceFactory = null;
     _context = null;
     _contents = null;
     _errors = null;
diff --git a/pkg/analyzer/test/generated/element_test.dart b/pkg/analyzer/test/generated/element_test.dart
index 13d08e5..eeee8c4 100644
--- a/pkg/analyzer/test/generated/element_test.dart
+++ b/pkg/analyzer/test/generated/element_test.dart
@@ -10,7 +10,7 @@
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/element.dart';
 import 'package:analyzer/src/generated/engine.dart'
-    show AnalysisContext, AnalysisContextImpl;
+    show AnalysisContext, AnalysisOptionsImpl;
 import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/generated/testing/ast_factory.dart';
@@ -36,6 +36,7 @@
   runReflectiveTests(ElementImplTest);
   runReflectiveTests(HtmlElementImplTest);
   runReflectiveTests(LibraryElementImplTest);
+  runReflectiveTests(MethodElementImplTest);
   runReflectiveTests(MultiplyDefinedElementImplTest);
   runReflectiveTests(ParameterElementImplTest);
 }
@@ -1063,7 +1064,7 @@
   }
 
   void test_isAccessibleIn_private_differentLibrary() {
-    AnalysisContextImpl context = createAnalysisContext();
+    AnalysisContext context = createAnalysisContext();
     LibraryElementImpl library1 = ElementFactory.library(context, "lib1");
     ClassElement classElement = ElementFactory.classElement2("_C");
     (library1.definingCompilationUnit as CompilationUnitElementImpl).types =
@@ -1082,7 +1083,7 @@
   }
 
   void test_isAccessibleIn_public_differentLibrary() {
-    AnalysisContextImpl context = createAnalysisContext();
+    AnalysisContext context = createAnalysisContext();
     LibraryElementImpl library1 = ElementFactory.library(context, "lib1");
     ClassElement classElement = ElementFactory.classElement2("C");
     (library1.definingCompilationUnit as CompilationUnitElementImpl).types =
@@ -1959,27 +1960,27 @@
 @reflectiveTest
 class HtmlElementImplTest extends EngineTestCase {
   void test_equals_differentSource() {
-    AnalysisContextImpl context = createAnalysisContext();
+    AnalysisContext context = createAnalysisContext();
     HtmlElementImpl elementA = ElementFactory.htmlUnit(context, "indexA.html");
     HtmlElementImpl elementB = ElementFactory.htmlUnit(context, "indexB.html");
     expect(elementA == elementB, isFalse);
   }
 
   void test_equals_null() {
-    AnalysisContextImpl context = createAnalysisContext();
+    AnalysisContext context = createAnalysisContext();
     HtmlElementImpl element = ElementFactory.htmlUnit(context, "index.html");
     expect(element == null, isFalse);
   }
 
   void test_equals_sameSource() {
-    AnalysisContextImpl context = createAnalysisContext();
+    AnalysisContext context = createAnalysisContext();
     HtmlElementImpl elementA = ElementFactory.htmlUnit(context, "index.html");
     HtmlElementImpl elementB = ElementFactory.htmlUnit(context, "index.html");
     expect(elementA == elementB, isTrue);
   }
 
   void test_equals_self() {
-    AnalysisContextImpl context = createAnalysisContext();
+    AnalysisContext context = createAnalysisContext();
     HtmlElementImpl element = ElementFactory.htmlUnit(context, "index.html");
     expect(element == element, isTrue);
   }
@@ -3863,6 +3864,71 @@
 }
 
 @reflectiveTest
+class MethodElementImplTest extends EngineTestCase {
+  void test_computeNode() {
+    AnalysisContextHelper contextHelper = new AnalysisContextHelper();
+    AnalysisContext context = contextHelper.context;
+    Source source = contextHelper.addSource("/test.dart", r'''
+abstract class A {
+  String m1() => null;
+  m2();
+}
+''');
+    // prepare CompilationUnitElement
+    LibraryElement libraryElement = context.computeLibraryElement(source);
+    CompilationUnitElement unitElement = libraryElement.definingCompilationUnit;
+    // m1
+    {
+      MethodElement m1Element = unitElement.getType("A").getMethod('m1');
+      MethodDeclaration m1Node = m1Element.computeNode();
+      expect(m1Node, isNotNull);
+      expect(m1Node.name.name, "m1");
+      expect(m1Node.element, same(m1Element));
+    }
+    // m2
+    {
+      MethodElement m2Element = unitElement.getType("A").getMethod('m2');
+      MethodDeclaration m2Node = m2Element.computeNode();
+      expect(m2Node, isNotNull);
+      expect(m2Node.name.name, "m2");
+      expect(m2Node.element, same(m2Element));
+    }
+  }
+
+  void test_computeNode_withoutFunctionBody() {
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.analyzeFunctionBodies = false;
+    AnalysisContextHelper contextHelper = new AnalysisContextHelper(options);
+    AnalysisContext context = contextHelper.context;
+    Source source = contextHelper.addSource("/test.dart", r'''
+abstract class A {
+  String m1() => null;
+  m2();
+}
+''');
+    // prepare CompilationUnitElement
+    LibraryElement libraryElement = context.computeLibraryElement(source);
+    CompilationUnitElement unitElement = libraryElement.definingCompilationUnit;
+    // m1
+    {
+      MethodElement m1Element = unitElement.getType("A").getMethod('m1');
+      MethodDeclaration m1Node = m1Element.computeNode();
+      expect(m1Node, isNotNull);
+      expect(m1Node.name.name, "m1");
+      expect(m1Node.element, same(m1Element));
+    }
+    // m2
+    {
+      MethodElement m2Element = unitElement.getType("A").getMethod('m2');
+      MethodDeclaration m2Node = m2Element.computeNode();
+      expect(m2Node, isNotNull);
+      expect(m2Node.name.name, "m2");
+      expect(m2Node.element, same(m2Element));
+    }
+  }
+}
+
+@reflectiveTest
 class MultiplyDefinedElementImplTest extends EngineTestCase {
   void test_fromElements_conflicting() {
     Element firstElement = ElementFactory.localVariableElement2("xx");
diff --git a/pkg/analyzer/test/generated/engine_test.dart b/pkg/analyzer/test/generated/engine_test.dart
index f6e60396..85ffcab 100644
--- a/pkg/analyzer/test/generated/engine_test.dart
+++ b/pkg/analyzer/test/generated/engine_test.dart
@@ -311,7 +311,7 @@
   }
 
   void test_applyChanges_change_flush_element() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     Source librarySource = _addSource("/lib.dart", r'''
 library lib;
@@ -324,7 +324,7 @@
   }
 
   Future test_applyChanges_change_multiple() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     SourcesChangedListener listener = new SourcesChangedListener();
     _context.onSourcesChanged.listen(listener.onData);
     _sourceFactory = _context.sourceFactory;
@@ -416,7 +416,7 @@
   }
 
   Future test_applyChanges_remove() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     SourcesChangedListener listener = new SourcesChangedListener();
     _context.onSourcesChanged.listen(listener.onData);
     _sourceFactory = _context.sourceFactory;
@@ -452,7 +452,7 @@
   }
 
   Future test_applyChanges_removeContainer() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     SourcesChangedListener listener = new SourcesChangedListener();
     _context.onSourcesChanged.listen(listener.onData);
     _sourceFactory = _context.sourceFactory;
@@ -485,7 +485,7 @@
   }
 
   void test_computeDocumentationComment_block() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     String comment = "/** Comment */";
     Source source = _addSource("/test.dart", """
@@ -499,7 +499,7 @@
   }
 
   void test_computeDocumentationComment_none() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     Source source = _addSource("/test.dart", "class A {}");
     LibraryElement libraryElement = _context.computeLibraryElement(source);
@@ -514,7 +514,7 @@
   }
 
   void test_computeDocumentationComment_singleLine_multiple_EOL_n() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     String comment = "/// line 1\n/// line 2\n/// line 3\n";
     Source source = _addSource("/test.dart", "${comment}class A {}");
@@ -527,7 +527,7 @@
   }
 
   void test_computeDocumentationComment_singleLine_multiple_EOL_rn() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     String comment = "/// line 1\r\n/// line 2\r\n/// line 3\r\n";
     Source source = _addSource("/test.dart", "${comment}class A {}");
@@ -627,7 +627,7 @@
   }
 
   void test_computeLibraryElement() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     Source source = _addSource("/test.dart", "library lib;");
     LibraryElement element = _context.computeLibraryElement(source);
@@ -685,7 +685,7 @@
   }
 
   Future test_computeResolvedCompilationUnitAsync() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     Source source = _addSource("/lib.dart", "library lib;");
     // Complete all pending analysis tasks and flush the AST so that it won't
@@ -709,7 +709,7 @@
   }
 
   Future test_computeResolvedCompilationUnitAsync_afterDispose() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     Source source = _addSource("/lib.dart", "library lib;");
     // Complete all pending analysis tasks and flush the AST so that it won't
@@ -736,7 +736,7 @@
   }
 
   Future test_computeResolvedCompilationUnitAsync_cancel() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     Source source = _addSource("/lib.dart", "library lib;");
     // Complete all pending analysis tasks and flush the AST so that it won't
@@ -764,7 +764,7 @@
   }
 
   Future test_computeResolvedCompilationUnitAsync_dispose() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     Source source = _addSource("/lib.dart", "library lib;");
     // Complete all pending analysis tasks and flush the AST so that it won't
@@ -794,7 +794,7 @@
   }
 
   Future test_computeResolvedCompilationUnitAsync_unrelatedLibrary() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     Source librarySource = _addSource("/lib.dart", "library lib;");
     Source partSource = _addSource("/part.dart", "part of foo;");
@@ -871,12 +871,12 @@
   }
 
   void test_getDeclaredVariables() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     expect(_context.declaredVariables, isNotNull);
   }
 
   void test_getElement() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     LibraryElement core =
         _context.computeLibraryElement(_sourceFactory.forUri("dart:core"));
@@ -983,7 +983,7 @@
   }
 
   void test_getHtmlFilesReferencing_html() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     Source htmlSource = _addSource("/test.html", r'''
 <html><head>
@@ -1016,7 +1016,7 @@
   }
 
   void test_getHtmlFilesReferencing_part() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     Source htmlSource = _addSource("/test.html", r'''
 <html><head>
@@ -1070,7 +1070,7 @@
   }
 
   void test_getLaunchableClientLibrarySources() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     List<Source> sources = _context.launchableClientLibrarySources;
     expect(sources, hasLength(0));
@@ -1083,7 +1083,7 @@
   }
 
   void test_getLaunchableServerLibrarySources() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     List<Source> sources = _context.launchableServerLibrarySources;
     expect(sources, hasLength(0));
@@ -1094,7 +1094,7 @@
   }
 
   void test_getLibrariesContaining() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     Source librarySource = _addSource("/lib.dart", r'''
 library lib;
@@ -1110,7 +1110,7 @@
   }
 
   void test_getLibrariesDependingOn() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     Source libASource = _addSource("/libA.dart", "library libA;");
     _addSource("/libB.dart", "library libB;");
@@ -1129,7 +1129,7 @@
   }
 
   void test_getLibrariesReferencedFromHtml() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     Source htmlSource = _addSource("/test.html", r'''
 <html><head>
@@ -1145,7 +1145,7 @@
   }
 
   void test_getLibrariesReferencedFromHtml_no() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     Source htmlSource = _addSource("/test.html", r'''
 <html><head>
@@ -1158,7 +1158,7 @@
   }
 
   void test_getLibraryElement() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     Source source = _addSource("/test.dart", "library lib;");
     LibraryElement element = _context.getLibraryElement(source);
@@ -1212,7 +1212,7 @@
   }
 
   void test_getPublicNamespace_element() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     Source source = _addSource("/test.dart", "class A {}");
     LibraryElement library = _context.computeLibraryElement(source);
@@ -1223,7 +1223,7 @@
   }
 
   void test_getResolvedCompilationUnit_library() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     Source source = _addSource("/lib.dart", "library libb;");
     LibraryElement library = _context.computeLibraryElement(source);
@@ -1233,14 +1233,14 @@
   }
 
   void test_getResolvedCompilationUnit_library_null() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     Source source = _addSource("/lib.dart", "library lib;");
     expect(_context.getResolvedCompilationUnit(source, null), isNull);
   }
 
   void test_getResolvedCompilationUnit_source_dart() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     Source source = _addSource("/lib.dart", "library lib;");
     expect(_context.getResolvedCompilationUnit2(source, source), isNull);
@@ -1249,7 +1249,7 @@
   }
 
   void test_getResolvedCompilationUnit_source_html() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     Source source = _addSource("/test.html", "<html></html>");
     expect(_context.getResolvedCompilationUnit2(source, source), isNull);
@@ -1258,7 +1258,7 @@
   }
 
   void test_getResolvedHtmlUnit() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     Source source = _addSource("/test.html", "<html></html>");
     expect(_context.getResolvedHtmlUnit(source), isNull);
@@ -1301,7 +1301,7 @@
   }
 
   void test_isClientLibrary_dart() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     Source source = _addSource("/test.dart", r'''
 import 'dart:html';
@@ -1320,7 +1320,7 @@
   }
 
   void test_isServerLibrary_dart() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     Source source = _addSource("/test.dart", r'''
 library lib;
@@ -1751,7 +1751,7 @@
   }
 
   void test_resolveCompilationUnit_import_relative() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     Source sourceA =
         _addSource("/libA.dart", "library libA; import 'libB.dart'; class A{}");
     _addSource("/libB.dart", "library libB; class B{}");
@@ -1765,7 +1765,7 @@
   }
 
   void test_resolveCompilationUnit_import_relative_cyclic() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     Source sourceA =
         _addSource("/libA.dart", "library libA; import 'libB.dart'; class A{}");
     _addSource("/libB.dart", "library libB; import 'libA.dart'; class B{}");
@@ -1779,7 +1779,7 @@
   }
 
   void test_resolveCompilationUnit_library() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     Source source = _addSource("/lib.dart", "library lib;");
     LibraryElement library = _context.computeLibraryElement(source);
@@ -1790,7 +1790,7 @@
   }
 
   void test_resolveCompilationUnit_source() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     Source source = _addSource("/lib.dart", "library lib;");
     CompilationUnit compilationUnit =
@@ -1864,7 +1864,7 @@
   Future test_setChangedContents_libraryWithPart() {
     AnalysisOptionsImpl options = new AnalysisOptionsImpl();
     options.incremental = true;
-    _context = AnalysisContextFactory.contextWithCoreAndOptions(options);
+    _context = AnalysisContextFactory.oldContextWithCoreAndOptions(options);
     SourcesChangedListener listener = new SourcesChangedListener();
     _context.onSourcesChanged.listen(listener.onData);
     _sourceFactory = _context.sourceFactory;
@@ -1907,7 +1907,7 @@
   }
 
   void test_setChangedContents_notResolved() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     AnalysisOptionsImpl options =
         new AnalysisOptionsImpl.from(_context.analysisOptions);
     options.incremental = true;
@@ -1927,7 +1927,7 @@
   }
 
   Future test_setContents_libraryWithPart() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     SourcesChangedListener listener = new SourcesChangedListener();
     _context.onSourcesChanged.listen(listener.onData);
     _sourceFactory = _context.sourceFactory;
@@ -1964,7 +1964,7 @@
   }
 
   void test_setContents_null() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     Source librarySource = _addSource("/lib.dart", r'''
 library lib;
@@ -2005,7 +2005,7 @@
   }
 
   void test_unreadableSource() {
-    _context = AnalysisContextFactory.contextWithCore();
+    _context = AnalysisContextFactory.oldContextWithCore();
     _sourceFactory = _context.sourceFactory;
     Source test1 = _addSource("/test1.dart", r'''
 import 'test2.dart';
@@ -2306,8 +2306,7 @@
 @reflectiveTest
 class AnalysisTaskTest extends EngineTestCase {
   void test_perform_exception() {
-    InternalAnalysisContext context = new AnalysisContextImpl();
-    context.sourceFactory = new SourceFactory([new FileUriResolver()]);
+    InternalAnalysisContext context = AnalysisContextFactory.contextWithCore();
     AnalysisTask task = new AnalysisTask_test_perform_exception(context);
     task.perform(new TestTaskVisitor<Object>());
   }
@@ -3884,8 +3883,7 @@
 
   void test_perform_valid() {
     Source source = new TestSource('/test.dart', 'class A {}');
-    InternalAnalysisContext context = new AnalysisContextImpl();
-    context.sourceFactory = new SourceFactory([new FileUriResolver()]);
+    InternalAnalysisContext context = AnalysisContextFactory.contextWithCore();
     GetContentTask task = new GetContentTask(context, source);
     task.perform(new GetContentTaskTestTV_perform_valid(context, source));
   }
@@ -4577,8 +4575,7 @@
   void test_perform_exception() {
     TestSource source = new TestSource();
     source.generateExceptionOnRead = true;
-    InternalAnalysisContext context = new AnalysisContextImpl();
-    context.sourceFactory = new SourceFactory([new FileUriResolver()]);
+    InternalAnalysisContext context = AnalysisContextFactory.contextWithCore();
     ParseDartTask task = new ParseDartTask(context, source, null, null);
     task.perform(new ParseDartTaskTestTV_perform_exception());
   }
@@ -4591,8 +4588,7 @@
 part 'part.dart';
 class A {''';
     Source source = new TestSource('/test.dart', content);
-    InternalAnalysisContext context = new AnalysisContextImpl();
-    context.sourceFactory = new SourceFactory([new FileUriResolver()]);
+    InternalAnalysisContext context = AnalysisContextFactory.contextWithCore();
     ParseDartTask task = _createParseTask(context, source, content);
     task.perform(new ParseDartTaskTestTV_perform_library(context, source));
   }
@@ -4602,8 +4598,7 @@
 part of lib;
 class B {}''';
     Source source = new TestSource('/test.dart', content);
-    InternalAnalysisContext context = new AnalysisContextImpl();
-    context.sourceFactory = new SourceFactory([new FileUriResolver()]);
+    InternalAnalysisContext context = AnalysisContextFactory.contextWithCore();
     ParseDartTask task = _createParseTask(context, source, content);
     task.perform(new ParseDartTaskTestTV_perform_part(context, source));
   }
@@ -4617,8 +4612,7 @@
 part 'part.dart';
 class A {}''';
     Source source = new TestSource('/test.dart', content);
-    InternalAnalysisContext context = new AnalysisContextImpl();
-    context.sourceFactory = new SourceFactory([new FileUriResolver()]);
+    InternalAnalysisContext context = AnalysisContextFactory.contextWithCore();
     ParseDartTask task = _createParseTask(context, source, content);
     task.perform(
         new ParseDartTaskTestTV_perform_validateDirectives(context, source));
@@ -4636,7 +4630,7 @@
   void test_resolveDirective_exception() {
     GatheringErrorListener listener = new GatheringErrorListener();
     ImportDirective directive = AstFactory.importDirective3('dart:core', null);
-    AnalysisContext context = new AnalysisContextImpl();
+    AnalysisContext context = AnalysisContextFactory.contextWithCore();
     context.sourceFactory = new MockSourceFactory();
     Source source =
         ParseDartTask.resolveDirective(context, null, directive, listener);
@@ -4753,9 +4747,8 @@
 
   ParseHtmlTask parseSource(
       Source source, String contents, TestLogger testLogger) {
-    InternalAnalysisContext context = new AnalysisContextImpl();
+    InternalAnalysisContext context = AnalysisContextFactory.contextWithCore();
     context.setContents(source, contents);
-    context.sourceFactory = new SourceFactory([new FileUriResolver()]);
     ParseHtmlTask task = new ParseHtmlTask(context, source, contents);
     Logger oldLogger = AnalysisEngine.instance.logger;
     try {
@@ -4979,8 +4972,7 @@
   void test_perform_exception() {
     TestSource source = new TestSource();
     source.generateExceptionOnRead = true;
-    InternalAnalysisContext context = new AnalysisContextImpl();
-    context.sourceFactory = new SourceFactory([new FileUriResolver()]);
+    InternalAnalysisContext context = AnalysisContextFactory.contextWithCore();
     ResolveDartLibraryTask task =
         new ResolveDartLibraryTask(context, source, source);
     task.perform(new ResolveDartLibraryTaskTestTV_perform_exception());
@@ -5154,8 +5146,7 @@
 
   void test_perform_exception() {
     Source source = new TestSource();
-    InternalAnalysisContext context = new AnalysisContextImpl();
-    context.sourceFactory = new SourceFactory([new FileUriResolver()]);
+    InternalAnalysisContext context = AnalysisContextFactory.contextWithCore();
     ResolveHtmlTask task = new ResolveHtmlTask(context, source, 0, null);
     task.perform(new ResolveHtmlTaskTestTV_perform_exception());
   }
@@ -5249,8 +5240,7 @@
   void test_perform_valid() {
     String content = 'class A {}';
     Source source = new TestSource('test.dart', content);
-    InternalAnalysisContext context = new AnalysisContextImpl();
-    context.sourceFactory = new SourceFactory([new FileUriResolver()]);
+    InternalAnalysisContext context = AnalysisContextFactory.contextWithCore();
     ScanDartTask task = new ScanDartTask(context, source, content);
     task.perform(new ScanDartTaskTestTV_perform_valid(context, source));
   }
@@ -5490,7 +5480,6 @@
     fail("Unexpected invocation of getPrioritySources");
     return null;
   }
-
   @override
   List<AnalysisTarget> get priorityTargets {
     fail("Unexpected invocation of visitCacheItems");
@@ -5498,6 +5487,12 @@
   }
 
   @override
+  CachePartition get privateAnalysisCachePartition {
+    fail("Unexpected invocation of privateAnalysisCachePartition");
+    return null;
+  }
+
+  @override
   ResolverVisitorFactory get resolverVisitorFactory {
     fail("Unexpected invocation of getResolverVisitorFactory");
     return null;
diff --git a/pkg/analyzer/test/generated/incremental_resolver_test.dart b/pkg/analyzer/test/generated/incremental_resolver_test.dart
index 3af917b..735a882 100644
--- a/pkg/analyzer/test/generated/incremental_resolver_test.dart
+++ b/pkg/analyzer/test/generated/incremental_resolver_test.dart
@@ -2471,6 +2471,17 @@
   LibraryElement library;
   CompilationUnit unit;
 
+  @override
+  void reset() {
+    analysisContext2 = AnalysisContextFactory.oldContextWithCore();
+  }
+
+  @override
+  void resetWithOptions(AnalysisOptions options) {
+    analysisContext2 =
+        AnalysisContextFactory.oldContextWithCoreAndOptions(options);
+  }
+
   void setUp() {
     super.setUp();
     test_resolveApiChanges = true;
@@ -2802,8 +2813,9 @@
     int updateEndOld = updateOffset + edit.length;
     int updateOldNew = updateOffset + edit.replacement.length;
     IncrementalResolver resolver = new IncrementalResolver(
-        analysisContext2.getReadableSourceEntryOrNull(source), null, null,
-        unit.element, updateOffset, updateEndOld, updateOldNew);
+        (analysisContext2 as AnalysisContextImpl)
+            .getReadableSourceEntryOrNull(source), null, null, unit.element,
+        updateOffset, updateEndOld, updateOldNew);
     bool success = resolver.resolve(newNode);
     expect(success, isTrue);
     List<AnalysisError> newErrors = analysisContext.computeErrors(source);
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index 8307a9c..5929e06 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -6,6 +6,7 @@
 
 import 'dart:collection';
 
+import 'package:analyzer/src/context/context.dart' as newContext;
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/element.dart';
 import 'package:analyzer/src/generated/element_resolver.dart';
@@ -75,23 +76,28 @@
 
   /**
    * Create an analysis context that has a fake core library already resolved.
-   *
-   * @return the analysis context that was created
+   * Return the context that was created.
    */
-  static AnalysisContextImpl contextWithCore() {
+  static InternalAnalysisContext contextWithCore() {
+    if (AnalysisEngine.instance.useTaskModel) {
+      NewAnalysisContextForTests context = new NewAnalysisContextForTests();
+      return initContextWithCore(context);
+    }
     AnalysisContextForTests context = new AnalysisContextForTests();
     return initContextWithCore(context);
   }
 
   /**
-   * Create an analysis context that uses the given options and has a fake core library already
-   * resolved.
-   *
-   * @param options the options to be applied to the context
-   * @return the analysis context that was created
+   * Create an analysis context that uses the given [options] and has a fake
+   * core library already resolved. Return the context that was created.
    */
-  static AnalysisContextImpl contextWithCoreAndOptions(
+  static InternalAnalysisContext contextWithCoreAndOptions(
       AnalysisOptions options) {
+    if (AnalysisEngine.instance.useTaskModel) {
+      NewAnalysisContextForTests context = new NewAnalysisContextForTests();
+      context._internalSetAnalysisOptions(options);
+      return initContextWithCore(context);
+    }
     AnalysisContextForTests context = new AnalysisContextForTests();
     context._internalSetAnalysisOptions(options);
     return initContextWithCore(context);
@@ -103,7 +109,8 @@
    * @param context the context to be initialized (not `null`)
    * @return the analysis context that was created
    */
-  static AnalysisContextImpl initContextWithCore(AnalysisContextImpl context) {
+  static InternalAnalysisContext initContextWithCore(
+      InternalAnalysisContext context) {
     DirectoryBasedDartSdk sdk = new _AnalysisContextFactory_initContextWithCore(
         new JavaFile("/fake/sdk"));
     SourceFactory sourceFactory =
@@ -120,6 +127,7 @@
     coreContext.setContents(coreSource, "");
     coreUnit.librarySource = coreUnit.source = coreSource;
     ClassElementImpl proxyClassElement = ElementFactory.classElement2("_Proxy");
+    ClassElement objectClassElement = provider.objectType.element;
     coreUnit.types = <ClassElement>[
       provider.boolType.element,
       provider.deprecatedType.element,
@@ -132,7 +140,7 @@
       provider.mapType.element,
       provider.nullType.element,
       provider.numType.element,
-      provider.objectType.element,
+      objectClassElement,
       proxyClassElement,
       provider.stackTraceType.element,
       provider.stringType.element,
@@ -141,18 +149,19 @@
     ];
     coreUnit.functions = <FunctionElement>[
       ElementFactory.functionElement3("identical", provider.boolType.element,
-          <ClassElement>[
-        provider.objectType.element,
-        provider.objectType.element
-      ], null),
+          <ClassElement>[objectClassElement, objectClassElement], null),
       ElementFactory.functionElement3("print", VoidTypeImpl.instance.element,
-          <ClassElement>[provider.objectType.element], null)
+          <ClassElement>[objectClassElement], null)
     ];
     TopLevelVariableElement proxyTopLevelVariableElt = ElementFactory
         .topLevelVariableElement3("proxy", true, false, proxyClassElement.type);
-    TopLevelVariableElement deprecatedTopLevelVariableElt = ElementFactory
-        .topLevelVariableElement3(
+    ConstTopLevelVariableElementImpl deprecatedTopLevelVariableElt =
+        ElementFactory.topLevelVariableElement3(
             "deprecated", true, false, provider.deprecatedType);
+    deprecatedTopLevelVariableElt.constantInitializer = AstFactory
+        .instanceCreationExpression2(Keyword.CONST,
+            AstFactory.typeName(provider.deprecatedType.element),
+            [AstFactory.string2('next release')]);
     coreUnit.accessors = <PropertyAccessorElement>[
       proxyTopLevelVariableElt.getter,
       deprecatedTopLevelVariableElt.getter
@@ -346,6 +355,26 @@
     context.recordLibraryElements(elementMap);
     return context;
   }
+
+  /**
+   * Create an analysis context that has a fake core library already resolved.
+   * Return the context that was created.
+   */
+  static AnalysisContextImpl oldContextWithCore() {
+    AnalysisContextForTests context = new AnalysisContextForTests();
+    return initContextWithCore(context);
+  }
+
+  /**
+   * Create an analysis context that uses the given [options] and has a fake
+   * core library already resolved. Return the context that was created.
+   */
+  static AnalysisContextImpl oldContextWithCoreAndOptions(
+      AnalysisOptions options) {
+    AnalysisContextForTests context = new AnalysisContextForTests();
+    context._internalSetAnalysisOptions(options);
+    return initContextWithCore(context);
+  }
 }
 
 /**
@@ -412,14 +441,14 @@
   AnalysisContext context;
 
   /**
-   * Creates new [AnalysisContext] using [AnalysisContextFactory.contextWithCore].
+   * Creates new [AnalysisContext] using [AnalysisContextFactory].
    */
-  AnalysisContextHelper() {
-    context = AnalysisContextFactory.contextWithCore();
-    AnalysisOptionsImpl options =
-        new AnalysisOptionsImpl.from(context.analysisOptions);
+  AnalysisContextHelper([AnalysisOptionsImpl options]) {
+    if (options == null) {
+      options = new AnalysisOptionsImpl();
+    }
     options.cacheSize = 256;
-    context.analysisOptions = options;
+    context = AnalysisContextFactory.contextWithCoreAndOptions(options);
   }
 
   Source addSource(String path, String code) {
@@ -1888,10 +1917,7 @@
    * @return the resolver that was created
    */
   ElementResolver _createResolver() {
-    AnalysisContextImpl context = new AnalysisContextImpl();
-    SourceFactory sourceFactory = new SourceFactory(
-        [new DartUriResolver(DirectoryBasedDartSdk.defaultSdk)]);
-    context.sourceFactory = sourceFactory;
+    InternalAnalysisContext context = AnalysisContextFactory.contextWithCore();
     FileBasedSource source =
         new FileBasedSource(FileUtilities2.createFile("/test.dart"));
     CompilationUnitElementImpl definingCompilationUnit =
@@ -5709,7 +5735,7 @@
    * @return the inheritance manager that was created
    */
   InheritanceManager _createInheritanceManager() {
-    AnalysisContextImpl context = AnalysisContextFactory.contextWithCore();
+    AnalysisContext context = AnalysisContextFactory.contextWithCore();
     FileBasedSource source =
         new FileBasedSource(FileUtilities2.createFile("/test.dart"));
     CompilationUnitElementImpl definingCompilationUnit =
@@ -5727,7 +5753,7 @@
   /**
    * The analysis context used to analyze sources.
    */
-  AnalysisContextImpl _context;
+  InternalAnalysisContext _context;
 
   /**
    * Add a source file to the content provider. The file path should be absolute.
@@ -5744,12 +5770,7 @@
 
   @override
   void setUp() {
-    SourceFactory sourceFactory = new SourceFactory([
-      new DartUriResolver(DirectoryBasedDartSdk.defaultSdk),
-      new FileUriResolver()
-    ]);
-    _context = new AnalysisContextImpl();
-    _context.sourceFactory = sourceFactory;
+    _context = AnalysisContextFactory.contextWithCore();
   }
 
   @override
@@ -5909,8 +5930,7 @@
 @reflectiveTest
 class LibraryImportScopeTest extends ResolverTestCase {
   void test_conflictingImports() {
-    AnalysisContext context = new AnalysisContextImpl();
-    context.sourceFactory = new SourceFactory([]);
+    AnalysisContext context = AnalysisContextFactory.contextWithCore();
     String typeNameA = "A";
     String typeNameB = "B";
     String typeNameC = "C";
@@ -5976,8 +5996,7 @@
   }
 
   void test_creation_nonEmpty() {
-    AnalysisContext context = new AnalysisContextImpl();
-    context.sourceFactory = new SourceFactory([]);
+    AnalysisContext context = AnalysisContextFactory.contextWithCore();
     String importedTypeName = "A";
     ClassElement importedType =
         new ClassElementImpl.forNode(AstFactory.identifier3(importedTypeName));
@@ -6028,8 +6047,7 @@
   }
 
   void test_nonConflictingImports_sameElement() {
-    AnalysisContext context = new AnalysisContextImpl();
-    context.sourceFactory = new SourceFactory([]);
+    AnalysisContext context = AnalysisContextFactory.contextWithCore();
     String typeNameA = "A";
     String typeNameB = "B";
     ClassElement typeA = ElementFactory.classElement2(typeNameA);
@@ -6053,8 +6071,7 @@
   }
 
   void test_prefixedAndNonPrefixed() {
-    AnalysisContext context = new AnalysisContextImpl();
-    context.sourceFactory = new SourceFactory([]);
+    AnalysisContext context = AnalysisContextFactory.contextWithCore();
     String typeName = "C";
     String prefixName = "p";
     ClassElement prefixedType = ElementFactory.classElement2(typeName);
@@ -6195,8 +6212,7 @@
   }
 
   void test_creation_nonEmpty() {
-    AnalysisContext context = new AnalysisContextImpl();
-    context.sourceFactory = new SourceFactory([]);
+    AnalysisContext context = AnalysisContextFactory.contextWithCore();
     String importedTypeName = "A";
     ClassElement importedType =
         new ClassElementImpl.forNode(AstFactory.identifier3(importedTypeName));
@@ -6231,14 +6247,9 @@
   GatheringErrorListener _errorListener;
 
   /**
-   * The source factory used to create libraries.
-   */
-  SourceFactory _sourceFactory;
-
-  /**
    * The analysis context to pass in to all libraries created by the tests.
    */
-  AnalysisContextImpl _analysisContext;
+  InternalAnalysisContext _analysisContext;
 
   /**
    * The library used by the tests.
@@ -6247,9 +6258,7 @@
 
   @override
   void setUp() {
-    _sourceFactory = new SourceFactory([new FileUriResolver()]);
-    _analysisContext = new AnalysisContextImpl();
-    _analysisContext.sourceFactory = _sourceFactory;
+    _analysisContext = AnalysisContextFactory.contextWithCore();
     _errorListener = new GatheringErrorListener();
     _library = _createLibrary("/lib.dart");
   }
@@ -6257,7 +6266,6 @@
   @override
   void tearDown() {
     _errorListener = null;
-    _sourceFactory = null;
     _analysisContext = null;
     _library = null;
     super.tearDown();
@@ -6381,6 +6389,63 @@
   }
 }
 
+/**
+ * An analysis context that has a fake SDK that is much smaller and faster for
+ * testing purposes.
+ */
+class NewAnalysisContextForTests extends newContext.AnalysisContextImpl {
+  @override
+  void set analysisOptions(AnalysisOptions options) {
+    AnalysisOptions currentOptions = analysisOptions;
+    bool needsRecompute = currentOptions.analyzeFunctionBodiesPredicate !=
+            options.analyzeFunctionBodiesPredicate ||
+        currentOptions.generateImplicitErrors !=
+            options.generateImplicitErrors ||
+        currentOptions.generateSdkErrors != options.generateSdkErrors ||
+        currentOptions.dart2jsHint != options.dart2jsHint ||
+        (currentOptions.hint && !options.hint) ||
+        currentOptions.preserveComments != options.preserveComments ||
+        currentOptions.enableNullAwareOperators !=
+            options.enableNullAwareOperators ||
+        currentOptions.enableStrictCallChecks != options.enableStrictCallChecks;
+    if (needsRecompute) {
+      fail(
+          "Cannot set options that cause the sources to be reanalyzed in a test context");
+    }
+    super.analysisOptions = options;
+  }
+
+  @override
+  bool exists(Source source) =>
+      super.exists(source) || sourceFactory.dartSdk.context.exists(source);
+
+  @override
+  TimestampedData<String> getContents(Source source) {
+    if (source.isInSystemLibrary) {
+      return sourceFactory.dartSdk.context.getContents(source);
+    }
+    return super.getContents(source);
+  }
+
+  @override
+  int getModificationStamp(Source source) {
+    if (source.isInSystemLibrary) {
+      return sourceFactory.dartSdk.context.getModificationStamp(source);
+    }
+    return super.getModificationStamp(source);
+  }
+
+  /**
+   * Set the analysis options, even if they would force re-analysis. This method should only be
+   * invoked before the fake SDK is initialized.
+   *
+   * @param options the analysis options to be set
+   */
+  void _internalSetAnalysisOptions(AnalysisOptions options) {
+    super.analysisOptions = options;
+  }
+}
+
 @reflectiveTest
 class NonHintCodeTest extends ResolverTestCase {
   void test_deadCode_deadBlock_conditionalElse_debugConst() {
@@ -7661,7 +7726,7 @@
   /**
    * The analysis context used to parse the compilation units being resolved.
    */
-  AnalysisContextImpl analysisContext2;
+  InternalAnalysisContext analysisContext2;
 
   /**
    * Specifies if [assertErrors] should check for [HintCode.UNUSED_ELEMENT] and
@@ -7771,7 +7836,7 @@
    * @return the library element that was created
    */
   LibraryElementImpl createDefaultTestLibrary() =>
-      createTestLibrary(new AnalysisContextImpl(), "test");
+      createTestLibrary(AnalysisContextFactory.contextWithCore(), "test");
 
   /**
    * Create a library element that represents a library with the given name containing a single
@@ -7935,27 +8000,25 @@
   }
 
   /**
-   * Verify that all of the identifiers in the compilation units associated with the given sources
-   * have been resolved.
-   *
-   * @param resolvedElementMap a table mapping the AST nodes that have been resolved to the element
-   *          to which they were resolved
-   * @param sources the sources identifying the compilation units to be verified
-   * @throws Exception if the contents of the compilation unit cannot be accessed
+   * Verify that all of the identifiers in the compilation units associated with
+   * the given [sources] have been resolved.
    */
   void verify(List<Source> sources) {
     ResolutionVerifier verifier = new ResolutionVerifier();
     for (Source source in sources) {
-      analysisContext2.parseCompilationUnit(source).accept(verifier);
+      List<Source> libraries = analysisContext2.getLibrariesContaining(source);
+      for (Source library in libraries) {
+        analysisContext2
+            .resolveCompilationUnit2(source, library)
+            .accept(verifier);
+      }
     }
     verifier.assertResolved();
   }
 
   /**
-   * Create a source object representing a file with the given name and give it an empty content.
-   *
-   * @param fileName the name of the file for which a source is to be created
-   * @return the source that was created
+   * Create a source object representing a file with the given [fileName] and
+   * give it an empty content. Return the source that was created.
    */
   FileBasedSource _createNamedSource(String fileName) {
     FileBasedSource source =
@@ -10994,10 +11057,7 @@
    * @return the analyzer to be used by the tests
    */
   StaticTypeAnalyzer _createAnalyzer() {
-    AnalysisContextImpl context = new AnalysisContextImpl();
-    SourceFactory sourceFactory = new SourceFactory(
-        [new DartUriResolver(DirectoryBasedDartSdk.defaultSdk)]);
-    context.sourceFactory = sourceFactory;
+    InternalAnalysisContext context = AnalysisContextFactory.contextWithCore();
     FileBasedSource source =
         new FileBasedSource(FileUtilities2.createFile("/lib.dart"));
     CompilationUnitElementImpl definingCompilationUnit =
@@ -11502,7 +11562,7 @@
   @override
   void setUp() {
     super.setUp();
-    AnalysisContextImpl context = AnalysisContextFactory.contextWithCore();
+    AnalysisContext context = AnalysisContextFactory.contextWithCore();
     FileBasedSource source =
         new FileBasedSource(FileUtilities2.createFile("/test.dart"));
     _definingCompilationUnit = new CompilationUnitElementImpl("test.dart");
@@ -13210,7 +13270,7 @@
     CompilationUnitElementImpl asyncUnit =
         new CompilationUnitElementImpl("async.dart");
     asyncUnit.types = <ClassElement>[futureType.element, streamType.element];
-    AnalysisContextImpl context = new AnalysisContextImpl();
+    AnalysisContext context = AnalysisEngine.instance.createAnalysisContext();
     LibraryElementImpl coreLibrary = new LibraryElementImpl.forNode(
         context, AstFactory.libraryIdentifier2(["dart.core"]));
     coreLibrary.definingCompilationUnit = coreUnit;
@@ -13333,9 +13393,7 @@
   @override
   void setUp() {
     _listener = new GatheringErrorListener();
-    SourceFactory factory = new SourceFactory([new FileUriResolver()]);
-    AnalysisContextImpl context = new AnalysisContextImpl();
-    context.sourceFactory = factory;
+    InternalAnalysisContext context = AnalysisContextFactory.contextWithCore();
     Source librarySource =
         new FileBasedSource(FileUtilities2.createFile("/lib.dart"));
     _library = new Library(context, _listener, librarySource);
diff --git a/pkg/analyzer/test/generated/test_support.dart b/pkg/analyzer/test/generated/test_support.dart
index 7d83198..2552ea7 100644
--- a/pkg/analyzer/test/generated/test_support.dart
+++ b/pkg/analyzer/test/generated/test_support.dart
@@ -18,6 +18,8 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:unittest/unittest.dart';
 
+import 'resolver_test.dart';
+
 /**
  * The class `EngineTestCase` defines utility methods for making assertions.
  */
@@ -54,10 +56,8 @@
     expect(elements, hasLength(names.length));
   }
 
-  AnalysisContextImpl createAnalysisContext() {
-    AnalysisContextImpl context = new AnalysisContextImpl();
-    context.sourceFactory = new SourceFactory([]);
-    return context;
+  AnalysisContext createAnalysisContext() {
+    return AnalysisContextFactory.contextWithCore();
   }
 
   /**
@@ -594,8 +594,6 @@
   UriKind get uriKind {
     throw new UnsupportedOperationException();
   }
-  @override
-  String toString() => '$_name';
   bool operator ==(Object other) {
     if (other is TestSource) {
       return other._name == _name;
@@ -616,6 +614,8 @@
     modificationStamp = new DateTime.now().millisecondsSinceEpoch;
     _contents = value;
   }
+  @override
+  String toString() => '$_name';
 }
 
 class TestSourceWithUri extends TestSource {
diff --git a/pkg/analyzer/test/src/context/context_test.dart b/pkg/analyzer/test/src/context/context_test.dart
index 71040ca..ddca982 100644
--- a/pkg/analyzer/test/src/context/context_test.dart
+++ b/pkg/analyzer/test/src/context/context_test.dart
@@ -473,6 +473,8 @@
 part 'part.dart';''');
     // run all tasks without part
     _analyzeAll_assertFinished();
+    expect(_hasAnalysisErrorWithErrorSeverity(context.getErrors(libSource)),
+        isTrue, reason: "lib has errors");
     // add part and run all tasks
     Source partSource = addSource("/part.dart", r'''
 part of lib;
@@ -481,6 +483,11 @@
     // "libSource" should be here
     List<Source> librariesWithPart = context.getLibrariesContaining(partSource);
     expect(librariesWithPart, unorderedEquals([libSource]));
+    expect(_hasAnalysisErrorWithErrorSeverity(context.getErrors(libSource)),
+        isFalse, reason: "lib doesn't have errors");
+    expect(
+        context.getResolvedCompilationUnit2(partSource, libSource), isNotNull,
+        reason: "part resolved");
   }
 
   void test_performAnalysisTask_changeLibraryContents() {
@@ -554,10 +561,7 @@
         reason: "part resolved 3");
   }
 
-  void fail_performAnalysisTask_changePartContents_makeItAPart() {
-    // TODO(paulberry): fix this.  It appears to be broken because of broken
-    // dependency handling with part files (see TODO comment in
-    // ContainingLibrariesTask.internalPeform)
+  void test_performAnalysisTask_changePartContents_makeItAPart() {
     Source libSource = addSource("/lib.dart", r'''
 library lib;
 part 'part.dart';
@@ -567,7 +571,7 @@
     expect(context.getResolvedCompilationUnit2(libSource, libSource), isNotNull,
         reason: "library resolved 1");
     expect(
-        context.getResolvedCompilationUnit2(partSource, libSource), isNotNull,
+        context.getResolvedCompilationUnit2(partSource, partSource), isNotNull,
         reason: "part resolved 1");
     // update and analyze
     context.setContents(partSource, r'''
@@ -575,7 +579,7 @@
 void g() { f(null); }''');
     expect(context.getResolvedCompilationUnit2(libSource, libSource), isNull,
         reason: "library changed 2");
-    expect(context.getResolvedCompilationUnit2(partSource, libSource), isNull,
+    expect(context.getResolvedCompilationUnit2(partSource, partSource), isNull,
         reason: "part changed 2");
     _analyzeAll_assertFinished();
     expect(context.getResolvedCompilationUnit2(libSource, libSource), isNotNull,
diff --git a/pkg/analyzer/test/src/task/dart_test.dart b/pkg/analyzer/test/src/task/dart_test.dart
index d5abbbf..4036ee2 100644
--- a/pkg/analyzer/test/src/task/dart_test.dart
+++ b/pkg/analyzer/test/src/task/dart_test.dart
@@ -899,6 +899,17 @@
     expect(error.getProperty(ErrorProperty.PARTS_LIBRARY_NAME), isNull);
   }
 
+  test_perform_error_partDoesNotExist() {
+    _performBuildTask({
+      '/lib.dart': '''
+library lib;
+part 'part.dart';
+'''
+    });
+    // we already report URI_DOES_NOT_EXIST, no need to report other errors
+    _assertErrorsWithCodes([]);
+  }
+
   test_perform_error_partOfDifferentLibrary() {
     _performBuildTask({
       '/lib.dart': '''
@@ -925,6 +936,16 @@
     _assertErrorsWithCodes([CompileTimeErrorCode.PART_OF_NON_PART]);
   }
 
+  test_perform_invalidUri_part() {
+    _performBuildTask({
+      '/lib.dart': '''
+library lib;
+part '//////////';
+'''
+    });
+    expect(libraryElement.parts, isEmpty);
+  }
+
   test_perform_isLaunchable_inDefiningUnit() {
     _performBuildTask({
       '/lib.dart': '''
@@ -961,7 +982,11 @@
 '''
     });
     expect(libraryElement.parts, hasLength(1));
-    expect(libraryElement.parts[0].library, same(libraryElement));
+    CompilationUnitElement part = libraryElement.parts[0];
+    expect(part, isNotNull);
+    expect(part.source, isNotNull);
+    expect(part.library, same(libraryElement));
+    expect(context.exists(part.source), isFalse);
   }
 
   test_perform_patchTopLevelAccessors() {
@@ -1161,6 +1186,40 @@
     }
   }
 
+  test_perform_importExportClosure() {
+    Source sourceA = newSource('/a.dart', '''
+library lib_a;
+''');
+    Source sourceB = newSource('/b.dart', '''
+library lib_b;
+export 'a.dart';
+''');
+    Source sourceC = newSource('/c.dart', '''
+library lib_c;
+import 'b.dart';
+''');
+    Source coreSource = context.sourceFactory.resolveUri(null, 'dart:core');
+    // c.dart
+    {
+      _computeResult(sourceC, IMPORT_EXPORT_SOURCE_CLOSURE);
+      expect(task, new isInstanceOf<BuildSourceClosuresTask>());
+      List<Source> closure = outputs[IMPORT_EXPORT_SOURCE_CLOSURE];
+      expect(closure, contains(sourceA));
+      expect(closure, contains(sourceB));
+      expect(closure, contains(sourceC));
+      expect(closure, contains(coreSource));
+    }
+    // b.dart
+    {
+      _computeResult(sourceB, IMPORT_EXPORT_SOURCE_CLOSURE);
+      expect(task, new isInstanceOf<BuildSourceClosuresTask>());
+      List<Source> closure = outputs[IMPORT_EXPORT_SOURCE_CLOSURE];
+      expect(closure, contains(sourceA));
+      expect(closure, contains(sourceB));
+      expect(closure, contains(coreSource));
+    }
+  }
+
   test_perform_isClient_false() {
     Source sourceA = newSource('/a.dart', '''
 library lib_a;
@@ -1289,6 +1348,25 @@
     expect(outputs[CONSTANT_DEPENDENCIES], [x]);
   }
 
+  test_enumConstant() {
+    Source source = newSource('/test.dart', '''
+enum E {A, B, C}
+''');
+    // First compute the resolved unit for the source.
+    LibrarySpecificUnit librarySpecificUnit =
+        new LibrarySpecificUnit(source, source);
+    _computeResult(librarySpecificUnit, RESOLVED_UNIT2);
+    CompilationUnit unit = outputs[RESOLVED_UNIT2];
+    // Find the element for 'A'
+    EnumDeclaration enumDeclaration = unit.declarations[0];
+    EnumConstantDeclaration constantDeclaration = enumDeclaration.constants[0];
+    FieldElement constantElement = constantDeclaration.element;
+    // Now compute the dependencies for the constant and check that there are
+    // none.
+    _computeResult(constantElement, CONSTANT_DEPENDENCIES);
+    expect(outputs[CONSTANT_DEPENDENCIES], isEmpty);
+  }
+
   test_perform() {
     Source source = newSource('/test.dart', '''
 const x = y;
@@ -2054,6 +2132,7 @@
     expect(inputs, isNotNull);
     expect(inputs.keys, unorderedEquals([
       ParseDartTask.LINE_INFO_INPUT_NAME,
+      ParseDartTask.MODIFICATION_TIME_INPUT_NAME,
       ParseDartTask.TOKEN_STREAM_INPUT_NAME
     ]));
   }
@@ -2097,6 +2176,35 @@
     expect(outputs[UNITS], hasLength(1));
   }
 
+  test_perform_computeSourceKind_noDirectives_hasContainingLibrary() {
+    // Parse "lib.dart" to let the context know that "test.dart" is included.
+    _computeResult(newSource('/lib.dart', r'''
+library lib;
+part 'test.dart';
+'''), PARSED_UNIT);
+    // If there are no the "part of" directive, then it is not a part.
+    _performParseTask('');
+    expect(outputs[SOURCE_KIND], SourceKind.LIBRARY);
+  }
+
+  test_perform_computeSourceKind_noDirectives_noContainingLibrary() {
+    _performParseTask('');
+    expect(outputs[SOURCE_KIND], SourceKind.LIBRARY);
+  }
+
+  test_perform_doesNotExist() {
+    _performParseTask(null);
+    expect(outputs, hasLength(8));
+    expect(outputs[EXPLICITLY_IMPORTED_LIBRARIES], hasLength(0));
+    expect(outputs[EXPORTED_LIBRARIES], hasLength(0));
+    _assertHasCore(outputs[IMPORTED_LIBRARIES], 1);
+    expect(outputs[INCLUDED_PARTS], hasLength(0));
+    expect(outputs[PARSE_ERRORS], hasLength(0));
+    expect(outputs[PARSED_UNIT], isNotNull);
+    expect(outputs[SOURCE_KIND], SourceKind.UNKNOWN);
+    expect(outputs[UNITS], hasLength(1));
+  }
+
   test_perform_invalidDirectives() {
     _performParseTask(r'''
 library lib;
@@ -2134,6 +2242,21 @@
     expect(outputs[UNITS], hasLength(2));
   }
 
+  test_perform_part() {
+    _performParseTask(r'''
+part of lib;
+class B {}''');
+    expect(outputs, hasLength(8));
+    expect(outputs[EXPLICITLY_IMPORTED_LIBRARIES], hasLength(0));
+    expect(outputs[EXPORTED_LIBRARIES], hasLength(0));
+    _assertHasCore(outputs[IMPORTED_LIBRARIES], 1);
+    expect(outputs[INCLUDED_PARTS], hasLength(0));
+    expect(outputs[PARSE_ERRORS], hasLength(0));
+    expect(outputs[PARSED_UNIT], isNotNull);
+    expect(outputs[SOURCE_KIND], SourceKind.PART);
+    expect(outputs[UNITS], hasLength(1));
+  }
+
   void _performParseTask(String content) {
     AnalysisTarget target = newSource('/test.dart', content);
     _computeResult(target, PARSED_UNIT);
@@ -2257,6 +2380,42 @@
     errorListener.assertErrorsWithCodes(
         <ErrorCode>[StaticTypeWarningCode.UNDEFINED_METHOD]);
   }
+
+  test_perform_importExport() {
+    newSource('/a.dart', '''
+library a;
+class A<T> {
+  T m() {}
+}
+''');
+    newSource('/b.dart', '''
+library b;
+export 'a.dart';
+''');
+    Source sourceC = newSource('/c.dart', '''
+library c;
+import 'b.dart';
+main() {
+  new A<int>().m();
+}
+''');
+    _computeResult(new LibrarySpecificUnit(sourceC, sourceC), RESOLVED_UNIT6);
+    expect(task, new isInstanceOf<ResolveReferencesTask>());
+    // validate
+    CompilationUnit unit = outputs[RESOLVED_UNIT6];
+    expect(unit, isNotNull);
+    {
+      FunctionDeclaration functionDeclaration = unit.declarations[0];
+      BlockFunctionBody body = functionDeclaration.functionExpression.body;
+      List<Statement> statements = body.block.statements;
+      ExpressionStatement statement = statements[0];
+      MethodInvocation invocation = statement.expression;
+      MethodElement methodElement = invocation.methodName.staticElement;
+      expect(methodElement, isNotNull);
+      expect(methodElement.type, isNotNull);
+      expect(methodElement.returnType.toString(), 'int');
+    }
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/test/src/task/dart_work_manager_test.dart b/pkg/analyzer/test/src/task/dart_work_manager_test.dart
index c5dc211..2281be8 100644
--- a/pkg/analyzer/test/src/task/dart_work_manager_test.dart
+++ b/pkg/analyzer/test/src/task/dart_work_manager_test.dart
@@ -37,6 +37,7 @@
 @reflectiveTest
 class DartWorkManagerTest {
   InternalAnalysisContext context = new _InternalAnalysisContextMock();
+  AnalysisCache cache;
   DartWorkManager manager;
 
   CaughtException caughtException = new CaughtException(null, null);
@@ -59,6 +60,7 @@
   }
 
   void setUp() {
+    cache = context.analysisCache;
     manager = new DartWorkManager(context);
     entry1 = context.getCacheEntry(source1);
     entry2 = context.getCacheEntry(source2);
@@ -143,6 +145,8 @@
     manager.partLibrariesMap[part3] = [library1];
     manager.libraryPartsMap[library1] = [part1, part3];
     manager.libraryPartsMap[library2] = [part1, part2];
+    _getOrCreateEntry(part1).setValue(CONTAINING_LIBRARIES, [], []);
+    expect(cache.getState(part1, CONTAINING_LIBRARIES), CacheState.VALID);
     // change library1
     manager.applyChange([], [library1], []);
     expect(manager.partLibrariesMap[part1], unorderedEquals([library2]));
@@ -150,6 +154,7 @@
     expect(manager.partLibrariesMap[part3], unorderedEquals([]));
     expect(manager.libraryPartsMap[library1], isNull);
     expect(manager.libraryPartsMap[library2], [part1, part2]);
+    expect(cache.getState(part1, CONTAINING_LIBRARIES), CacheState.INVALID);
   }
 
   void test_applyChange_updatePartsLibraries_changePart() {
@@ -163,12 +168,15 @@
     manager.partLibrariesMap[part3] = [library1];
     manager.libraryPartsMap[library1] = [part1, part3];
     manager.libraryPartsMap[library2] = [part1, part2];
+    _getOrCreateEntry(part1).setValue(CONTAINING_LIBRARIES, [], []);
+    expect(cache.getState(part1, CONTAINING_LIBRARIES), CacheState.VALID);
     // change part1
     manager.applyChange([], [part1], []);
     expect(manager.partLibrariesMap[part2], unorderedEquals([library2]));
     expect(manager.partLibrariesMap[part3], unorderedEquals([library1]));
     expect(manager.libraryPartsMap[library1], [part1, part3]);
     expect(manager.libraryPartsMap[library2], [part1, part2]);
+    expect(cache.getState(part1, CONTAINING_LIBRARIES), CacheState.INVALID);
   }
 
   void test_applyChange_updatePartsLibraries_removeLibrary() {
@@ -403,6 +411,58 @@
     expect(manager.getNextResultPriority(), WorkOrderPriority.NONE);
   }
 
+  void test_onAnalysisOptionsChanged() {
+    when(context.exists(anyObject)).thenReturn(true);
+    // set cache values
+    entry1.setValue(PARSED_UNIT, AstFactory.compilationUnit(), []);
+    entry1.setValue(IMPORTED_LIBRARIES, <Source>[], []);
+    entry1.setValue(EXPLICITLY_IMPORTED_LIBRARIES, <Source>[], []);
+    entry1.setValue(EXPORTED_LIBRARIES, <Source>[], []);
+    entry1.setValue(INCLUDED_PARTS, <Source>[], []);
+    // configure LibrarySpecificUnit
+    LibrarySpecificUnit unitTarget = new LibrarySpecificUnit(source2, source3);
+    CacheEntry unitEntry = new CacheEntry(unitTarget);
+    cache.put(unitEntry);
+    unitEntry.setValue(BUILD_LIBRARY_ERRORS, <AnalysisError>[], []);
+    expect(unitEntry.getState(BUILD_LIBRARY_ERRORS), CacheState.VALID);
+    // notify
+    manager.onAnalysisOptionsChanged();
+    // resolution is invalidated
+    expect(unitEntry.getState(BUILD_LIBRARY_ERRORS), CacheState.INVALID);
+    // ...but URIs are still value
+    expect(entry1.getState(PARSED_UNIT), CacheState.VALID);
+    expect(entry1.getState(IMPORTED_LIBRARIES), CacheState.VALID);
+    expect(entry1.getState(EXPLICITLY_IMPORTED_LIBRARIES), CacheState.VALID);
+    expect(entry1.getState(EXPORTED_LIBRARIES), CacheState.VALID);
+    expect(entry1.getState(INCLUDED_PARTS), CacheState.VALID);
+  }
+
+  void test_onSourceFactoryChanged() {
+    when(context.exists(anyObject)).thenReturn(true);
+    // set cache values
+    entry1.setValue(PARSED_UNIT, AstFactory.compilationUnit(), []);
+    entry1.setValue(IMPORTED_LIBRARIES, <Source>[], []);
+    entry1.setValue(EXPLICITLY_IMPORTED_LIBRARIES, <Source>[], []);
+    entry1.setValue(EXPORTED_LIBRARIES, <Source>[], []);
+    entry1.setValue(INCLUDED_PARTS, <Source>[], []);
+    // configure LibrarySpecificUnit
+    LibrarySpecificUnit unitTarget = new LibrarySpecificUnit(source2, source3);
+    CacheEntry unitEntry = new CacheEntry(unitTarget);
+    cache.put(unitEntry);
+    unitEntry.setValue(BUILD_LIBRARY_ERRORS, <AnalysisError>[], []);
+    expect(unitEntry.getState(BUILD_LIBRARY_ERRORS), CacheState.VALID);
+    // notify
+    manager.onSourceFactoryChanged();
+    // resolution is invalidated
+    expect(unitEntry.getState(BUILD_LIBRARY_ERRORS), CacheState.INVALID);
+    // ...and URIs resolution too
+    expect(entry1.getState(PARSED_UNIT), CacheState.INVALID);
+    expect(entry1.getState(IMPORTED_LIBRARIES), CacheState.INVALID);
+    expect(entry1.getState(EXPLICITLY_IMPORTED_LIBRARIES), CacheState.INVALID);
+    expect(entry1.getState(EXPORTED_LIBRARIES), CacheState.INVALID);
+    expect(entry1.getState(INCLUDED_PARTS), CacheState.INVALID);
+  }
+
   void test_resultsComputed_errors_forLibrarySpecificUnit() {
     AnalysisError error1 =
         new AnalysisError(source1, 1, 0, ScannerErrorCode.MISSING_DIGIT);
@@ -443,12 +503,14 @@
     expect(notice.lineInfo, lineInfo);
   }
 
-  void test_resultsComputed_includedParts() {
+  void test_resultsComputed_includedParts_updatePartLibraries() {
     Source part1 = new TestSource('part1.dart');
     Source part2 = new TestSource('part2.dart');
     Source part3 = new TestSource('part3.dart');
     Source library1 = new TestSource('library1.dart');
     Source library2 = new TestSource('library2.dart');
+    _getOrCreateEntry(part1).setValue(CONTAINING_LIBRARIES, [], []);
+    expect(cache.getState(part1, CONTAINING_LIBRARIES), CacheState.VALID);
     // library1 parts
     manager.resultsComputed(library1, {INCLUDED_PARTS: [part1, part2]});
     expect(manager.partLibrariesMap[part1], [library1]);
@@ -463,6 +525,8 @@
     expect(manager.partLibrariesMap[part3], [library2]);
     expect(manager.libraryPartsMap[library1], [part1, part2]);
     expect(manager.libraryPartsMap[library2], [part2, part3]);
+    // part1 CONTAINING_LIBRARIES
+    expect(cache.getState(part1, CONTAINING_LIBRARIES), CacheState.INVALID);
   }
 
   void test_resultsComputed_noSourceKind() {
@@ -518,17 +582,30 @@
     expect_librarySourceQueue([]);
     expect_unknownSourceQueue([source1, source3]);
   }
+
+  CacheEntry _getOrCreateEntry(Source source) {
+    CacheEntry entry = cache.get(source);
+    if (entry == null) {
+      entry = new CacheEntry(source);
+      cache.put(entry);
+    }
+    return entry;
+  }
 }
 
 class _InternalAnalysisContextMock extends TypedMock
     implements InternalAnalysisContext {
   @override
+  CachePartition privateAnalysisCachePartition;
+
+  @override
   AnalysisCache analysisCache;
 
   Map<Source, ChangeNoticeImpl> _pendingNotices = <Source, ChangeNoticeImpl>{};
 
   _InternalAnalysisContextMock() {
-    analysisCache = new AnalysisCache([new UniversalCachePartition(this)]);
+    privateAnalysisCachePartition = new UniversalCachePartition(this);
+    analysisCache = new AnalysisCache([privateAnalysisCachePartition]);
   }
 
   @override
diff --git a/pkg/analyzer/test/src/task/incremental_element_builder_test.dart b/pkg/analyzer/test/src/task/incremental_element_builder_test.dart
index dd05bcb..415e031 100644
--- a/pkg/analyzer/test/src/task/incremental_element_builder_test.dart
+++ b/pkg/analyzer/test/src/task/incremental_element_builder_test.dart
@@ -21,6 +21,7 @@
 @reflectiveTest
 class IncrementalCompilationUnitElementBuilderTest extends AbstractContextTest {
   Source source;
+
   String oldCode;
   CompilationUnit oldUnit;
   CompilationUnitElement unitElement;
@@ -28,6 +29,8 @@
   String newCode;
   CompilationUnit newUnit;
 
+  CompilationUnitElementDelta unitDelta;
+
   String getNodeText(AstNode node) {
     return newCode.substring(node.offset, node.end);
   }
@@ -37,13 +40,13 @@
 library test;
 import 'dart:math';
 ''');
+    List<Directive> oldDirectives = oldUnit.directives.toList();
     _buildNewUnit(r'''
 library test;
 import 'dart:async';
 import 'dart:math';
 ''');
-    var oldDirectives = oldUnit.directives;
-    var newDirectives = newUnit.directives;
+    List<Directive> newDirectives = newUnit.directives;
     {
       Directive newNode = newDirectives[0];
       expect(newNode, same(oldDirectives[0]));
@@ -66,6 +69,7 @@
       expect(element, isNotNull);
       expect(element.nameOffset, newCode.indexOf("import 'dart:math';"));
     }
+    expect(unitDelta.hasDirectiveChange, isTrue);
   }
 
   test_directives_keepOffset_partOf() {
@@ -79,12 +83,12 @@
 part of my_lib;
 class A {}
 ''', libSource);
+    List<Directive> oldDirectives = oldUnit.directives.toList();
     _buildNewUnit(r'''
 part of my_lib;
 class A {}
 ''');
-    var oldDirectives = oldUnit.directives;
-    var newDirectives = newUnit.directives;
+    List<Directive> newDirectives = newUnit.directives;
     {
       Directive newNode = newDirectives[0];
       expect(newNode, same(oldDirectives[0]));
@@ -101,12 +105,12 @@
 import 'dart:async';
 import 'dart:math';
 ''');
+    List<Directive> oldDirectives = oldUnit.directives.toList();
     _buildNewUnit(r'''
 library test;
 import 'dart:math';
 ''');
-    var oldDirectives = oldUnit.directives;
-    var newDirectives = newUnit.directives;
+    List<Directive> newDirectives = newUnit.directives;
     {
       Directive newNode = newDirectives[0];
       expect(newNode, same(oldDirectives[0]));
@@ -123,6 +127,7 @@
       expect(element, isNotNull);
       expect(element.nameOffset, newCode.indexOf("import 'dart:math';"));
     }
+    expect(unitDelta.hasDirectiveChange, isTrue);
   }
 
   test_directives_reorder() {
@@ -131,13 +136,13 @@
 import  'dart:math' as m;
 import 'dart:async';
 ''');
+    List<Directive> oldDirectives = oldUnit.directives.toList();
     _buildNewUnit(r'''
 library test;
 import 'dart:async';
 import 'dart:math' as m;
 ''');
-    var oldDirectives = oldUnit.directives;
-    var newDirectives = newUnit.directives;
+    List<Directive> newDirectives = newUnit.directives;
     {
       Directive newNode = newDirectives[0];
       expect(newNode, same(oldDirectives[0]));
@@ -163,6 +168,7 @@
       expect(element.nameOffset, newCode.indexOf("import 'dart:math' as m;"));
       expect(element.prefix.nameOffset, newCode.indexOf("m;"));
     }
+    expect(unitDelta.hasDirectiveChange, isFalse);
   }
 
   test_directives_sameOrder_insertSpaces() {
@@ -171,14 +177,14 @@
 import 'dart:async';
 import 'dart:math';
 ''');
+    List<Directive> oldDirectives = oldUnit.directives.toList();
     _buildNewUnit(r'''
 library test;
 
 import 'dart:async' ;
 import  'dart:math';
 ''');
-    var oldDirectives = oldUnit.directives;
-    var newDirectives = newUnit.directives;
+    List<Directive> newDirectives = newUnit.directives;
     {
       Directive newNode = newDirectives[0];
       expect(newNode, same(oldDirectives[0]));
@@ -203,6 +209,7 @@
       expect(element, isNotNull);
       expect(element.nameOffset, newCode.indexOf("import  'dart:math';"));
     }
+    expect(unitDelta.hasDirectiveChange, isFalse);
   }
 
   test_directives_sameOrder_removeSpaces() {
@@ -212,13 +219,13 @@
 import 'dart:async' ;
 import  'dart:math';
 ''');
+    List<Directive> oldDirectives = oldUnit.directives.toList();
     _buildNewUnit(r'''
 library test;
 import 'dart:async';
 import 'dart:math';
 ''');
-    var oldDirectives = oldUnit.directives;
-    var newDirectives = newUnit.directives;
+    List<Directive> newDirectives = newUnit.directives;
     {
       Directive newNode = newDirectives[0];
       expect(newNode, same(oldDirectives[0]));
@@ -243,17 +250,18 @@
       expect(element, isNotNull);
       expect(element.nameOffset, newCode.indexOf("import 'dart:math';"));
     }
+    expect(unitDelta.hasDirectiveChange, isFalse);
   }
 
   test_unitMembers_accessor_add() {
     _buildOldUnit(r'''
 get a => 1;
 ''');
+    List<CompilationUnitMember> oldNodes = oldUnit.declarations.toList();
     _buildNewUnit(r'''
 get a => 1;
 get b => 2;
 ''');
-    List<CompilationUnitMember> oldNodes = oldUnit.declarations;
     List<CompilationUnitMember> newNodes = newUnit.declarations;
     // nodes
     FunctionDeclaration node1 = newNodes[0];
@@ -276,11 +284,11 @@
     _buildOldUnit(r'''
 class A {}
 ''');
+    List<CompilationUnitMember> oldNodes = oldUnit.declarations.toList();
     _buildNewUnit(r'''
 class A {}
 class B {}
 ''');
-    List<CompilationUnitMember> oldNodes = oldUnit.declarations;
     List<CompilationUnitMember> newNodes = newUnit.declarations;
     // nodes
     CompilationUnitMember nodeA = newNodes[0];
@@ -295,6 +303,9 @@
     expect(elementB.name, 'B');
     // unit.types
     expect(unitElement.types, unorderedEquals([elementA, elementB]));
+    // verify delta
+    expect(unitDelta.addedDeclarations, unorderedEquals([elementB]));
+    expect(unitDelta.removedDeclarations, unorderedEquals([]));
   }
 
   test_unitMembers_class_comments() {
@@ -306,6 +317,7 @@
 /// reference [double] and [B] types.
 class C {}
 ''');
+    List<CompilationUnitMember> oldNodes = oldUnit.declarations.toList();
     _buildNewUnit(r'''
 /// reference [double] and [B] types.
 class C {}
@@ -314,7 +326,6 @@
 /// reference [int] type.
 class B {}
 ''');
-    List<CompilationUnitMember> oldNodes = oldUnit.declarations;
     List<CompilationUnitMember> newNodes = newUnit.declarations;
     {
       CompilationUnitMember newNode = newNodes[0];
@@ -369,6 +380,37 @@
         expect(docReferences[0].identifier.staticElement.name, 'int');
       }
     }
+    // verify delta
+    expect(unitDelta.addedDeclarations, unorderedEquals([]));
+    expect(unitDelta.removedDeclarations, unorderedEquals([]));
+  }
+
+  test_unitMembers_class_remove() {
+    _buildOldUnit(r'''
+class A {}
+class B {}
+''');
+    List<CompilationUnitMember> oldNodes = oldUnit.declarations.toList();
+    _buildNewUnit(r'''
+class A {}
+''');
+    List<CompilationUnitMember> newNodes = newUnit.declarations;
+    // nodes
+    CompilationUnitMember nodeA = newNodes[0];
+    CompilationUnitMember nodeB = oldNodes[1];
+    expect(nodeA, same(oldNodes[0]));
+    // elements
+    ClassElement elementA = nodeA.element;
+    ClassElement elementB = nodeB.element;
+    expect(elementA, isNotNull);
+    expect(elementB, isNotNull);
+    expect(elementA.name, 'A');
+    expect(elementB.name, 'B');
+    // unit.types
+    expect(unitElement.types, unorderedEquals([elementA]));
+    // verify delta
+    expect(unitDelta.addedDeclarations, unorderedEquals([]));
+    expect(unitDelta.removedDeclarations, unorderedEquals([elementB]));
   }
 
   test_unitMembers_class_reorder() {
@@ -377,12 +419,12 @@
 class B {}
 class C {}
 ''');
+    List<CompilationUnitMember> oldNodes = oldUnit.declarations.toList();
     _buildNewUnit(r'''
 class C {}
 class A {}
 class B {}
 ''');
-    List<CompilationUnitMember> oldNodes = oldUnit.declarations;
     List<CompilationUnitMember> newNodes = newUnit.declarations;
     {
       CompilationUnitMember newNode = newNodes[0];
@@ -411,17 +453,20 @@
       expect(element.name, 'B');
       expect(element.nameOffset, newCode.indexOf('B {}'));
     }
+    // verify delta
+    expect(unitDelta.addedDeclarations, unorderedEquals([]));
+    expect(unitDelta.removedDeclarations, unorderedEquals([]));
   }
 
   test_unitMembers_enum_add() {
     _buildOldUnit(r'''
 enum A {A1, A2}
 ''');
+    List<CompilationUnitMember> oldNodes = oldUnit.declarations.toList();
     _buildNewUnit(r'''
 enum A {A1, A2}
 enum B {B1, B2}
 ''');
-    List<CompilationUnitMember> oldNodes = oldUnit.declarations;
     List<CompilationUnitMember> newNodes = newUnit.declarations;
     // nodes
     CompilationUnitMember nodeA = newNodes[0];
@@ -436,17 +481,20 @@
     expect(elementB.name, 'B');
     // unit.types
     expect(unitElement.enums, unorderedEquals([elementA, elementB]));
+    // verify delta
+    expect(unitDelta.addedDeclarations, unorderedEquals([elementB]));
+    expect(unitDelta.removedDeclarations, unorderedEquals([]));
   }
 
   test_unitMembers_function_add() {
     _buildOldUnit(r'''
 a() {}
 ''');
+    List<CompilationUnitMember> oldNodes = oldUnit.declarations.toList();
     _buildNewUnit(r'''
 a() {}
 b() {}
 ''');
-    List<CompilationUnitMember> oldNodes = oldUnit.declarations;
     List<CompilationUnitMember> newNodes = newUnit.declarations;
     // nodes
     CompilationUnitMember nodeA = newNodes[0];
@@ -461,17 +509,20 @@
     expect(elementB.name, 'b');
     // unit.types
     expect(unitElement.functions, unorderedEquals([elementA, elementB]));
+    // verify delta
+    expect(unitDelta.addedDeclarations, unorderedEquals([elementB]));
+    expect(unitDelta.removedDeclarations, unorderedEquals([]));
   }
 
   test_unitMembers_functionTypeAlias_add() {
     _buildOldUnit(r'''
 typedef A();
 ''');
+    List<CompilationUnitMember> oldNodes = oldUnit.declarations.toList();
     _buildNewUnit(r'''
 typedef A();
 typedef B();
 ''');
-    List<CompilationUnitMember> oldNodes = oldUnit.declarations;
     List<CompilationUnitMember> newNodes = newUnit.declarations;
     // nodes
     CompilationUnitMember nodeA = newNodes[0];
@@ -487,17 +538,20 @@
     // unit.types
     expect(
         unitElement.functionTypeAliases, unorderedEquals([elementA, elementB]));
+    // verify delta
+    expect(unitDelta.addedDeclarations, unorderedEquals([elementB]));
+    expect(unitDelta.removedDeclarations, unorderedEquals([]));
   }
 
   test_unitMembers_topLevelVariable_add() {
     _buildOldUnit(r'''
 int a, b;
 ''');
+    List<CompilationUnitMember> oldNodes = oldUnit.declarations.toList();
     _buildNewUnit(r'''
 int a, b;
 int c, d;
 ''');
-    List<CompilationUnitMember> oldNodes = oldUnit.declarations;
     List<CompilationUnitMember> newNodes = newUnit.declarations;
     // nodes
     TopLevelVariableDeclaration node1 = newNodes[0];
@@ -536,12 +590,12 @@
 bool a = 1, b = 2;
 int c = 3;
 ''');
+    List<CompilationUnitMember> oldNodes = oldUnit.declarations.toList();
     _buildNewUnit(r'''
 int c = 3;
 
 bool a =1, b = 2;
 ''');
-    List<CompilationUnitMember> oldNodes = oldUnit.declarations;
     List<CompilationUnitMember> newNodes = newUnit.declarations;
     {
       TopLevelVariableDeclaration newNode = newNodes[0];
@@ -574,13 +628,19 @@
         expect(element.nameOffset, newCode.indexOf('b = 2'));
       }
     }
+    // verify delta
+    expect(unitDelta.addedDeclarations, unorderedEquals([]));
+    expect(unitDelta.removedDeclarations, unorderedEquals([]));
   }
 
   void _buildNewUnit(String newCode) {
     this.newCode = newCode;
     context.setContents(source, newCode);
     newUnit = context.parseCompilationUnit(source);
-    new IncrementalCompilationUnitElementBuilder(oldUnit, newUnit).build();
+    IncrementalCompilationUnitElementBuilder builder =
+        new IncrementalCompilationUnitElementBuilder(oldUnit, newUnit);
+    builder.build();
+    unitDelta = builder.unitDelta;
     expect(newUnit.element, unitElement);
   }
 
diff --git a/pkg/analyzer/test/src/task/inputs_test.dart b/pkg/analyzer/test/src/task/inputs_test.dart
index 4c4c6a4..cbd5890 100644
--- a/pkg/analyzer/test/src/task/inputs_test.dart
+++ b/pkg/analyzer/test/src/task/inputs_test.dart
@@ -564,7 +564,6 @@
   test_inputValue_afterCurrentValueNotAvailable() {
     SimpleTaskInputBuilder builder = new SimpleTaskInputBuilder(input);
     builder.moveNext();
-    String value = 'value';
     builder.currentValueNotAvailable();
     builder.moveNext();
     expect(builder.inputValue, isNull);
diff --git a/pkg/analyzer/test/task/task_dart_test.dart b/pkg/analyzer/test/task/task_dart_test.dart
index 352bc3b..e7c03be 100644
--- a/pkg/analyzer/test/task/task_dart_test.dart
+++ b/pkg/analyzer/test/task/task_dart_test.dart
@@ -63,8 +63,7 @@
   void test_perform_exception() {
     TestSource source = new TestSource();
     source.generateExceptionOnRead = true;
-    InternalAnalysisContext context = new AnalysisContextImpl();
-    context.sourceFactory = new SourceFactory([new FileUriResolver()]);
+    InternalAnalysisContext context = AnalysisContextFactory.contextWithCore();
     CompilationUnit unit = parseUnit(context, source, "");
     BuildUnitElementTask task =
         new BuildUnitElementTask(context, null, source, unit);
diff --git a/pkg/compiler/lib/src/compile_time_constants.dart b/pkg/compiler/lib/src/compile_time_constants.dart
index 00112af..a1c3768 100644
--- a/pkg/compiler/lib/src/compile_time_constants.dart
+++ b/pkg/compiler/lib/src/compile_time_constants.dart
@@ -22,6 +22,16 @@
 /// A [ConstantEnvironment] provides access for constants compiled for variable
 /// initializers.
 abstract class ConstantEnvironment {
+  /// The [ConstantSystem] used by this environment.
+  ConstantSystem get constantSystem;
+
+  /// Returns the constant value computed for [expression].
+  // TODO(johnniwinther): Support directly evaluation of [expression].
+  ConstantValue getConstantValue(ConstantExpression expression);
+
+  /// Returns the constant value for the initializer of [element].
+  ConstantValue getConstantValueForVariable(VariableElement element);
+
   /// Returns the constant for the initializer of [element].
   ConstantExpression getConstantForVariable(VariableElement element);
 }
@@ -73,13 +83,18 @@
 /// A [BackendConstantEnvironment] provides access to constants needed for
 /// backend implementation.
 abstract class BackendConstantEnvironment extends ConstantEnvironment {
+  /// Returns the compile-time constant value associated with [node].
+  ///
+  /// Depending on implementation, the constant might be stored in [elements].
+  ConstantValue getConstantValueForNode(Node node, TreeElements elements);
+
   /// Returns the compile-time constant associated with [node].
   ///
   /// Depending on implementation, the constant might be stored in [elements].
   ConstantExpression getConstantForNode(Node node, TreeElements elements);
 
   /// Returns the compile-time constant value of [metadata].
-  ConstantExpression getConstantForMetadata(MetadataAnnotation metadata);
+  ConstantValue getConstantValueForMetadata(MetadataAnnotation metadata);
 }
 
 /// Interface for the task that compiles the constant environments for the
@@ -87,6 +102,13 @@
 abstract class ConstantCompilerTask extends CompilerTask
     implements ConstantCompiler {
   ConstantCompilerTask(Compiler compiler) : super(compiler);
+
+  /// Copy all cached constant values from [task].
+  ///
+  /// This is a hack to support reuse cached compilers in memory_compiler.
+  // TODO(johnniwinther): Remove this when values are computed from the
+  // expressions.
+  void copyConstantValues(ConstantCompilerTask task);
 }
 
 /**
@@ -117,8 +139,17 @@
   /** The set of variable elements that are in the process of being computed. */
   final Set<VariableElement> pendingVariables = new Set<VariableElement>();
 
+  final Map<ConstantExpression, ConstantValue> constantValueMap =
+      <ConstantExpression, ConstantValue>{};
+
   ConstantCompilerBase(this.compiler, this.constantSystem);
 
+  @override
+  ConstantValue getConstantValueForVariable(VariableElement element) {
+    return getConstantValue(initialVariableValues[element.declaration]);
+  }
+
+  @override
   ConstantExpression getConstantForVariable(VariableElement element) {
     return initialVariableValues[element.declaration];
   }
@@ -159,35 +190,39 @@
       if (isConst) {
         compiler.reportError(
             node, MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS);
-        return new ErroneousConstantExpression();
+        ConstantExpression expression = new ErroneousConstantExpression();
+        constantValueMap[expression] = constantSystem.createNull();
+        return expression;
       }
       return null;
     }
     pendingVariables.add(element);
 
     Expression initializer = element.initializer;
-    ConstantExpression value;
+    ConstantExpression expression;
     if (initializer == null) {
       // No initial value.
-      value = new NullConstantExpression(new NullConstantValue());
+      expression = new NullConstantExpression();
+      constantValueMap[expression] = constantSystem.createNull();
     } else {
-      value = compileNodeWithDefinitions(
+      expression = compileNodeWithDefinitions(
           initializer, definitions, isConst: isConst);
       if (compiler.enableTypeAssertions &&
-          value != null &&
+          expression != null &&
           element.isField) {
         DartType elementType = element.type;
-        if (elementType.isMalformed && !value.value.isNull) {
+        ConstantValue value = getConstantValue(expression);
+        if (elementType.isMalformed && !value.isNull) {
           if (isConst) {
             ErroneousElement element = elementType.element;
             compiler.reportError(
                 node, element.messageKind, element.messageArguments);
           } else {
             // We need to throw an exception at runtime.
-            value = null;
+            expression = null;
           }
         } else {
-          DartType constantType = value.value.getType(compiler.coreTypes);
+          DartType constantType = value.getType(compiler.coreTypes);
           if (!constantSystem.isSubtype(compiler.types,
                                         constantType, elementType)) {
             if (isConst) {
@@ -197,20 +232,20 @@
             } else {
               // If the field cannot be lazily initialized, we will throw
               // the exception at runtime.
-              value = null;
+              expression = null;
             }
           }
         }
       }
     }
-    if (value != null) {
-      initialVariableValues[element.declaration] = value;
+    if (expression != null) {
+      initialVariableValues[element.declaration] = expression;
     } else {
       assert(invariant(element, !isConst,
              message: "Variable $element does not compile to a constant."));
     }
     pendingVariables.remove(element);
-    return value;
+    return expression;
   }
 
   ConstantExpression compileNodeWithDefinitions(Node node,
@@ -220,7 +255,15 @@
     CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator(
         this, definitions, compiler, isConst: isConst);
     AstConstant constant = evaluator.evaluate(node);
-    return constant != null ? constant.expression : null;
+    if (constant != null) {
+      constantValueMap[constant.expression] = constant.value;
+      return constant.expression;
+    }
+    return null;
+  }
+
+  ConstantValue getConstantValue(ConstantExpression expression) {
+    return constantValueMap[expression];
   }
 
   ConstantExpression compileNode(Node node, TreeElements elements,
@@ -255,10 +298,6 @@
     return definitions.getConstant(node);
   }
 
-  ConstantExpression getConstantForMetadata(MetadataAnnotation metadata) {
-    return metadata.constant;
-  }
-
   ConstantExpression compileNodeWithDefinitions(Node node,
                                                 TreeElements definitions,
                                                 {bool isConst: true}) {
@@ -312,23 +351,26 @@
 
   AstConstant visitLiteralBool(LiteralBool node) {
     return new AstConstant(
-        context, node, new BoolConstantExpression(
-            node.value,
-            constantSystem.createBool(node.value)));
+        context,
+        node,
+        new BoolConstantExpression(node.value),
+        constantSystem.createBool(node.value));
   }
 
   AstConstant visitLiteralDouble(LiteralDouble node) {
     return new AstConstant(
-        context, node, new DoubleConstantExpression(
-            node.value,
-            constantSystem.createDouble(node.value)));
+        context,
+        node,
+        new DoubleConstantExpression(node.value),
+        constantSystem.createDouble(node.value));
   }
 
   AstConstant visitLiteralInt(LiteralInt node) {
     return new AstConstant(
-        context, node, new IntConstantExpression(
-            node.value,
-            constantSystem.createInt(node.value)));
+        context,
+        node,
+        new IntConstantExpression(node.value),
+        constantSystem.createInt(node.value));
   }
 
   AstConstant visitLiteralList(LiteralList node) {
@@ -349,10 +391,10 @@
     }
     DartType type = elements.getType(node);
     return new AstConstant(
-        context, node, new ListConstantExpression(
-            constantSystem.createList(type, argumentValues),
-            type,
-            argumentExpressions));
+        context,
+        node,
+        new ListConstantExpression(type, argumentExpressions),
+        constantSystem.createList(type, argumentValues));
   }
 
   AstConstant visitLiteralMap(LiteralMap node) {
@@ -360,9 +402,9 @@
       return signalNotCompileTimeConstant(node);
     }
     List<ConstantExpression> keyExpressions = <ConstantExpression>[];
+    List<ConstantExpression> valueExpressions = <ConstantExpression>[];
     List<ConstantValue> keyValues = <ConstantValue>[];
-    Map<ConstantValue, ConstantExpression> map =
-        new Map<ConstantValue, ConstantExpression>();
+    Map<ConstantValue, ConstantValue> map = <ConstantValue, ConstantValue>{};
     for (Link<Node> link = node.entries.nodes;
          !link.isEmpty;
          link = link.tail) {
@@ -371,40 +413,45 @@
       if (key == null) {
         return null;
       }
-      if (!map.containsKey(key.value)) {
-        keyExpressions.add(key.expression);
-        keyValues.add(key.value);
-      } else {
-        compiler.reportWarning(entry.key, MessageKind.EQUAL_MAP_ENTRY_KEY);
-      }
       AstConstant value = evaluateConstant(entry.value);
       if (value == null) {
         return null;
       }
-      map[key.value] = value.expression;
+      if (!map.containsKey(key.value)) {
+        keyValues.add(key.value);
+      } else {
+        compiler.reportWarning(entry.key, MessageKind.EQUAL_MAP_ENTRY_KEY);
+      }
+      keyExpressions.add(key.expression);
+      valueExpressions.add(value.expression);
+      map[key.value] = value.value;
     }
-    List<ConstantExpression> valueExpressions = map.values.toList();
     InterfaceType type = elements.getType(node);
     return new AstConstant(
-        context, node, new MapConstantExpression(
-            constantSystem.createMap(compiler, type, keyValues,
-                valueExpressions.map((e) => e.value).toList()),
+        context,
+        node,
+        new MapConstantExpression(
             type,
             keyExpressions,
-            valueExpressions));
+            valueExpressions),
+        constantSystem.createMap(
+            compiler, type, keyValues, map.values.toList()));
   }
 
   AstConstant visitLiteralNull(LiteralNull node) {
     return new AstConstant(
-        context, node, new NullConstantExpression(
-            constantSystem.createNull()));
+        context,
+        node,
+        new NullConstantExpression(),
+        constantSystem.createNull());
   }
 
   AstConstant visitLiteralString(LiteralString node) {
     return new AstConstant(
-        context, node, new StringConstantExpression(
-            node.dartString.slowToString(),
-            constantSystem.createString(node.dartString)));
+        context,
+        node,
+        new StringConstantExpression(node.dartString.slowToString()),
+        constantSystem.createString(node.dartString));
   }
 
   AstConstant visitStringJuxtaposition(StringJuxtaposition node) {
@@ -414,11 +461,12 @@
     StringConstantValue leftValue = left.value;
     StringConstantValue rightValue = right.value;
     return new AstConstant(
-        context, node, new ConcatenateConstantExpression(
-            constantSystem.createString(
-                new DartString.concat(
-                    leftValue.primitiveValue, rightValue.primitiveValue)),
-            [left.expression, right.expression]));
+        context,
+        node,
+        new ConcatenateConstantExpression([left.expression, right.expression]),
+        constantSystem.createString(
+            new DartString.concat(
+                leftValue.primitiveValue, rightValue.primitiveValue)));
   }
 
   AstConstant visitStringInterpolation(StringInterpolation node) {
@@ -459,30 +507,31 @@
           new DartString.concat(accumulator, partStringValue.primitiveValue);
     };
     return new AstConstant(
-        context, node, new ConcatenateConstantExpression(
-          constantSystem.createString(accumulator),
-          subexpressions));
+        context,
+        node,
+        new ConcatenateConstantExpression(subexpressions),
+        constantSystem.createString(accumulator));
   }
 
   AstConstant visitLiteralSymbol(LiteralSymbol node) {
     InterfaceType type = compiler.symbolClass.rawType;
     String text = node.slowNameString;
     List<AstConstant> arguments =
-        <AstConstant>[new AstConstant(context, node,
-          new StringConstantExpression(
-              text,
-              constantSystem.createString(new LiteralDartString(text))))];
+        <AstConstant>[new AstConstant(
+            context,
+            node,
+            new StringConstantExpression(text),
+            constantSystem.createString(new LiteralDartString(text)))];
     ConstructorElement constructor = compiler.symbolConstructor;
     AstConstant constant = createConstructorInvocation(
         node, type, constructor, CallStructure.ONE_ARG,
         normalizedArguments: arguments);
     return new AstConstant(
-        context, node, new SymbolConstantExpression(constant.value, text));
+        context, node, new SymbolConstantExpression(text), constant.value);
   }
 
-  ConstantExpression makeTypeConstant(DartType elementType) {
-    return new TypeConstantExpression(
-        constantSystem.createType(compiler, elementType), elementType);
+  ConstantValue makeTypeConstant(DartType elementType) {
+    return constantSystem.createType(compiler, elementType);
   }
 
   /// Returns true if the prefix of the send resolves to a deferred import
@@ -498,7 +547,8 @@
     if (Elements.isClass(element) || Elements.isTypedef(element)) {
       TypeDeclarationElement typeDeclarationElement = element;
       DartType type = typeDeclarationElement.rawType;
-      return new AstConstant(element, node, makeTypeConstant(type));
+      return new AstConstant(element, node,
+          new TypeConstantExpression(type), makeTypeConstant(type));
     }
     return signalNotCompileTimeConstant(node);
   }
@@ -507,13 +557,15 @@
   AstConstant visitSend(Send send) {
     Element element = elements[send];
     if (send.isPropertyAccess) {
-      ConstantExpression result;
-
+      AstConstant result;
       if (Elements.isStaticOrTopLevelFunction(element)) {
         FunctionElementX function = element;
         function.computeType(compiler);
-        result = new FunctionConstantExpression(
-            new FunctionConstantValue(function), function);
+        result = new AstConstant(
+            context,
+            send,
+            new FunctionConstantExpression(function),
+            new FunctionConstantValue(function));
       } else if (Elements.isStaticOrTopLevelField(element)) {
         ConstantExpression elementExpression;
         if (element.isConst) {
@@ -522,12 +574,20 @@
           elementExpression = handler.compileVariable(element);
         }
         if (elementExpression != null) {
-          result =
-              new VariableConstantExpression(elementExpression.value, element);
+          result = new AstConstant(
+              context,
+              send,
+              new VariableConstantExpression(element),
+              handler.getConstantValue(elementExpression));
         }
       } else if (Elements.isClass(element) || Elements.isTypedef(element)) {
         assert(elements.isTypeLiteral(send));
-        result = makeTypeConstant(elements.getTypeLiteralType(send));
+        DartType elementType = elements.getTypeLiteralType(send);
+        result = new AstConstant(
+            context,
+            send,
+            new TypeConstantExpression(elementType),
+            makeTypeConstant(elementType));
       } else if (send.receiver != null) {
         if (send.selector.asIdentifier().source == "length") {
           AstConstant left = evaluate(send.receiver);
@@ -535,7 +595,11 @@
             StringConstantValue stringConstantValue = left.value;
             DartString string = stringConstantValue.primitiveValue;
             IntConstantValue length = constantSystem.createInt(string.length);
-            result = new VariableConstantExpression(length, element);
+            result = new AstConstant(
+                context,
+                send,
+                new StringLengthConstantExpression(left.expression),
+                length);
           }
         }
         // Fall through to error handling.
@@ -545,8 +609,11 @@
         ConstantExpression variableExpression =
             handler.compileConstant(element);
         if (variableExpression != null) {
-          result = new VariableConstantExpression(variableExpression.value,
-                                                  element);
+          result = new AstConstant(
+              context,
+              send,
+              new VariableConstantExpression(element),
+              handler.getConstantValue(variableExpression));
         }
       }
       if (result == null) {
@@ -558,14 +625,17 @@
         }
         PrefixElement prefix = compiler.deferredLoadTask
             .deferredPrefixElement(send, elements);
-        result = new DeferredConstantExpression(
-            new DeferredConstantValue(result.value, prefix),
-            result,
-            prefix);
+        result = new AstConstant(
+            context,
+            send,
+            new DeferredConstantExpression(
+                result.expression,
+                prefix),
+            new DeferredConstantValue(result.value, prefix));
         compiler.deferredLoadTask
             .registerConstantDeferredUse(result.value, prefix);
       }
-      return new AstConstant(context, send, result);
+      return result;
     } else if (send.isCall) {
       if (element == compiler.identicalFunction
           && send.argumentCount() == 2) {
@@ -578,8 +648,11 @@
             constantSystem.identity.fold(left.value, right.value);
         if (result != null) {
           return new AstConstant(
-              context, send, new IdenticalConstantExpression(result,
-                  left.expression, right.expression));
+              context,
+              send,
+              new IdenticalConstantExpression(
+                  left.expression, right.expression),
+              result);
         }
       }
       return signalNotCompileTimeConstant(send);
@@ -600,8 +673,11 @@
         return signalNotCompileTimeConstant(send);
       }
       return new AstConstant(
-          context, send, new UnaryConstantExpression(folded,
-              operator, receiverConstant.expression));
+          context,
+          send,
+          new UnaryConstantExpression(
+              operator, receiverConstant.expression),
+          folded);
     } else if (send.isOperator && !send.isPostfix) {
       assert(send.argumentCount() == 1);
       AstConstant left = evaluate(send.receiver);
@@ -644,8 +720,11 @@
         return signalNotCompileTimeConstant(send);
       }
       return new AstConstant(
-          context, send, new BinaryConstantExpression(folded,
-              left.expression, operator, right.expression));
+          context,
+          send,
+          new BinaryConstantExpression(
+              left.expression, operator, right.expression),
+          folded);
     }
     return signalNotCompileTimeConstant(send);
   }
@@ -671,13 +750,15 @@
     }
     BoolConstantValue boolCondition = condition.value;
     return new AstConstant(
-        context, node, new ConditionalConstantExpression(
-            boolCondition.primitiveValue
-                ? thenExpression.value
-                : elseExpression.value,
+        context,
+        node,
+        new ConditionalConstantExpression(
             condition.expression,
             thenExpression.expression,
-            elseExpression.expression));
+            elseExpression.expression),
+        boolCondition.primitiveValue
+            ? thenExpression.value
+            : elseExpression.value);
   }
 
   AstConstant visitSendSet(SendSet node) {
@@ -701,7 +782,8 @@
 
     AstConstant compileDefaultValue(VariableElement element) {
       ConstantExpression constant = handler.compileConstant(element);
-      return new AstConstant.fromDefaultValue(element, constant);
+      return new AstConstant.fromDefaultValue(
+          element, constant, handler.getConstantValue(constant));
     }
     target.computeSignature(compiler);
 
@@ -773,14 +855,17 @@
     ConstructorElement implementation = target.implementation;
 
     if (implementation.isErroneous) {
+      // TODO(johnniwinther): This should probably be an [ErroneousAstConstant].
       return new AstConstant(
-          context, node, new ConstructedConstantExpression(
-              new ConstructedConstantValue(
-                  constructedType, const <FieldElement, ConstantValue>{}),
+          context,
+          node,
+          new ConstructedConstantExpression(
               type,
               constructor,
               callStructure,
-              const <ConstantExpression>[]));
+              const <ConstantExpression>[]),
+          new ConstructedConstantValue(
+              constructedType, const <FieldElement, ConstantValue>{}));
     }
 
     List<AstConstant> concreteArguments;
@@ -880,17 +965,22 @@
     AstConstant createEvaluatedConstant(ConstantValue value) {
 
       ConstantExpression expression;
+      ConstantExpression name = concreteArguments[0].expression;
+      ConstantExpression defaultValue;
+      if (concreteArguments.length > 1) {
+        defaultValue = concreteArguments[1].expression;
+      }
       if (constructor == compiler.intEnvironment) {
         expression = new IntFromEnvironmentConstantExpression(
-            value, name, normalizedArguments[1].expression);
+            name, defaultValue);
       } else if (constructor == compiler.boolEnvironment) {
         expression = new BoolFromEnvironmentConstantExpression(
-            value, name, normalizedArguments[1].expression);
+            name, defaultValue);
       } else if (constructor == compiler.stringEnvironment) {
         expression = new StringFromEnvironmentConstantExpression(
-            value, name, normalizedArguments[1].expression);
+            name, defaultValue);
       }
-      return new AstConstant(context, node, expression);
+      return new AstConstant(context, node, expression, value);
     }
 
     if (value == null) {
@@ -933,8 +1023,7 @@
       assert(invariant(node, compiler.compilationFailed,
           message: "makeConstructedConstant can only be called with the "
                    "effective target: $constructor"));
-      return new AstConstant(
-          context, node, new ErroneousConstantExpression());
+      return new ErroneousAstConstant(context, node);
     }
     assert(invariant(node, callStructure.signatureApplies(constructor) ||
                      compiler.compilationFailed,
@@ -952,12 +1041,14 @@
       fieldValues[field] = astConstant.value;
     });
     return new AstConstant(
-        context, node, new ConstructedConstantExpression(
-            new ConstructedConstantValue(constructedType, fieldValues),
+        context,
+        node,
+        new ConstructedConstantExpression(
             type,
             constructor,
             callStructure,
-            concreteArguments.map((e) => e.expression).toList()));
+            concreteArguments.map((e) => e.expression).toList()),
+        new ConstructedConstantValue(constructedType, fieldValues));
   }
 
   AstConstant visitParenthesizedExpression(ParenthesizedExpression node) {
@@ -976,7 +1067,10 @@
       error(node, message);
 
       return new AstConstant(
-          null, node, new NullConstantExpression(new NullConstantValue()));
+          context,
+          node,
+          new ErroneousConstantExpression(),
+          new NullConstantValue());
     }
     // Else we don't need to do anything. The final handler is only
     // optimistically trying to compile constants. So it is normal that we
@@ -1182,8 +1276,11 @@
           AstConstant fieldValue = fieldValues[field];
           if (fieldValue == null) {
             // Use the default value.
+            ConstantExpression fieldExpression = handler.compileConstant(field);
             fieldValue = new AstConstant.fromDefaultValue(
-                field, handler.compileConstant(field));
+                field,
+                fieldExpression,
+                handler.getConstantValue(fieldExpression));
           }
           fieldConstants[field] = fieldValue;
         },
@@ -1205,27 +1302,30 @@
   final Element element;
   final Node node;
   final ConstantExpression expression;
+  final ConstantValue value;
 
-  AstConstant(this.element, this.node, this.expression);
+  AstConstant(this.element, this.node, this.expression, this.value);
 
   factory AstConstant.fromDefaultValue(
       VariableElement element,
-      ConstantExpression constant) {
+      ConstantExpression constant,
+      ConstantValue value) {
     return new AstConstant(
         element,
         element.initializer != null ? element.initializer : element.node,
-        constant);
+        constant,
+        value);
   }
 
-  ConstantValue get value => expression.value;
-
   String toString() => expression.toString();
 }
 
 /// A synthetic constant used to recover from errors.
 class ErroneousAstConstant extends AstConstant {
   ErroneousAstConstant(Element element, Node node)
-      : super(element, node, new ErroneousConstantExpression());
+      : super(element, node,
+          // TODO(johnniwinther): Return a [NonConstantValue] instead.
+          new ErroneousConstantExpression(), new NullConstantValue());
 }
 
 // TODO(johnniwinther): Avoid the need for this hack.
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index 98afea3..2ba863e 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -1380,8 +1380,9 @@
       functionApplyMethod = functionClass.lookupLocalMember('apply');
 
       proxyConstant =
-          resolver.constantCompiler.compileConstant(
-              coreLibrary.find('proxy')).value;
+          constants.getConstantValue(
+              resolver.constantCompiler.compileConstant(
+                  coreLibrary.find('proxy')));
 
       if (preserveComments) {
         return libraryLoader.loadLibrary(DART_MIRRORS)
@@ -1510,14 +1511,6 @@
     });
   }
 
-  bool irEnabled() {
-    // TODO(sigurdm,kmillikin): Support checked-mode checks.
-    return useCpsIr &&
-        backend is DartBackend &&
-        !enableTypeAssertions &&
-        !enableConcreteTypeInference;
-  }
-
   void computeMain() {
     if (mainApp == null) return;
 
@@ -1649,11 +1642,6 @@
 
     deferredLoadTask.onResolutionComplete(mainFunction);
 
-    if (irEnabled()) {
-      log('Building IR...');
-      irBuilder.buildNodes();
-    }
-
     log('Inferring types...');
     typesTask.onResolutionComplete(mainFunction);
 
diff --git a/pkg/compiler/lib/src/constants/constructors.dart b/pkg/compiler/lib/src/constants/constructors.dart
index 2e83e56..ab0e45a 100644
--- a/pkg/compiler/lib/src/constants/constructors.dart
+++ b/pkg/compiler/lib/src/constants/constructors.dart
@@ -122,7 +122,7 @@
     CallStructure callStructure = new CallStructure(index, argumentNames);
 
     return new RedirectingFactoryConstantConstructor(
-        new ConstructedConstantExpression(null,
+        new ConstructedConstantExpression(
             redirectionType,
             redirectionTarget,
             callStructure,
@@ -252,7 +252,7 @@
       _) {
     List<ConstantExpression> argumentExpression =
         arguments.nodes.map((a) => apply(a)).toList();
-    return new ConstructedConstantExpression(null,
+    return new ConstructedConstantExpression(
         type,
         superConstructor,
         callStructure,
@@ -264,7 +264,7 @@
       ConstructorElement superConstructor,
       InterfaceType type,
       _) {
-     return new ConstructedConstantExpression(null,
+     return new ConstructedConstantExpression(
          type,
          superConstructor,
          CallStructure.NO_ARGS,
@@ -279,7 +279,7 @@
       _) {
     List<ConstantExpression> argumentExpression =
         arguments.nodes.map((a) => apply(a)).toList();
-    return new ConstructedConstantExpression(null,
+    return new ConstructedConstantExpression(
         currentClass.thisType,
         thisConstructor,
         callStructure,
@@ -293,7 +293,7 @@
       BinaryOperator operator,
       Node right,
       _) {
-    return new BinaryConstantExpression(null,
+    return new BinaryConstantExpression(
         apply(left), operator, apply(right));
   }
 
@@ -304,7 +304,7 @@
       UnaryOperator operator,
       Node expression,
       _) {
-    return new UnaryConstantExpression(null,
+    return new UnaryConstantExpression(
         operator, apply(expression));
   }
 
@@ -313,7 +313,7 @@
       Send node,
       FieldElement field,
       _) {
-    return new VariableConstantExpression(null, field);
+    return new VariableConstantExpression(field);
   }
 
   @override
@@ -321,33 +321,32 @@
       Send node,
       FieldElement field,
       _) {
-    return new VariableConstantExpression(null, field);
+    return new VariableConstantExpression(field);
   }
 
   @override
   ConstantExpression visitLiteralInt(LiteralInt node) {
-    return new IntConstantExpression(
-        node.value, new IntConstantValue(node.value));
+    return new IntConstantExpression(node.value);
   }
 
   @override
   ConstantExpression visitLiteralBool(LiteralBool node) {
-    return new BoolConstantExpression(node.value, null);
+    return new BoolConstantExpression(node.value);
   }
 
   @override
   ConstantExpression visitLiteralNull(LiteralNull node) {
-    return new NullConstantExpression(new NullConstantValue());
+    return new NullConstantExpression();
   }
 
   @override
   ConstantExpression visitLiteralString(LiteralString node) {
-    return new StringConstantExpression(node.dartString.slowToString(), null);
+    return new StringConstantExpression(node.dartString.slowToString());
   }
 
   @override
   ConstantExpression visitConditional(Conditional node) {
-    return new ConditionalConstantExpression(null,
+    return new ConditionalConstantExpression(
         apply(node.condition),
         apply(node.thenExpression),
         apply(node.elseExpression));
@@ -369,7 +368,7 @@
       throw new UnsupportedError("Unexpected function call: $function");
     }
     return new IdenticalConstantExpression(
-        null, apply(arguments.nodes.head), apply(arguments.nodes.tail.head));
+        apply(arguments.nodes.head), apply(arguments.nodes.tail.head));
   }
 
   @override
diff --git a/pkg/compiler/lib/src/constants/expressions.dart b/pkg/compiler/lib/src/constants/expressions.dart
index 0c6a6ac..23d65f2 100644
--- a/pkg/compiler/lib/src/constants/expressions.dart
+++ b/pkg/compiler/lib/src/constants/expressions.dart
@@ -38,6 +38,7 @@
   NULL,
   STRING,
   STRING_FROM_ENVIRONMENT,
+  STRING_LENGTH,
   SYMBOL,
   TYPE,
   UNARY,
@@ -260,11 +261,6 @@
 
   ConstantExpressionKind get kind;
 
-  /// Returns the value of this constant expression.
-  // TODO(johnniwinther): Replace this with an evaluation method that takes
-  // a constant system and an environment.
-  ConstantValue get value;
-
   // TODO(johnniwinther): Unify precedence handled between constants, front-end
   // and back-end.
   int get precedence => 16;
@@ -313,8 +309,6 @@
 
 /// A synthetic constant used to recover from errors.
 class ErroneousConstantExpression extends ConstantExpression {
-  final PrimitiveConstantValue value = new NullConstantValue();
-
   ConstantExpressionKind get kind => ConstantExpressionKind.ERRONEOUS;
 
   accept(ConstantExpressionVisitor visitor, [context]) {
@@ -325,7 +319,7 @@
   ConstantValue evaluate(Environment environment,
                          ConstantSystem constantSystem) {
     // TODO(johnniwinther): Use non-constant values for errors.
-    return value;
+    return new NonConstantValue();
   }
 
   @override
@@ -337,10 +331,6 @@
 
 /// A boolean, int, double, string, or null constant.
 abstract class PrimitiveConstantExpression extends ConstantExpression {
-  final PrimitiveConstantValue value;
-
-  PrimitiveConstantExpression(this.value);
-
   /// The primitive value of this contant expression.
   get primitiveValue;
 }
@@ -349,8 +339,7 @@
 class BoolConstantExpression extends PrimitiveConstantExpression {
   final bool primitiveValue;
 
-  BoolConstantExpression(this.primitiveValue,
-                         PrimitiveConstantValue value) : super(value);
+  BoolConstantExpression(this.primitiveValue);
 
   ConstantExpressionKind get kind => ConstantExpressionKind.BOOL;
 
@@ -377,8 +366,7 @@
 class IntConstantExpression extends PrimitiveConstantExpression {
   final int primitiveValue;
 
-  IntConstantExpression(this.primitiveValue,
-                        PrimitiveConstantValue value) : super(value);
+  IntConstantExpression(this.primitiveValue);
 
   ConstantExpressionKind get kind => ConstantExpressionKind.INT;
 
@@ -405,8 +393,7 @@
 class DoubleConstantExpression extends PrimitiveConstantExpression {
   final double primitiveValue;
 
-  DoubleConstantExpression(this.primitiveValue,
-                           PrimitiveConstantValue value) : super(value);
+  DoubleConstantExpression(this.primitiveValue);
 
   ConstantExpressionKind get kind => ConstantExpressionKind.DOUBLE;
 
@@ -433,8 +420,7 @@
 class StringConstantExpression extends PrimitiveConstantExpression {
   final String primitiveValue;
 
-  StringConstantExpression(this.primitiveValue,
-                           PrimitiveConstantValue value) : super(value);
+  StringConstantExpression(this.primitiveValue);
 
   ConstantExpressionKind get kind => ConstantExpressionKind.STRING;
 
@@ -459,7 +445,7 @@
 
 /// Null literal constant.
 class NullConstantExpression extends PrimitiveConstantExpression {
-  NullConstantExpression(PrimitiveConstantValue value) : super(value);
+  NullConstantExpression();
 
   ConstantExpressionKind get kind => ConstantExpressionKind.NULL;
 
@@ -484,11 +470,10 @@
 
 /// Literal list constant.
 class ListConstantExpression extends ConstantExpression {
-  final ListConstantValue value;
   final InterfaceType type;
   final List<ConstantExpression> values;
 
-  ListConstantExpression(this.value, this.type, this.values);
+  ListConstantExpression(this.type, this.values);
 
   ConstantExpressionKind get kind => ConstantExpressionKind.LIST;
 
@@ -504,8 +489,8 @@
   }
 
   ConstantExpression apply(NormalizedArguments arguments) {
-    return new ListConstantExpression(null, type,
-        values.map((v) => v.apply(arguments)).toList());
+    return new ListConstantExpression(
+        type, values.map((v) => v.apply(arguments)).toList());
   }
 
   @override
@@ -530,12 +515,11 @@
 
 /// Literal map constant.
 class MapConstantExpression extends ConstantExpression {
-  final MapConstantValue value;
   final InterfaceType type;
   final List<ConstantExpression> keys;
   final List<ConstantExpression> values;
 
-  MapConstantExpression(this.value, this.type, this.keys, this.values);
+  MapConstantExpression(this.type, this.keys, this.values);
 
   ConstantExpressionKind get kind => ConstantExpressionKind.MAP;
 
@@ -553,7 +537,8 @@
   }
 
   ConstantExpression apply(NormalizedArguments arguments) {
-    return new MapConstantExpression(null, type,
+    return new MapConstantExpression(
+        type,
         keys.map((k) => k.apply(arguments)).toList(),
         values.map((v) => v.apply(arguments)).toList());
   }
@@ -581,14 +566,12 @@
 
 /// Invocation of a const constructor.
 class ConstructedConstantExpression extends ConstantExpression {
-  final ConstantValue value;
   final InterfaceType type;
   final ConstructorElement target;
   final CallStructure callStructure;
   final List<ConstantExpression> arguments;
 
   ConstructedConstantExpression(
-      this.value,
       this.type,
       this.target,
       this.callStructure,
@@ -613,7 +596,7 @@
   }
 
   ConstructedConstantExpression apply(NormalizedArguments arguments) {
-    return new ConstructedConstantExpression(null,
+    return new ConstructedConstantExpression(
         type, target, callStructure,
         this.arguments.map((a) => a.apply(arguments)).toList());
   }
@@ -656,10 +639,9 @@
 
 /// String literal with juxtaposition and/or interpolations.
 class ConcatenateConstantExpression extends ConstantExpression {
-  final StringConstantValue value;
   final List<ConstantExpression> expressions;
 
-  ConcatenateConstantExpression(this.value, this.expressions);
+  ConcatenateConstantExpression(this.expressions);
 
   ConstantExpressionKind get kind => ConstantExpressionKind.CONCATENATE;
 
@@ -668,7 +650,7 @@
   }
 
   ConstantExpression apply(NormalizedArguments arguments) {
-    return new ConcatenateConstantExpression(null,
+    return new ConcatenateConstantExpression(
         expressions.map((a) => a.apply(arguments)).toList());
   }
 
@@ -721,10 +703,9 @@
 
 /// Symbol literal.
 class SymbolConstantExpression extends ConstantExpression {
-  final ConstructedConstantValue value;
   final String name;
 
-  SymbolConstantExpression(this.value, this.name);
+  SymbolConstantExpression(this.name);
 
   ConstantExpressionKind get kind => ConstantExpressionKind.SYMBOL;
 
@@ -750,11 +731,10 @@
 
 /// Type literal.
 class TypeConstantExpression extends ConstantExpression {
-  final TypeConstantValue value;
   /// Either [DynamicType] or a raw [GenericType].
   final DartType type;
 
-  TypeConstantExpression(this.value, this.type) {
+  TypeConstantExpression(this.type) {
     assert(type is GenericType || type is DynamicType);
   }
 
@@ -781,10 +761,9 @@
 
 /// Reference to a constant local, top-level, or static variable.
 class VariableConstantExpression extends ConstantExpression {
-  final ConstantValue value;
   final VariableElement element;
 
-  VariableConstantExpression(this.value, this.element);
+  VariableConstantExpression(this.element);
 
   ConstantExpressionKind get kind => ConstantExpressionKind.VARIABLE;
 
@@ -809,10 +788,9 @@
 
 /// Reference to a top-level or static function.
 class FunctionConstantExpression extends ConstantExpression {
-  final FunctionConstantValue value;
   final FunctionElement element;
 
-  FunctionConstantExpression(this.value, this.element);
+  FunctionConstantExpression(this.element);
 
   ConstantExpressionKind get kind => ConstantExpressionKind.FUNCTION;
 
@@ -837,12 +815,11 @@
 
 /// A constant binary expression like `a * b`.
 class BinaryConstantExpression extends ConstantExpression {
-  final ConstantValue value;
   final ConstantExpression left;
   final BinaryOperator operator;
   final ConstantExpression right;
 
-  BinaryConstantExpression(this.value, this.left, this.operator, this.right) {
+  BinaryConstantExpression(this.left, this.operator, this.right) {
     assert(PRECEDENCE_MAP[operator.kind] != null);
   }
 
@@ -862,7 +839,6 @@
 
   ConstantExpression apply(NormalizedArguments arguments) {
     return new BinaryConstantExpression(
-        value,
         left.apply(arguments),
         operator,
         right.apply(arguments));
@@ -909,11 +885,10 @@
 
 /// A constant identical invocation like `identical(a, b)`.
 class IdenticalConstantExpression extends ConstantExpression {
-  final ConstantValue value;
   final ConstantExpression left;
   final ConstantExpression right;
 
-  IdenticalConstantExpression(this.value, this.left, this.right);
+  IdenticalConstantExpression(this.left, this.right);
 
   ConstantExpressionKind get kind => ConstantExpressionKind.IDENTICAL;
 
@@ -931,7 +906,6 @@
 
   ConstantExpression apply(NormalizedArguments arguments) {
     return new IdenticalConstantExpression(
-        value,
         left.apply(arguments),
         right.apply(arguments));
   }
@@ -953,11 +927,10 @@
 
 /// A unary constant expression like `-a`.
 class UnaryConstantExpression extends ConstantExpression {
-  final ConstantValue value;
   final UnaryOperator operator;
   final ConstantExpression expression;
 
-  UnaryConstantExpression(this.value, this.operator, this.expression) {
+  UnaryConstantExpression(this.operator, this.expression) {
     assert(PRECEDENCE_MAP[operator.kind] != null);
   }
 
@@ -976,7 +949,6 @@
 
   ConstantExpression apply(NormalizedArguments arguments) {
     return new UnaryConstantExpression(
-        value,
         operator,
         expression.apply(arguments));
   }
@@ -1002,15 +974,54 @@
   };
 }
 
+
+/// A string length constant expression like `a.length`.
+class StringLengthConstantExpression extends ConstantExpression {
+  final ConstantExpression expression;
+
+  StringLengthConstantExpression(this.expression);
+
+  ConstantExpressionKind get kind => ConstantExpressionKind.STRING_LENGTH;
+
+  accept(ConstantExpressionVisitor visitor, [context]) {
+    return visitor.visitStringLength(this, context);
+  }
+
+  @override
+  ConstantValue evaluate(Environment environment,
+                         ConstantSystem constantSystem) {
+    ConstantValue value = expression.evaluate(environment, constantSystem);
+    if (value.isString) {
+      StringConstantValue stringValue = value;
+      return constantSystem.createInt(stringValue.primitiveValue.length);
+    }
+    return new NonConstantValue();
+  }
+
+  ConstantExpression apply(NormalizedArguments arguments) {
+    return new StringLengthConstantExpression(expression.apply(arguments));
+  }
+
+  int get precedence => 15;
+
+  @override
+  int _computeHashCode() {
+    return 23 * expression.hashCode;
+  }
+
+  @override
+  bool _equals(StringLengthConstantExpression other) {
+    return expression == other.expression;
+  }
+}
+
 /// A constant conditional expression like `a ? b : c`.
 class ConditionalConstantExpression extends ConstantExpression {
-  final ConstantValue value;
   final ConstantExpression condition;
   final ConstantExpression trueExp;
   final ConstantExpression falseExp;
 
-  ConditionalConstantExpression(this.value,
-                                this.condition,
+  ConditionalConstantExpression(this.condition,
                                 this.trueExp,
                                 this.falseExp);
 
@@ -1022,7 +1033,6 @@
 
   ConstantExpression apply(NormalizedArguments arguments) {
     return new ConditionalConstantExpression(
-        value,
         condition.apply(arguments),
         trueExp.apply(arguments),
         falseExp.apply(arguments));
@@ -1077,10 +1087,6 @@
     return visitor.visitPositional(this, context);
   }
 
-  ConstantValue get value {
-    throw new UnsupportedError('PositionalArgumentReference.value');
-  }
-
   ConstantExpression apply(NormalizedArguments arguments) {
     return arguments.getPositionalArgument(index);
   }
@@ -1112,10 +1118,6 @@
     return visitor.visitNamed(this, context);
   }
 
-  ConstantValue get value {
-    throw new UnsupportedError('NamedArgumentReference.value');
-  }
-
   ConstantExpression apply(NormalizedArguments arguments) {
     return arguments.getNamedArgument(name);
   }
@@ -1134,11 +1136,10 @@
 }
 
 abstract class FromEnvironmentConstantExpression extends ConstantExpression {
-  final ConstantValue value;
-  final String name;
+  final ConstantExpression name;
   final ConstantExpression defaultValue;
 
-  FromEnvironmentConstantExpression(this.value, this.name, this.defaultValue);
+  FromEnvironmentConstantExpression(this.name, this.defaultValue);
 
   @override
   int _computeHashCode() {
@@ -1158,10 +1159,9 @@
     extends FromEnvironmentConstantExpression {
 
   BoolFromEnvironmentConstantExpression(
-      ConstantValue value,
-      String name,
+      ConstantExpression name,
       ConstantExpression defaultValue)
-      : super(value, name, defaultValue);
+      : super(name, defaultValue);
 
   ConstantExpressionKind get kind {
     return ConstantExpressionKind.BOOL_FROM_ENVIRONMENT;
@@ -1174,19 +1174,34 @@
   @override
   ConstantValue evaluate(Environment environment,
                          ConstantSystem constantSystem) {
-    String text = environment.readFromEnvironment(name);
+    ConstantValue nameConstantValue =
+        name.evaluate(environment, constantSystem);
+    ConstantValue defaultConstantValue;
+    if (defaultValue != null) {
+      defaultConstantValue =
+          defaultValue.evaluate(environment, constantSystem);
+    } else {
+      defaultConstantValue = constantSystem.createBool(false);
+    }
+    if (!nameConstantValue.isString) {
+      return new NonConstantValue();
+    }
+    StringConstantValue nameStringConstantValue = nameConstantValue;
+    String text = environment.readFromEnvironment(
+        nameStringConstantValue.primitiveValue.slowToString());
     if (text == 'true') {
       return constantSystem.createBool(true);
     } else if (text == 'false') {
       return constantSystem.createBool(false);
     } else {
-      return defaultValue.evaluate(environment, constantSystem);
+      return defaultConstantValue;
     }
   }
 
   ConstantExpression apply(NormalizedArguments arguments) {
     return new BoolFromEnvironmentConstantExpression(
-        null, name, defaultValue.apply(arguments));
+        name.apply(arguments),
+        defaultValue != null ? defaultValue.apply(arguments) : null);
   }
 }
 
@@ -1195,10 +1210,9 @@
     extends FromEnvironmentConstantExpression {
 
   IntFromEnvironmentConstantExpression(
-      ConstantValue value,
-      String name,
+      ConstantExpression name,
       ConstantExpression defaultValue)
-      : super(value, name, defaultValue);
+      : super(name, defaultValue);
 
   ConstantExpressionKind get kind {
     return ConstantExpressionKind.INT_FROM_ENVIRONMENT;
@@ -1211,13 +1225,27 @@
   @override
   ConstantValue evaluate(Environment environment,
                          ConstantSystem constantSystem) {
+    ConstantValue nameConstantValue =
+        name.evaluate(environment, constantSystem);
+    ConstantValue defaultConstantValue;
+    if (defaultValue != null) {
+      defaultConstantValue =
+          defaultValue.evaluate(environment, constantSystem);
+    } else {
+      defaultConstantValue = constantSystem.createNull();
+    }
+    if (!nameConstantValue.isString) {
+      return new NonConstantValue();
+    }
+    StringConstantValue nameStringConstantValue = nameConstantValue;
+    String text = environment.readFromEnvironment(
+        nameStringConstantValue.primitiveValue.slowToString());
     int value;
-    String text = environment.readFromEnvironment(name);
     if (text != null) {
       value = int.parse(text, onError: (_) => null);
     }
     if (value == null) {
-      return defaultValue.evaluate(environment, constantSystem);
+      return defaultConstantValue;
     } else {
       return constantSystem.createInt(value);
     }
@@ -1225,7 +1253,8 @@
 
   ConstantExpression apply(NormalizedArguments arguments) {
     return new IntFromEnvironmentConstantExpression(
-        null, name, defaultValue.apply(arguments));
+        name.apply(arguments),
+        defaultValue != null ? defaultValue.apply(arguments) : null);
   }
 }
 
@@ -1234,10 +1263,9 @@
     extends FromEnvironmentConstantExpression {
 
   StringFromEnvironmentConstantExpression(
-      ConstantValue value,
-      String name,
+      ConstantExpression name,
       ConstantExpression defaultValue)
-      : super(value, name, defaultValue);
+      : super(name, defaultValue);
 
   ConstantExpressionKind get kind {
     return ConstantExpressionKind.STRING_FROM_ENVIRONMENT;
@@ -1250,9 +1278,23 @@
   @override
   ConstantValue evaluate(Environment environment,
                          ConstantSystem constantSystem) {
-    String text = environment.readFromEnvironment(name);
+    ConstantValue nameConstantValue =
+        name.evaluate(environment, constantSystem);
+    ConstantValue defaultConstantValue;
+    if (defaultValue != null) {
+      defaultConstantValue =
+          defaultValue.evaluate(environment, constantSystem);
+    } else {
+      defaultConstantValue = constantSystem.createNull();
+    }
+    if (!nameConstantValue.isString) {
+      return new NonConstantValue();
+    }
+    StringConstantValue nameStringConstantValue = nameConstantValue;
+    String text = environment.readFromEnvironment(
+        nameStringConstantValue.primitiveValue.slowToString());
     if (text == null) {
-      return defaultValue.evaluate(environment, constantSystem);
+      return defaultConstantValue;
     } else {
       return constantSystem.createString(new DartString.literal(text));
     }
@@ -1260,18 +1302,18 @@
 
   ConstantExpression apply(NormalizedArguments arguments) {
     return new StringFromEnvironmentConstantExpression(
-        null, name, defaultValue.apply(arguments));
+        name.apply(arguments),
+        defaultValue != null ? defaultValue.apply(arguments) : null);
   }
 }
 
 /// A constant expression referenced with a deferred prefix.
 /// For example `lib.C`.
 class DeferredConstantExpression extends ConstantExpression {
-  final ConstantValue value;
   final ConstantExpression expression;
   final PrefixElement prefix;
 
-  DeferredConstantExpression(this.value, this.expression, this.prefix);
+  DeferredConstantExpression(this.expression, this.prefix);
 
   ConstantExpressionKind get kind => ConstantExpressionKind.DEFERRED;
 
@@ -1286,6 +1328,11 @@
     return 13 * expression.hashCode;
   }
 
+  ConstantExpression apply(NormalizedArguments arguments) {
+    return new DeferredConstantExpression(
+        expression.apply(arguments), prefix);
+  }
+
   @override
   bool _equals(DeferredConstantExpression other) {
     return expression == other.expression;
@@ -1320,6 +1367,7 @@
   R visitBinary(BinaryConstantExpression exp, A context);
   R visitIdentical(IdenticalConstantExpression exp, A context);
   R visitUnary(UnaryConstantExpression exp, A context);
+  R visitStringLength(StringLengthConstantExpression exp, A context);
   R visitConditional(ConditionalConstantExpression exp, A context);
   R visitBoolFromEnvironment(BoolFromEnvironmentConstantExpression exp,
                              A context);
@@ -1346,8 +1394,8 @@
   final StringBuffer sb = new StringBuffer();
 
   void write(ConstantExpression parent,
-        ConstantExpression child,
-        {bool leftAssociative: true}) {
+             ConstantExpression child,
+             {bool leftAssociative: true}) {
     if (child.precedence < parent.precedence ||
         !leftAssociative && child.precedence == parent.precedence) {
       sb.write('(');
@@ -1443,11 +1491,11 @@
   void visitConstructed(ConstructedConstantExpression exp, [_]) {
     sb.write('const ');
     sb.write(exp.target.enclosingClass.name);
+    writeTypeArguments(exp.type);
     if (exp.target.name != '') {
       sb.write('.');
       sb.write(exp.target.name);
     }
-    writeTypeArguments(exp.type);
     sb.write('(');
     bool needsComma = false;
 
@@ -1473,7 +1521,20 @@
 
   @override
   void visitConcatenate(ConcatenateConstantExpression exp, [_]) {
-    sb.write(exp.value.unparse());
+    sb.write('"');
+    for (ConstantExpression expression in exp.expressions) {
+      if (expression.kind == ConstantExpressionKind.STRING) {
+        StringConstantExpression string = expression;
+        // TODO(johnniwinther): Ensure correct escaping.
+        sb.write('${string.primitiveValue}');
+      } else {
+        sb.write(r"${");
+        visit(expression);
+        sb.write("}");
+      }
+
+    }
+    sb.write('"');
   }
 
   @override
@@ -1530,6 +1591,12 @@
   }
 
   @override
+  void visitStringLength(StringLengthConstantExpression exp, [_]) {
+    write(exp, exp.expression, leftAssociative: false);
+    sb.write('.length');
+  }
+
+  @override
   void visitConditional(ConditionalConstantExpression exp, [_]) {
     write(exp, exp.condition, leftAssociative: false);
     sb.write(' ? ');
@@ -1560,23 +1627,35 @@
   @override
   void visitBoolFromEnvironment(BoolFromEnvironmentConstantExpression exp,
                                 [_]) {
-    sb.write('const bool.fromEnvironment("${exp.name}", defaultValue: ');
-    visit(exp.defaultValue);
+    sb.write('const bool.fromEnvironment(');
+    visit(exp.name);
+    if (exp.defaultValue != null) {
+      sb.write(', defaultValue: ');
+      visit(exp.defaultValue);
+    }
     sb.write(')');
   }
 
   @override
   void visitIntFromEnvironment(IntFromEnvironmentConstantExpression exp, [_]) {
-    sb.write('const int.fromEnvironment("${exp.name}", defaultValue: ');
-    visit(exp.defaultValue);
+    sb.write('const int.fromEnvironment(');
+    visit(exp.name);
+    if (exp.defaultValue != null) {
+      sb.write(', defaultValue: ');
+      visit(exp.defaultValue);
+    }
     sb.write(')');
   }
 
   @override
   void visitStringFromEnvironment(StringFromEnvironmentConstantExpression exp,
                                   [_]) {
-    sb.write('const String.fromEnvironment("${exp.name}", defaultValue: ');
-    visit(exp.defaultValue);
+    sb.write('const String.fromEnvironment(');
+    visit(exp.name);
+    if (exp.defaultValue != null) {
+      sb.write(', defaultValue: ');
+      visit(exp.defaultValue);
+    }
     sb.write(')');
   }
 
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
index 4300917..0ea0217 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
@@ -4,9 +4,10 @@
 
 library dart2js.ir_builder;
 
+import '../compile_time_constants.dart' show BackendConstantEnvironment;
 import '../constants/constant_system.dart';
 import '../constants/expressions.dart';
-import '../constants/values.dart' show PrimitiveConstantValue;
+import '../constants/values.dart' show ConstantValue, PrimitiveConstantValue;
 import '../dart_types.dart';
 import '../dart2jslib.dart';
 import '../elements/elements.dart';
@@ -384,7 +385,9 @@
 
 /// Shared state between delimited IrBuilders within the same function.
 class IrBuilderSharedState {
-  final ConstantSystem constantSystem;
+  final BackendConstantEnvironment constants;
+
+  ConstantSystem get constantSystem => constants.constantSystem;
 
   /// A stack of collectors for breaks.
   final List<JumpCollector> breakCollectors = <JumpCollector>[];
@@ -402,7 +405,7 @@
 
   final List<ir.Parameter> functionParameters = <ir.Parameter>[];
 
-  IrBuilderSharedState(this.constantSystem, this.currentElement);
+  IrBuilderSharedState(this.constants, this.currentElement);
 
   ir.Parameter get thisParameter => _thisParameter;
   void set thisParameter(ir.Parameter value) {
@@ -548,8 +551,9 @@
   ir.Expression _current = null;
 
   /// Initialize a new top-level IR builder.
-  void _init(ConstantSystem constantSystem, ExecutableElement currentElement) {
-    state = new IrBuilderSharedState(constantSystem, currentElement);
+  void _init(BackendConstantEnvironment constants,
+             ExecutableElement currentElement) {
+    state = new IrBuilderSharedState(constants, currentElement);
     environment = new Environment.empty();
     mutableVariables = <Local, ir.MutableVariable>{};
   }
@@ -668,50 +672,53 @@
 
 
   /// Create a [ir.Constant] from [constant] and add it to the CPS term.
-  ir.Constant buildConstant(ConstantExpression constant) {
+  // TODO(johnniwinther): Remove [value] when [ConstantValue] can be computed
+  // directly from [constant].
+  ir.Constant buildConstant(ConstantExpression constant, ConstantValue value) {
     assert(isOpen);
-    return addPrimitive(new ir.Constant(constant));
+    return addPrimitive(new ir.Constant(constant, value));
   }
 
   /// Create an integer constant and add it to the CPS term.
   ir.Constant buildIntegerConstant(int value) {
-    return buildConstant(new IntConstantExpression(
-        value,
-        state.constantSystem.createInt(value)));
+    return buildConstant(
+        new IntConstantExpression(value),
+        state.constantSystem.createInt(value));
   }
 
   /// Create a double constant and add it to the CPS term.
   ir.Constant buildDoubleConstant(double value) {
-    return buildConstant(new DoubleConstantExpression(
-        value,
-        state.constantSystem.createDouble(value)));
+    return buildConstant(
+        new DoubleConstantExpression(value),
+        state.constantSystem.createDouble(value));
   }
 
   /// Create a Boolean constant and add it to the CPS term.
   ir.Constant buildBooleanConstant(bool value) {
-    return buildConstant(new BoolConstantExpression(
-        value,
-        state.constantSystem.createBool(value)));
+    return buildConstant(
+        new BoolConstantExpression(value),
+        state.constantSystem.createBool(value));
   }
 
   /// Create a null constant and add it to the CPS term.
   ir.Constant buildNullConstant() {
-    return buildConstant(new NullConstantExpression(
-        state.constantSystem.createNull()));
+    return buildConstant(
+        new NullConstantExpression(),
+        state.constantSystem.createNull());
   }
 
   /// Create a string constant and add it to the CPS term.
   ir.Constant buildStringConstant(String value) {
-    return buildConstant(new StringConstantExpression(
-        value,
-        state.constantSystem.createString(new ast.DartString.literal(value))));
+    return buildConstant(
+        new StringConstantExpression(value),
+        state.constantSystem.createString(new ast.DartString.literal(value)));
   }
 
   /// Create a string constant and add it to the CPS term.
   ir.Constant buildDartStringConstant(ast.DartString value) {
-    return buildConstant(new StringConstantExpression(
-        value.slowToString(),
-        state.constantSystem.createString(value)));
+    return buildConstant(
+        new StringConstantExpression(value.slowToString()),
+        state.constantSystem.createString(value));
   }
 
   /// Creates a non-constant list literal of the provided [type] and with the
@@ -1918,9 +1925,9 @@
     ir.Continuation elseContinuation = new ir.Continuation([]);
 
     ir.Constant makeBoolConstant(bool value) {
-      return new ir.Constant(new BoolConstantExpression(
-          value,
-          state.constantSystem.createBool(value)));
+      return new ir.Constant(
+          new BoolConstantExpression(value),
+          state.constantSystem.createBool(value));
     }
 
     ir.Constant trueConstant = makeBoolConstant(true);
@@ -2055,10 +2062,10 @@
   IrBuilder _makeInstance() => new JsIrBuilder._blank(program, jsState);
   JsIrBuilder._blank(this.program, this.jsState);
 
-  JsIrBuilder(this.program, ConstantSystem constantSystem,
+  JsIrBuilder(this.program, BackendConstantEnvironment constants,
       ExecutableElement currentElement)
       : jsState = new JsIrBuilderSharedState() {
-    _init(constantSystem, currentElement);
+    _init(constants, currentElement);
   }
 
   void enterInitializers() {
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
index b311280..c075b77 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
@@ -22,87 +22,59 @@
 import 'cps_ir_nodes.dart' as ir;
 import 'cps_ir_builder.dart';
 
-/**
- * This task iterates through all resolved elements and builds [ir.Node]s. The
- * nodes are stored in the [nodes] map and accessible through [hasIr] and
- * [getIr].
- *
- * The functionality of the IrNodes is added gradually, therefore elements might
- * have an IR or not, depending on the language features that are used. For
- * elements that do have an IR, the tree [ast.Node]s and the [Token]s are not
- * used in the rest of the compilation. This is ensured by setting the element's
- * cached tree to `null` and also breaking the token stream to crash future
- * attempts to parse.
- *
- * The type inferrer works on either IR nodes or tree nodes. The IR nodes are
- * then translated into the SSA form for optimizations and code generation.
- * Long-term, once the IR supports the full language, the backend can be
- * re-implemented to work directly on the IR.
- */
+typedef void IrBuilderCallback(Element element, ir.FunctionDefinition irNode);
+
+/// This task provides the interface to build IR nodes from [ast.Node]s, which
+/// is used from the [CpsFunctionCompiler] to generate code.
+///
+/// This class is mainly there to correctly measure how long building the IR
+/// takes.
 class IrBuilderTask extends CompilerTask {
-  final Map<Element, ir.FunctionDefinition> nodes =
-      <Element, ir.FunctionDefinition>{};
   final SourceInformationFactory sourceInformationFactory;
 
   String bailoutMessage = null;
 
-  IrBuilderTask(Compiler compiler, this.sourceInformationFactory)
+  /// If not null, this function will be called with for each
+  /// [ir.FunctionDefinition] node that has been built.
+  IrBuilderCallback builderCallback;
+
+  IrBuilderTask(Compiler compiler, this.sourceInformationFactory,
+      [this.builderCallback])
       : super(compiler);
 
   String get name => 'IR builder';
 
-  bool hasIr(Element element) => nodes.containsKey(element.implementation);
-
-  ir.FunctionDefinition getIr(ExecutableElement element) {
-    return nodes[element.implementation];
-  }
-
   ir.FunctionDefinition buildNode(AstElement element) {
-    return measure(() => _buildNode(element));
-  }
+    return measure(() {
+      bailoutMessage = null;
 
-  ir.FunctionDefinition _buildNode(AstElement element) {
-    bailoutMessage = null;
+      TreeElements elementsMapping = element.resolvedAst.elements;
+      element = element.implementation;
+      return compiler.withCurrentElement(element, () {
+        SourceInformationBuilder sourceInformationBuilder =
+            sourceInformationFactory.forContext(element);
 
-    TreeElements elementsMapping = element.resolvedAst.elements;
-    element = element.implementation;
-    return compiler.withCurrentElement(element, () {
-      SourceInformationBuilder sourceInformationBuilder =
-          sourceInformationFactory.forContext(element);
-
-      IrBuilderVisitor builder =
-          new JsIrBuilderVisitor(
-              elementsMapping, compiler, sourceInformationBuilder);
-      ir.FunctionDefinition irNode = builder.buildExecutable(element);
-      if (irNode == null) {
-        bailoutMessage = builder.bailoutMessage;
-      } else {
-        nodes[element] = irNode;
-      }
-      return irNode;
+        IrBuilderVisitor builder =
+            new JsIrBuilderVisitor(
+                elementsMapping, compiler, sourceInformationBuilder);
+        ir.FunctionDefinition irNode = builder.buildExecutable(element);
+        if (irNode == null) {
+          bailoutMessage = builder.bailoutMessage;
+        } else if (builderCallback != null) {
+          builderCallback(element, irNode);
+        }
+        return irNode;
+      });
     });
   }
-
-  void buildNodes() {
-    measure(() {
-      Set<Element> resolved = compiler.enqueuer.resolution.resolvedElements;
-      resolved.forEach(buildNode);
-    });
-  }
-
-  bool get inCheckedMode {
-    bool result = false;
-    assert((result = true));
-    return result;
-  }
-
 }
 
-/**
- * A tree visitor that builds [IrNodes]. The visit methods add statements using
- * to the [builder] and return the last added statement for trees that represent
- * an expression.
- */
+
+/// A tree visitor that builds [ir.Node]s.
+///
+/// The visit methods add statements using the [irBuilder] and return the last
+/// added statement for trees that represent expressions.
+///
 // TODO(johnniwinther): Implement [SemanticDeclVisitor].
 abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
     with IrBuilderMixin<ast.Node>,
@@ -469,7 +441,7 @@
 
   ConstantExpression getConstantForNode(ast.Node node) {
     ConstantExpression constant =
-        compiler.backend.constants.getConstantForNode(node, elements);
+        irBuilder.state.constants.getConstantForNode(node, elements);
     assert(invariant(node, constant != null,
         message: 'No constant computed for $node'));
     return constant;
@@ -477,12 +449,20 @@
 
   ConstantExpression getConstantForVariable(VariableElement element) {
     ConstantExpression constant =
-        compiler.backend.constants.getConstantForVariable(element);
+        irBuilder.state.constants.getConstantForVariable(element);
     assert(invariant(element, constant != null,
             message: 'No constant computed for $element'));
     return constant;
   }
 
+  /// Builds a constant pulling the value from the constant environment.
+  // TODO(johnniwinther): Remove this when [IrBuilder.buildConstant] only takes
+  // a [ConstantExpression].
+  ir.Primitive buildConstant(ConstantExpression expression) {
+    return irBuilder.buildConstant(expression,
+        irBuilder.state.constants.getConstantValue(expression));
+  }
+
   ir.Primitive visitLiteralList(ast.LiteralList node) {
     if (node.isConst) {
       return translateConstant(node);
@@ -577,7 +557,7 @@
   ir.Primitive handleConstantGet(
       ast.Node node,
       ConstantExpression constant, _) {
-    return irBuilder.buildConstant(constant);
+    return buildConstant(constant);
   }
 
   /// If [node] is null, returns this.
@@ -614,7 +594,7 @@
       ast.Send node,
       ConstantExpression constant,
       _) {
-    return irBuilder.buildConstant(constant);
+    return buildConstant(constant);
   }
 
   @override
@@ -623,7 +603,7 @@
       LocalVariableElement element,
       _) {
     return element.isConst
-        ? irBuilder.buildConstant(getConstantForVariable(element))
+        ? buildConstant(getConstantForVariable(element))
         : irBuilder.buildLocalVariableGet(element);
   }
 
@@ -930,7 +910,7 @@
       ast.NodeList arguments,
       CallStructure callStructure,
       _) {
-    ir.Primitive target = irBuilder.buildConstant(constant);
+    ir.Primitive target = buildConstant(constant);
     return translateCallInvoke(target, arguments, callStructure);
   }
 
@@ -1267,7 +1247,7 @@
       CompoundRhs rhs,
       arg) {
     return translateCompounds(
-        getValue: () => irBuilder.buildConstant(constant),
+        getValue: () => buildConstant(constant),
         rhs: rhs,
         setValue: (value) {}); // The binary operator will throw before this.
   }
@@ -1510,7 +1490,7 @@
 
   ir.Primitive translateConstant(ast.Node node) {
     assert(irBuilder.isOpen);
-    return irBuilder.buildConstant(getConstantForNode(node));
+    return buildConstant(getConstantForNode(node));
   }
 
   ir.Primitive visitThrow(ast.Throw node) {
@@ -1578,6 +1558,17 @@
   }
 
   @override
+  ir.Primitive visitConstructorIncompatibleInvoke(
+      ast.NewExpression node,
+      Element constructor,
+      DartType type,
+      ast.NodeList arguments,
+      CallStructure callStructure, _) {
+    return buildStaticNoSuchMethod(elements.getSelector(node.send),
+        translateDynamicArguments(arguments, callStructure));
+  }
+
+  @override
   ir.Primitive errorNonConstantConstructorInvoke(
       ast.NewExpression node,
       Element element,
@@ -2244,7 +2235,7 @@
   JsIrBuilder getBuilderFor(Element element) {
     return new JsIrBuilder(
         new GlobalProgramInformation(compiler),
-        compiler.backend.constantSystem,
+        compiler.backend.constants,
         element);
   }
 
@@ -2800,7 +2791,7 @@
     ConstantExpression constant =
         backend.constants.getConstantForVariable(field);
     if (constant != null && !field.isAssignable) {
-      return irBuilder.buildConstant(constant);
+      return buildConstant(constant);
     } else if (backend.constants.lazyStatics.contains(field)) {
       return irBuilder.buildStaticFieldLazyGet(field, src);
     } else {
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
index d052121..0bb7ecc 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
@@ -269,6 +269,11 @@
   final Reference<Continuation> continuation;
   final SourceInformation sourceInformation;
 
+  /// If true, it is known that the receiver cannot be `null`.
+  ///
+  /// This field is `null` until initialized by optimization phases.
+  bool receiverIsNotNull;
+
   InvokeMethod(Primitive receiver,
                this.selector,
                List<Primitive> arguments,
@@ -670,10 +675,9 @@
 
 class Constant extends Primitive {
   final ConstantExpression expression;
+  final values.ConstantValue value;
 
-  Constant(this.expression);
-
-  values.ConstantValue get value => expression.value;
+  Constant(this.expression, this.value);
 
   accept(Visitor visitor) => visitor.visitConstant(this);
 }
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart
index b4bbcdc..ed8d685 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart
@@ -203,8 +203,7 @@
   }
 
   String visitConstant(Constant node) {
-    String value =
-        node.expression.value.accept(new ConstantStringifier(), null);
+    String value = node.value.accept(new ConstantStringifier(), null);
     return '(Constant $value)';
   }
 
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart
index 74d973e..c0097e9 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart
@@ -254,7 +254,7 @@
   String formatPrimitive(cps_ir.Primitive p) => visit(p);
 
   visitConstant(cps_ir.Constant node) {
-    return "Constant ${node.expression.value.toStructuredString()}";
+    return "Constant ${node.value.toStructuredString()}";
   }
 
   visitParameter(cps_ir.Parameter node) {
diff --git a/pkg/compiler/lib/src/cps_ir/type_propagation.dart b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
index 87f9abe..b9db352 100644
--- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart
+++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
@@ -28,15 +28,22 @@
   T get stringType;
   T get listType;
   T get mapType;
+  T get nonNullType;
 
   T getReturnType(FunctionElement element);
   T getSelectorReturnType(Selector selector);
   T getParameterType(ParameterElement element);
+  T getFieldType(FieldElement element);
   T join(T a, T b);
-  T typeOf(ConstantValue constant);
+  T exact(ClassElement element);
+  T getTypeOf(ConstantValue constant);
+
+  bool areDisjoint(T leftType, T rightType);
 
   /// True if all values satisfying [type] are booleans (null is not a boolean).
   bool isDefinitelyBool(T type);
+
+  bool isDefinitelyNotNull(T type);
 }
 
 class UnitTypeSystem implements TypeSystem<String> {
@@ -50,14 +57,23 @@
   get mapType => UNIT;
   get stringType => UNIT;
   get typeType => UNIT;
+  get nonNullType => UNIT;
 
   getParameterType(_) => UNIT;
   getReturnType(_) => UNIT;
   getSelectorReturnType(_) => UNIT;
+  getFieldType(_) => UNIT;
   join(a, b) => UNIT;
-  typeOf(_) => UNIT;
+  exact(_) => UNIT;
+  getTypeOf(_) => UNIT;
 
   bool isDefinitelyBool(_) => false;
+
+  bool isDefinitelyNotNull(_) => false;
+
+  bool areDisjoint(String leftType, String rightType) {
+    return false;
+  }
 }
 
 class TypeMaskSystem implements TypeSystem<TypeMask> {
@@ -72,6 +88,7 @@
   TypeMask get stringType => inferrer.stringType;
   TypeMask get listType => inferrer.listType;
   TypeMask get mapType => inferrer.mapType;
+  TypeMask get nonNullType => inferrer.nonNullType;
 
   // TODO(karlklose): remove compiler here.
   TypeMaskSystem(dart2js.Compiler compiler)
@@ -90,19 +107,39 @@
     return inferrer.getGuaranteedTypeOfSelector(selector);
   }
 
+  TypeMask getFieldType(FieldElement field) {
+    return inferrer.getGuaranteedTypeOfElement(field);
+  }
+
   @override
   TypeMask join(TypeMask a, TypeMask b) {
     return a.union(b, classWorld);
   }
 
   @override
-  TypeMask typeOf(ConstantValue constant) {
+  TypeMask getTypeOf(ConstantValue constant) {
     return computeTypeMask(inferrer.compiler, constant);
   }
 
+  TypeMask exact(ClassElement element) {
+    // The class world does not know about classes created by
+    // closure conversion, so just treat those as a subtypes of Function.
+    // TODO(asgerf): Maybe closure conversion should create a new ClassWorld?
+    if (element.isClosure) return functionType;
+    return new TypeMask.exact(element, classWorld);
+  }
+
   bool isDefinitelyBool(TypeMask t) {
     return t.containsOnlyBool(classWorld) && !t.isNullable;
   }
+
+  bool isDefinitelyNotNull(TypeMask t) => !t.isNullable;
+
+  @override
+  bool areDisjoint(TypeMask leftType, TypeMask rightType) {
+    TypeMask intersection = leftType.intersection(rightType, classWorld);
+    return intersection.isEmpty && !intersection.isNullable;
+  }
 }
 
 /**
@@ -197,7 +234,7 @@
     PrimitiveConstantValue primitiveConstant = value.constant;
     ConstantExpression constExp =
         const ConstantExpressionCreator().convert(primitiveConstant);
-    Constant constant = new Constant(constExp);
+    Constant constant = new Constant(constExp, primitiveConstant);
     LetPrim letPrim = new LetPrim(constant);
     InvokeContinuation invoke =
         new InvokeContinuation(continuation, <Primitive>[constant]);
@@ -274,6 +311,8 @@
     });
 
     if (letPrim == null) {
+      _AbstractValue<T> receiver = getValue(node.receiver.definition);
+      node.receiverIsNotNull = receiver.isDefinitelyNotNull(typeSystem);
       super.visitInvokeMethod(node);
     } else {
       visitLetPrim(letPrim);
@@ -453,7 +492,8 @@
 
   void visitFunctionDefinition(FunctionDefinition node) {
     if (node.thisParameter != null) {
-      setValue(node.thisParameter, nonConstant());
+      // TODO(asgerf): Use a more precise type for 'this'.
+      setValue(node.thisParameter, nonConstant(typeSystem.nonNullType));
     }
     node.parameters.forEach(visit);
     setReachable(node.body);
@@ -575,7 +615,7 @@
     if (result == null) {
       setValues(nonConstant());
     } else {
-      T type = typeSystem.typeOf(result);
+      T type = typeSystem.getTypeOf(result);
       setValues(constantValue(result, type));
     }
    }
@@ -596,7 +636,7 @@
 
     assert(cont.parameters.length == 1);
     Parameter returnValue = cont.parameters[0];
-    setValue(returnValue, nonConstant());
+    setValue(returnValue, nonConstant(typeSystem.getReturnType(node.target)));
   }
 
   void visitConcatenateStrings(ConcatenateStrings node) {
@@ -735,7 +775,7 @@
 
   void visitConstant(Constant node) {
     ConstantValue value = node.value;
-    setValue(node, constantValue(value, typeSystem.typeOf(value)));
+    setValue(node, constantValue(value, typeSystem.getTypeOf(value)));
   }
 
   void visitCreateFunction(CreateFunction node) {
@@ -794,7 +834,11 @@
   }
 
   void visitGetStatic(GetStatic node) {
-    setValue(node, nonConstant());
+    if (node.element.isFunction) {
+      setValue(node, nonConstant(typeSystem.functionType));
+    } else {
+      setValue(node, nonConstant(typeSystem.getFieldType(node.element)));
+    }
   }
 
   void visitSetStatic(SetStatic node) {
@@ -807,7 +851,7 @@
 
     assert(cont.parameters.length == 1);
     Parameter returnValue = cont.parameters[0];
-    setValue(returnValue, nonConstant());
+    setValue(returnValue, nonConstant(typeSystem.getFieldType(node.element)));
   }
 
   void visitIsTrue(IsTrue node) {
@@ -826,7 +870,12 @@
     } else if (!leftConst.isConstant || !rightConst.isConstant) {
       T leftType = leftConst.type;
       T rightType = rightConst.type;
-      setValue(node, nonConstant(typeSystem.boolType));
+      if (typeSystem.areDisjoint(leftType, rightType)) {
+        setValue(node,
+            constantValue(new FalseConstantValue(), typeSystem.boolType));
+      } else {
+        setValue(node, nonConstant(typeSystem.boolType));
+      }
     } else if (leftValue.isPrimitive && rightValue.isPrimitive) {
       assert(leftConst.isConstant && rightConst.isConstant);
       PrimitiveConstantValue left = leftValue;
@@ -841,12 +890,12 @@
     setReachable(node.input.definition);
     _AbstractValue<T> value = getValue(node.input.definition);
     if (!value.isNothing) {
-      setValue(node, nonConstant());
+      setValue(node, nonConstant(typeSystem.nonNullType));
     }
   }
 
   void visitGetField(GetField node) {
-    setValue(node, nonConstant());
+    setValue(node, nonConstant(typeSystem.getFieldType(node.field)));
   }
 
   void visitSetField(SetField node) {
@@ -854,11 +903,11 @@
   }
 
   void visitCreateBox(CreateBox node) {
-    setValue(node, nonConstant());
+    setValue(node, nonConstant(typeSystem.nonNullType));
   }
 
   void visitCreateInstance(CreateInstance node) {
-    setValue(node, nonConstant());
+    setValue(node, nonConstant(typeSystem.exact(node.classElement)));
   }
 
   void visitReifyRuntimeType(ReifyRuntimeType node) {
@@ -879,7 +928,8 @@
   }
 
   void visitCreateInvocationMirror(CreateInvocationMirror node) {
-    setValue(node, nonConstant());
+    // TODO(asgerf): Expose [Invocation] type.
+    setValue(node, nonConstant(typeSystem.nonNullType));
   }
 }
 
@@ -960,6 +1010,13 @@
     if (kind == NOTHING) return true;
     return typeSystem.isDefinitelyBool(type);
   }
+
+  /// True if null is not a member of this value.
+  bool isDefinitelyNotNull(TypeSystem<T> typeSystem) {
+    if (kind == NOTHING) return true;
+    if (kind == CONSTANT) return !constant.isNull;
+    return typeSystem.isDefinitelyNotNull(type);
+  }
 }
 
 class ConstantExpressionCreator
@@ -971,7 +1028,7 @@
 
   @override
   ConstantExpression visitBool(BoolConstantValue constant, _) {
-    return new BoolConstantExpression(constant.primitiveValue, constant);
+    return new BoolConstantExpression(constant.primitiveValue);
   }
 
   @override
@@ -986,7 +1043,7 @@
 
   @override
   ConstantExpression visitDouble(DoubleConstantValue constant, arg) {
-    return new DoubleConstantExpression(constant.primitiveValue, constant);
+    return new DoubleConstantExpression(constant.primitiveValue);
   }
 
   @override
@@ -1001,7 +1058,7 @@
 
   @override
   ConstantExpression visitInt(IntConstantValue constant, arg) {
-    return new IntConstantExpression(constant.primitiveValue, constant);
+    return new IntConstantExpression(constant.primitiveValue);
   }
 
   @override
@@ -1021,13 +1078,13 @@
 
   @override
   ConstantExpression visitNull(NullConstantValue constant, arg) {
-    return new NullConstantExpression(constant);
+    return new NullConstantExpression();
   }
 
   @override
   ConstantExpression visitString(StringConstantValue constant, arg) {
     return new StringConstantExpression(
-        constant.primitiveValue.slowToString(), constant);
+        constant.primitiveValue.slowToString());
   }
 
   @override
diff --git a/pkg/compiler/lib/src/dart_backend/backend.dart b/pkg/compiler/lib/src/dart_backend/backend.dart
index 78aaeba..7ac9d67 100644
--- a/pkg/compiler/lib/src/dart_backend/backend.dart
+++ b/pkg/compiler/lib/src/dart_backend/backend.dart
@@ -424,18 +424,41 @@
 
   String get name => 'ConstantHandler';
 
+  @override
+  ConstantSystem get constantSystem => constantCompiler.constantSystem;
+
+  @override
+  ConstantValue getConstantValue(ConstantExpression expression) {
+    return constantCompiler.getConstantValue(expression);
+  }
+
+  @override
+  ConstantValue getConstantValueForVariable(VariableElement element) {
+    return constantCompiler.getConstantValueForVariable(element);
+  }
+
+  @override
   ConstantExpression getConstantForVariable(VariableElement element) {
     return constantCompiler.getConstantForVariable(element);
   }
 
+  @override
   ConstantExpression getConstantForNode(Node node, TreeElements elements) {
     return constantCompiler.getConstantForNode(node, elements);
   }
 
-  ConstantExpression getConstantForMetadata(MetadataAnnotation metadata) {
-    return metadata.constant;
+  @override
+  ConstantValue getConstantValueForNode(Node node, TreeElements elements) {
+    return getConstantValue(
+        constantCompiler.getConstantForNode(node, elements));
   }
 
+  @override
+  ConstantValue getConstantValueForMetadata(MetadataAnnotation metadata) {
+    return getConstantValue(metadata.constant);
+  }
+
+  @override
   ConstantExpression compileConstant(VariableElement element) {
     return measure(() {
       return constantCompiler.compileConstant(element);
@@ -448,21 +471,34 @@
     });
   }
 
-  ConstantExpression compileNode(Node node, TreeElements elements,
-                                 {bool enforceConst: true}) {
+  @override
+  ConstantExpression compileNode(
+      Node node,
+      TreeElements elements,
+      {bool enforceConst: true}) {
     return measure(() {
       return constantCompiler.compileNodeWithDefinitions(node, elements,
           isConst: enforceConst);
     });
   }
 
-  ConstantExpression compileMetadata(MetadataAnnotation metadata,
-                           Node node,
-                           TreeElements elements) {
+  @override
+  ConstantExpression compileMetadata(
+      MetadataAnnotation metadata,
+      Node node,
+      TreeElements elements) {
     return measure(() {
       return constantCompiler.compileMetadata(metadata, node, elements);
     });
   }
+
+  // TODO(johnniwinther): Remove this when values are computed from the
+  // expressions.
+  @override
+  void copyConstantValues(DartConstantTask task) {
+    constantCompiler.constantValueMap.addAll(
+        task.constantCompiler.constantValueMap);
+  }
 }
 
 abstract class ElementAstCreationContext {
diff --git a/pkg/compiler/lib/src/dart_backend/dart_backend.dart b/pkg/compiler/lib/src/dart_backend/dart_backend.dart
index d8221ad..2dbc036 100644
--- a/pkg/compiler/lib/src/dart_backend/dart_backend.dart
+++ b/pkg/compiler/lib/src/dart_backend/dart_backend.dart
@@ -14,6 +14,7 @@
 import '../compile_time_constants.dart';
 import '../constants/constant_system.dart';
 import '../constants/expressions.dart';
+import '../constants/values.dart';
 import '../util/util.dart';
 import '../mirror_renamer/mirror_renamer.dart';
 import 'backend_ast_to_frontend_ast.dart' as backend2frontend;
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index 2b0b7fc..92116b8 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -287,17 +287,17 @@
       treeElements.forEachConstantNode((Node node, _) {
         // Explicitly depend on the backend constants.
         constants.add(
-            backend.constants.getConstantForNode(node, treeElements).value);
+            backend.constants.getConstantValueForNode(node, treeElements));
       });
       elements.addAll(treeElements.otherDependencies);
     }
 
     // TODO(sigurdm): How is metadata on a patch-class handled?
     for (MetadataAnnotation metadata in element.metadata) {
-      ConstantExpression constant =
-          backend.constants.getConstantForMetadata(metadata);
+      ConstantValue constant =
+          backend.constants.getConstantValueForMetadata(metadata);
       if (constant != null) {
-        constants.add(constant.value);
+        constants.add(constant);
       }
     }
 
@@ -491,20 +491,18 @@
       });
 
       for (MetadataAnnotation metadata in library.metadata) {
-        ConstantExpression constant =
-            backend.constants.getConstantForMetadata(metadata);
+        ConstantValue constant =
+            backend.constants.getConstantValueForMetadata(metadata);
         if (constant != null) {
-          _mapConstantDependencies(constant.value,
-                                   deferredImport);
+          _mapConstantDependencies(constant, deferredImport);
         }
       }
       for (LibraryTag tag in library.tags) {
         for (MetadataAnnotation metadata in tag.metadata) {
-          ConstantExpression constant =
-              backend.constants.getConstantForMetadata(metadata);
+          ConstantValue constant =
+              backend.constants.getConstantValueForMetadata(metadata);
           if (constant != null) {
-            _mapConstantDependencies(constant.value,
-                                     deferredImport);
+            _mapConstantDependencies(constant, deferredImport);
           }
         }
       }
@@ -537,10 +535,11 @@
         assert(metadatas != null);
         for (MetadataAnnotation metadata in metadatas) {
           metadata.ensureResolved(compiler);
-          Element element =
-              metadata.constant.value.getType(compiler.coreTypes).element;
+          ConstantValue value =
+              compiler.constants.getConstantValue(metadata.constant);
+          Element element = value.getType(compiler.coreTypes).element;
           if (element == deferredLibraryClass) {
-            ConstructedConstantValue constant = metadata.constant.value;
+            ConstructedConstantValue constant = value;
             StringConstantValue s = constant.fields.values.single;
             result = s.primitiveValue.slowToString();
             break;
@@ -727,8 +726,9 @@
           if (metadataList != null) {
             for (MetadataAnnotation metadata in metadataList) {
               metadata.ensureResolved(compiler);
-              Element element =
-                  metadata.constant.value.getType(compiler.coreTypes).element;
+              ConstantValue value =
+                  compiler.constants.getConstantValue(metadata.constant);
+              Element element = value.getType(compiler.coreTypes).element;
               if (element == deferredLibraryClass) {
                  compiler.reportError(
                      import, MessageKind.DEFERRED_OLD_SYNTAX);
diff --git a/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart b/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
index 6012f86..59372ca 100644
--- a/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
@@ -5,6 +5,7 @@
 library simple_types_inferrer;
 
 import '../closure.dart' show ClosureClassMap, ClosureScope;
+import '../constants/values.dart' show ConstantValue, IntConstantValue;
 import '../cps_ir/cps_ir_nodes.dart' as cps_ir show Node;
 import '../dart_types.dart'
     show DartType, InterfaceType, FunctionType, TypeKind;
@@ -1474,10 +1475,11 @@
                && element.isField
                && Elements.isStaticOrTopLevelField(element)
                && compiler.world.fieldNeverChanges(element)) {
-      var constant =
-          compiler.backend.constants.getConstantForVariable(element);
-      if (constant != null && constant.value.isInt) {
-        return constant.value.primitiveValue;
+      ConstantValue value =
+          compiler.backend.constants.getConstantValueForVariable(element);
+      if (value != null && value.isInt) {
+        IntConstantValue intValue = value;
+        return intValue.primitiveValue;
       }
     }
     return null;
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
index b812859..7d760e5 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
@@ -812,10 +812,9 @@
           if (type is! ListTypeInformation && type is! MapTypeInformation) {
             // For non-container types, the constant handler does
             // constant folding that could give more precise results.
-            ConstantExpression constant = compiler.backend.constants
-                .getConstantForVariable(element);
-            if (constant != null) {
-              ConstantValue value = constant.value;
+            ConstantValue value = compiler.backend.constants
+                .getConstantValueForVariable(element);
+            if (value != null) {
               if (value.isFunction) {
                 FunctionConstantValue functionConstant = value;
                 type = types.allocateClosure(node, functionConstant.element);
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index 0101ab0..b99336b 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -237,7 +237,7 @@
 
   String get patchVersion => USE_NEW_EMITTER ? 'new' : 'old';
 
-  final Annotations annotations = new Annotations();
+  final Annotations annotations;
 
   /// Reference to the internal library to lookup functions to always inline.
   LibraryElement internalLibrary;
@@ -620,6 +620,7 @@
         interceptedElements = new Map<String, Set<Element>>(),
         rti = new RuntimeTypes(compiler),
         specializedGetInterceptors = new Map<String, Set<ClassElement>>(),
+        annotations = new Annotations(compiler),
         super(compiler) {
     emitter = new CodeEmitterTask(compiler, namer, generateSourceMap);
     typeVariableHandler = new TypeVariableHandler(compiler);
@@ -971,7 +972,7 @@
                                 Element annotatedElement,
                                 Registry registry) {
     assert(registry.isForResolution);
-    ConstantValue constant = constants.getConstantForMetadata(metadata).value;
+    ConstantValue constant = constants.getConstantValueForMetadata(metadata);
     registerCompileTimeConstant(constant, registry);
     metadataConstants.add(new Dependency(constant, annotatedElement));
   }
@@ -1400,11 +1401,11 @@
       return const WorldImpact();
     }
     if (kind.category == ElementCategory.VARIABLE) {
-      ConstantExpression initialValue =
-          constants.getConstantForVariable(element);
+      ConstantValue initialValue =
+          constants.getConstantValueForVariable(element);
       if (initialValue != null) {
-        registerCompileTimeConstant(initialValue.value, work.registry);
-        constants.addCompileTimeConstantForEmission(initialValue.value);
+        registerCompileTimeConstant(initialValue, work.registry);
+        constants.addCompileTimeConstantForEmission(initialValue);
         // We don't need to generate code for static or top-level
         // variables. For instance variables, we may need to generate
         // the checked setter.
@@ -1954,7 +1955,7 @@
       for (MetadataAnnotation metadata in element.metadata) {
         metadata.ensureResolved(compiler);
         ConstantValue constant =
-            constants.getConstantForMetadata(metadata).value;
+            constants.getConstantValueForMetadata(metadata);
         constants.addCompileTimeConstantForEmission(constant);
       }
       return true;
@@ -2238,7 +2239,8 @@
       // all metadata but only stuff that potentially would match one
       // of the used meta targets.
       metadata.ensureResolved(compiler);
-      ConstantValue value = metadata.constant.value;
+      ConstantValue value =
+          compiler.constants.getConstantValue(metadata.constant);
       if (value == null) continue;
       DartType type = value.getType(compiler.coreTypes);
       if (metaTargetsUsed.contains(type.element)) return true;
@@ -2536,8 +2538,10 @@
     bool hasNoSideEffects = false;
     for (MetadataAnnotation metadata in element.metadata) {
       metadata.ensureResolved(compiler);
-      if (!metadata.constant.value.isConstructedObject) continue;
-      ObjectConstantValue value = metadata.constant.value;
+      ConstantValue constantValue =
+          compiler.constants.getConstantValue(metadata.constant);
+      if (!constantValue.isConstructedObject) continue;
+      ObjectConstantValue value = constantValue;
       ClassElement cls = value.type.element;
       if (cls == forceInlineClass) {
         hasForceInline = true;
@@ -2672,10 +2676,14 @@
   static final Uri PACKAGE_EXPECT =
       new Uri(scheme: 'package', path: 'expect/expect.dart');
 
+  final Compiler compiler;
+
   ClassElement expectNoInlineClass;
   ClassElement expectTrustTypeAnnotationsClass;
   ClassElement expectAssumeDynamicClass;
 
+  Annotations(this.compiler);
+
   void onLibraryScanned(LibraryElement library) {
     if (library.canonicalUri == PACKAGE_EXPECT) {
       expectNoInlineClass = library.find('NoInline');
@@ -2715,7 +2723,8 @@
     for (Link<MetadataAnnotation> link = element.metadata;
          !link.isEmpty;
          link = link.tail) {
-      ConstantValue value = link.head.constant.value;
+      ConstantValue value =
+          compiler.constants.getConstantValue(link.head.constant);
       if (value.isConstructedObject) {
         ConstructedConstantValue constructedConstant = value;
         if (constructedConstant.type.element == annotationClass) {
diff --git a/pkg/compiler/lib/src/js_backend/codegen/codegen.dart b/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
index ed8c803..b852418 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
@@ -156,8 +156,11 @@
     return name;
   }
 
-  List<js.Expression> visitArguments(List<tree_ir.Expression> arguments) {
-    return arguments.map(visitExpression).toList();
+  List<js.Expression> visitExpressionList(
+      List<tree_ir.Expression> expressions) {
+    return new List<js.Expression>.generate(expressions.length,
+        (int index) => visitExpression(expressions[index]),
+        growable: false);
   }
 
   giveup(tree_ir.Node node,
@@ -173,9 +176,9 @@
 
     js.Expression toString(tree_ir.Expression input) {
       bool useDirectly = input is tree_ir.Constant &&
-          (input.expression.value.isString ||
-           input.expression.value.isInt ||
-           input.expression.value.isBool);
+          (input.value.isString ||
+           input.value.isInt ||
+           input.value.isBool);
       js.Expression value = visitExpression(input);
       if (useDirectly) {
         return value;
@@ -205,11 +208,11 @@
 
   @override
   js.Expression visitConstant(tree_ir.Constant node) {
-    return buildConstant(node.expression.value);
+    return buildConstant(node.value);
   }
 
   js.Expression compileConstant(ParameterElement parameter) {
-    return buildConstant(glue.getConstantForVariable(parameter).value);
+    return buildConstant(glue.getConstantValueForVariable(parameter));
   }
 
   // TODO(karlklose): get rid of the selector argument.
@@ -242,7 +245,7 @@
     registry.registerInstantiatedType(node.type);
     Selector selector = node.selector;
     FunctionElement target = node.target;
-    List<js.Expression> arguments = visitArguments(node.arguments);
+    List<js.Expression> arguments = visitExpressionList(node.arguments);
     return buildStaticInvoke(selector, target, arguments);
   }
 
@@ -269,7 +272,7 @@
     registerMethodInvoke(node);
     return js.propertyCall(visitExpression(node.receiver),
                            glue.invocationName(node.selector),
-                           visitArguments(node.arguments));
+                           visitExpressionList(node.arguments));
   }
 
   @override
@@ -277,7 +280,7 @@
     Selector selector = node.selector;
     assert(selector.isGetter || selector.isSetter || selector.isCall);
     FunctionElement target = node.target;
-    List<js.Expression> arguments = visitArguments(node.arguments);
+    List<js.Expression> arguments = visitExpressionList(node.arguments);
     return buildStaticInvoke(selector, target, arguments,
         sourceInformation: node.sourceInformation);
   }
@@ -291,19 +294,19 @@
       return js.js('#.#(#)',
           [visitExpression(node.receiver),
            glue.instanceMethodName(node.target),
-           visitArguments(node.arguments)]);
+           visitExpressionList(node.arguments)]);
     }
     return js.js('#.#.call(#, #)',
         [glue.prototypeAccess(node.target.enclosingClass),
          glue.invocationName(node.selector),
          visitExpression(node.receiver),
-         visitArguments(node.arguments)]);
+         visitExpressionList(node.arguments)]);
   }
 
   @override
   js.Expression visitLiteralList(tree_ir.LiteralList node) {
     registry.registerInstantiatedClass(glue.listClass);
-    List<js.Expression> entries = node.values.map(visitExpression).toList();
+    List<js.Expression> entries = visitExpressionList(node.values);
     return new js.ArrayInitializer(entries);
   }
 
@@ -351,8 +354,7 @@
   @override
   js.Expression visitTypeOperator(tree_ir.TypeOperator node) {
     js.Expression value = visitExpression(node.value);
-    List<js.Expression> typeArguments =
-        node.typeArguments.map(visitExpression).toList();
+    List<js.Expression> typeArguments = visitExpressionList(node.typeArguments);
     if (!node.isTypeTest) {
       giveup(node, 'type casts not implemented.');
     }
@@ -557,7 +559,7 @@
 
   @override
   js.Expression visitCreateBox(tree_ir.CreateBox node) {
-    return new js.ObjectInitializer([]);
+    return new js.ObjectInitializer(const <js.Property>[]);
   }
 
   @override
@@ -570,7 +572,7 @@
     registry.registerInstantiatedClass(cls);
     js.Expression instance = new js.New(
         glue.constructorAccess(cls),
-        node.arguments.map(visitExpression).toList());
+        visitExpressionList(node.arguments));
 
     List<tree_ir.Expression> typeInformation = node.typeInformation;
     assert(typeInformation.isEmpty ||
@@ -578,7 +580,7 @@
     if (typeInformation.isNotEmpty) {
       FunctionElement helper = glue.getAddRuntimeTypeInformation();
       js.Expression typeArguments = new js.ArrayInitializer(
-          typeInformation.map(visitExpression).toList());
+          visitExpressionList(typeInformation));
       return buildStaticHelperInvocation(helper,
           <js.Expression>[instance, typeArguments]);
     } else {
@@ -593,9 +595,9 @@
     js.Expression internalName = js.string(glue.invocationName(node.selector));
     js.Expression kind = js.number(node.selector.invocationMirrorKind);
     js.Expression arguments = new js.ArrayInitializer(
-        node.arguments.map(visitExpression).toList());
+        visitExpressionList(node.arguments));
     js.Expression argumentNames = new js.ArrayInitializer(
-        node.selector.namedArguments.map(js.string).toList());
+        node.selector.namedArguments.map(js.string).toList(growable: false));
     return buildStaticHelperInvocation(glue.createInvocationMirrorMethod,
         [name, internalName, kind, arguments, argumentNames]);
   }
@@ -628,7 +630,8 @@
       // Read a lazily initialized field.
       registry.registerStaticUse(node.element.declaration);
       js.Expression getter = glue.isolateLazyInitializerAccess(node.element);
-      return new js.Call(getter, [], sourceInformation: node.sourceInformation);
+      return new js.Call(getter, <js.Expression>[],
+          sourceInformation: node.sourceInformation);
     }
     // Read an eagerly initialized field.
     registry.registerStaticUse(node.element.declaration);
@@ -678,8 +681,7 @@
 
   @override
   js.Expression visitTypeExpression(tree_ir.TypeExpression node) {
-    List<js.Expression> arguments =
-        node.arguments.map(visitExpression).toList(growable: false);
+    List<js.Expression> arguments = visitExpressionList(node.arguments);
     return glue.generateTypeRepresentation(node.dartType, arguments);
   }
 
diff --git a/pkg/compiler/lib/src/js_backend/codegen/glue.dart b/pkg/compiler/lib/src/js_backend/codegen/glue.dart
index 50fea4f..4cdc447 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/glue.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/glue.dart
@@ -44,8 +44,8 @@
     _compiler.internalError(_compiler.currentElement, message);
   }
 
-  ConstantExpression getConstantForVariable(VariableElement variable) {
-    return _backend.constants.getConstantForVariable(variable);
+  ConstantValue getConstantValueForVariable(VariableElement variable) {
+    return _backend.constants.getConstantValueForVariable(variable);
   }
 
   js.Expression staticFunctionAccess(FunctionElement element) {
diff --git a/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart b/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart
index 9ce842f..045e766 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart
@@ -83,22 +83,20 @@
 
   Constant get trueConstant {
     return new Constant(
-        new BoolConstantExpression(
-            true,
-            new TrueConstantValue()));
+        new BoolConstantExpression(true),
+        new TrueConstantValue());
   }
 
   Constant get falseConstant {
     return new Constant(
-        new BoolConstantExpression(
-            false,
-            new FalseConstantValue()));
+        new BoolConstantExpression(false),
+        new FalseConstantValue());
   }
 
   Constant get nullConstant {
     return new Constant(
-        new NullConstantExpression(
-            new NullConstantValue()));
+        new NullConstantExpression(),
+        new NullConstantValue());
   }
 
   void insertLetPrim(Primitive primitive, Expression node) {
diff --git a/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart b/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
index a9d83e5..d6fdc1b 100644
--- a/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
@@ -23,10 +23,25 @@
 
   String get name => 'ConstantHandler';
 
+  @override
+  ConstantSystem get constantSystem => dartConstantCompiler.constantSystem;
+
+  @override
+  ConstantValue getConstantValue(ConstantExpression expression) {
+    return dartConstantCompiler.getConstantValue(expression);
+  }
+
+  @override
+  ConstantValue getConstantValueForVariable(VariableElement element) {
+    return dartConstantCompiler.getConstantValueForVariable(element);
+  }
+
+  @override
   ConstantExpression getConstantForVariable(VariableElement element) {
     return dartConstantCompiler.getConstantForVariable(element);
   }
 
+  @override
   ConstantExpression compileConstant(VariableElement element) {
     return measure(() {
       ConstantExpression result = dartConstantCompiler.compileConstant(element);
@@ -63,6 +78,16 @@
       return constant;
     });
   }
+
+  // TODO(johnniwinther): Remove this when values are computed from the
+  // expressions.
+  @override
+  void copyConstantValues(JavaScriptConstantTask task) {
+    jsConstantCompiler.constantValueMap.addAll(
+        task.jsConstantCompiler.constantValueMap);
+    dartConstantCompiler.constantValueMap.addAll(
+        task.dartConstantCompiler.constantValueMap);
+  }
 }
 
 /**
@@ -157,13 +182,13 @@
     return result;
   }
 
-  ConstantExpression getInitialValueFor(VariableElement element) {
+  ConstantValue getInitialValueFor(VariableElement element) {
     ConstantExpression initialValue =
         initialVariableValues[element.declaration];
     if (initialValue == null) {
       compiler.internalError(element, "No initial value for given element.");
     }
-    return initialValue;
+    return getConstantValue(initialValue);
   }
 
   ConstantExpression compileNode(Node node, TreeElements elements,
@@ -186,6 +211,10 @@
     return constant;
   }
 
+  ConstantValue getConstantValueForNode(Node node, TreeElements definitions) {
+    return getConstantValue(getConstantForNode(node, definitions));
+  }
+
   ConstantExpression getConstantForNode(Node node, TreeElements definitions) {
     ConstantExpression constant = nodeConstantMap[node];
     if (constant != null) {
@@ -194,13 +223,14 @@
     return definitions.getConstant(node);
   }
 
-  ConstantExpression getConstantForMetadata(MetadataAnnotation metadata) {
-    return metadataConstantMap[metadata];
+  ConstantValue getConstantValueForMetadata(MetadataAnnotation metadata) {
+    return getConstantValue(metadataConstantMap[metadata]);
   }
 
-  ConstantExpression compileMetadata(MetadataAnnotation metadata,
-                           Node node,
-                           TreeElements elements) {
+  ConstantExpression compileMetadata(
+      MetadataAnnotation metadata,
+      Node node,
+      TreeElements elements) {
     ConstantExpression constant =
         super.compileMetadata(metadata, node, elements);
     metadataConstantMap[metadata] = constant;
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index 4e15e5d..06267f8 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -435,6 +435,19 @@
       case JsGetName.DEFAULT_VALUES_PROPERTY: return defaultValuesField;
       case JsGetName.CALL_NAME_PROPERTY: return callNameField;
       case JsGetName.DEFERRED_ACTION_PROPERTY: return deferredAction;
+      case JsGetName.OPERATOR_AS_PREFIX: return operatorAsPrefix;
+      case JsGetName.SIGNATURE_NAME: return operatorSignature;
+      case JsGetName.TYPEDEF_TAG: return typedefTag;
+      case JsGetName.FUNCTION_TYPE_VOID_RETURN_TAG:
+        return functionTypeVoidReturnTag;
+      case JsGetName.FUNCTION_TYPE_RETURN_TYPE_TAG:
+        return functionTypeReturnTypeTag;
+      case JsGetName.FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG:
+        return functionTypeRequiredParametersTag;
+      case JsGetName.FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG:
+        return functionTypeOptionalParametersTag;
+      case JsGetName.FUNCTION_TYPE_NAMED_PARAMETERS_TAG:
+        return functionTypeNamedParametersTag;
       default:
         compiler.reportError(
           node, MessageKind.GENERIC,
diff --git a/pkg/compiler/lib/src/js_backend/type_variable_handler.dart b/pkg/compiler/lib/src/js_backend/type_variable_handler.dart
index 26e38a9..6b04672 100644
--- a/pkg/compiler/lib/src/js_backend/type_variable_handler.dart
+++ b/pkg/compiler/lib/src/js_backend/type_variable_handler.dart
@@ -72,27 +72,24 @@
     for (TypeVariableType currentTypeVariable in cls.typeVariables) {
       TypeVariableElement typeVariableElement = currentTypeVariable.element;
 
-      AstConstant wrapConstant(ConstantExpression constant) {
-        return new AstConstant(typeVariableElement,
-                               typeVariableElement.node,
-                               constant);
-      }
-
-      ConstantExpression name = new StringConstantExpression(
-          currentTypeVariable.name,
+      AstConstant name = new AstConstant(
+          typeVariableElement,
+          typeVariableElement.node,
+          new StringConstantExpression(currentTypeVariable.name),
           _backend.constantSystem.createString(
               new DartString.literal(currentTypeVariable.name)));
       int boundIndex = _metadataCollector.reifyType(typeVariableElement.bound);
-      ConstantExpression bound = new IntConstantExpression(
-          boundIndex,
+      AstConstant bound = new AstConstant(
+          typeVariableElement,
+          typeVariableElement.node,
+          new IntConstantExpression(boundIndex),
           _backend.constantSystem.createInt(boundIndex));
-      ConstantExpression type =
-          new TypeConstantExpression(
-              _backend.constantSystem.createType(
-                  _backend.compiler, cls.rawType),
-              cls.rawType);
-      List<AstConstant> arguments =
-          [wrapConstant(type), wrapConstant(name), wrapConstant(bound)];
+      AstConstant type = new AstConstant(
+          typeVariableElement,
+          typeVariableElement.node,
+          new TypeConstantExpression(cls.rawType),
+          _backend.constantSystem.createType(_backend.compiler, cls.rawType));
+      List<AstConstant> arguments = [type, name, bound];
 
       // TODO(johnniwinther): Support a less front-end specific creation of
       // constructed constants.
diff --git a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
index a2501fd..b2f1351 100644
--- a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
@@ -49,12 +49,12 @@
       if (link != null) {
         for (; !link.isEmpty; link = link.tail) {
           MetadataAnnotation annotation = link.head;
-          ConstantExpression constant =
-              _backend.constants.getConstantForMetadata(annotation);
+          ConstantValue constant =
+              _backend.constants.getConstantValueForMetadata(annotation);
           if (constant == null) {
             _compiler.internalError(annotation, 'Annotation value is null.');
           } else {
-            metadata.add(_emitter.constantReference(constant.value));
+            metadata.add(_emitter.constantReference(constant));
           }
         }
       }
@@ -69,24 +69,24 @@
     if (signature.optionalParameterCount == 0) return const [];
     List<int> defaultValues = <int>[];
     for (ParameterElement element in signature.optionalParameters) {
-      ConstantExpression constant =
-          _backend.constants.getConstantForVariable(element);
+      ConstantValue constant =
+          _backend.constants.getConstantValueForVariable(element);
       jsAst.Expression expression = (constant == null)
           ? null
-          : _emitter.constantReference(constant.value);
+          : _emitter.constantReference(constant);
       defaultValues.add(addGlobalMetadata(expression));
     }
     return defaultValues;
   }
 
   int reifyMetadata(MetadataAnnotation annotation) {
-    ConstantExpression constant =
-        _backend.constants.getConstantForMetadata(annotation);
+    ConstantValue constant =
+        _backend.constants.getConstantValueForMetadata(annotation);
     if (constant == null) {
       _compiler.internalError(annotation, 'Annotation value is null.');
       return -1;
     }
-    return addGlobalMetadata(_emitter.constantReference(constant.value));
+    return addGlobalMetadata(_emitter.constantReference(constant));
   }
 
   int reifyType(DartType type, {bool ignoreTypeVariables: false}) {
diff --git a/pkg/compiler/lib/src/js_emitter/old_emitter/container_builder.dart b/pkg/compiler/lib/src/js_emitter/old_emitter/container_builder.dart
index bd070c7..bccbce8 100644
--- a/pkg/compiler/lib/src/js_emitter/old_emitter/container_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/old_emitter/container_builder.dart
@@ -141,7 +141,7 @@
           Iterable<int> metadataIndices =
               parameter.metadata.map((MetadataAnnotation annotation) {
             ConstantValue constant =
-                backend.constants.getConstantForMetadata(annotation).value;
+                backend.constants.getConstantValueForMetadata(annotation);
             backend.constants.addCompileTimeConstantForEmission(constant);
             return task.metadataCollector.reifyMetadata(annotation);
           });
diff --git a/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart
index d573580..1462ee7 100644
--- a/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart
@@ -551,7 +551,7 @@
     if (fields != null) {
       for (Element element in fields) {
         compiler.withCurrentElement(element, () {
-          ConstantValue constant = handler.getInitialValueFor(element).value;
+          ConstantValue constant = handler.getInitialValueFor(element);
           parts.add(buildInitialization(element, constantReference(constant)));
         });
       }
diff --git a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
index 7d5122b..2e9ed21 100644
--- a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
@@ -100,12 +100,11 @@
           parametersBuffer[optionalParameterStart + index] =
               new jsAst.Parameter(jsName);
         } else {
-          ConstantExpression constant = handler.getConstantForVariable(element);
-          if (constant == null) {
+          ConstantValue value = handler.getConstantValueForVariable(element);
+          if (value == null) {
             argumentsBuffer[count] =
                 emitter.constantReference(new NullConstantValue());
           } else {
-            ConstantValue value = constant.value;
             if (!value.isNull) {
               // If the value is the null constant, we should not pass it
               // down to the native method.
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder.dart
index 4d0e3b2..af92768 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder.dart
@@ -210,7 +210,7 @@
 
   StaticField _buildStaticField(Element element) {
     JavaScriptConstantCompiler handler = backend.constants;
-    ConstantValue initialValue = handler.getInitialValueFor(element).value;
+    ConstantValue initialValue = handler.getInitialValueFor(element);
     // TODO(zarah): The holder should not be registered during building of
     // a static field.
     _registry.registerHolder(namer.globalObjectForConstant(initialValue));
@@ -466,16 +466,16 @@
     if (signature.optionalParametersAreNamed) {
       optionalParameterDefaultValues = new Map<String, ConstantValue>();
       signature.forEachOptionalParameter((ParameterElement parameter) {
-        ConstantExpression def =
-            backend.constants.getConstantForVariable(parameter);
-        optionalParameterDefaultValues[parameter.name] = def.value;
+        ConstantValue def =
+            backend.constants.getConstantValueForVariable(parameter);
+        optionalParameterDefaultValues[parameter.name] = def;
       });
     } else {
       optionalParameterDefaultValues = <ConstantValue>[];
       signature.forEachOptionalParameter((ParameterElement parameter) {
-        ConstantExpression def =
-            backend.constants.getConstantForVariable(parameter);
-        optionalParameterDefaultValues.add(def.value);
+        ConstantValue def =
+            backend.constants.getConstantValueForVariable(parameter);
+        optionalParameterDefaultValues.add(def);
       });
     }
     return optionalParameterDefaultValues;
diff --git a/pkg/compiler/lib/src/mirrors/dart2js_member_mirrors.dart b/pkg/compiler/lib/src/mirrors/dart2js_member_mirrors.dart
index f2e3c7c..bd510c2 100644
--- a/pkg/compiler/lib/src/mirrors/dart2js_member_mirrors.dart
+++ b/pkg/compiler/lib/src/mirrors/dart2js_member_mirrors.dart
@@ -204,7 +204,7 @@
           message: "Missing constant for parameter "
                    "$parameter with default value."));
       return _convertConstantToInstanceMirror(mirrorSystem,
-          constant, constant.value);
+          constant, mirrorSystem.compiler.constants.getConstantValue(constant));
     }
     return null;
   }
diff --git a/pkg/compiler/lib/src/mirrors/dart2js_mirrors.dart b/pkg/compiler/lib/src/mirrors/dart2js_mirrors.dart
index 86c95cc..51ab110 100644
--- a/pkg/compiler/lib/src/mirrors/dart2js_mirrors.dart
+++ b/pkg/compiler/lib/src/mirrors/dart2js_mirrors.dart
@@ -220,7 +220,9 @@
             mirrorSystem.compiler.commentMap[metadata.beginToken]);
         metadata.ensureResolved(mirrorSystem.compiler);
         _metadata.add(_convertConstantToInstanceMirror(
-            mirrorSystem, metadata.constant, metadata.constant.value));
+            mirrorSystem, metadata.constant,
+            mirrorSystem.compiler.constants.getConstantValue(
+                metadata.constant)));
       }
       _appendCommentTokens(mirrorSystem.compiler.commentMap[getBeginToken()]);
     }
diff --git a/pkg/compiler/lib/src/mirrors_used.dart b/pkg/compiler/lib/src/mirrors_used.dart
index 05f0720..ec535c7 100644
--- a/pkg/compiler/lib/src/mirrors_used.dart
+++ b/pkg/compiler/lib/src/mirrors_used.dart
@@ -137,7 +137,8 @@
       if (named == null) continue;
       ConstantCompiler constantCompiler = compiler.resolver.constantCompiler;
       ConstantValue value =
-          constantCompiler.compileNode(named.expression, mapping).value;
+          constantCompiler.getConstantValue(
+              constantCompiler.compileNode(named.expression, mapping));
 
       MirrorUsageBuilder builder =
           new MirrorUsageBuilder(
@@ -266,10 +267,11 @@
     List<MirrorUsage> result = <MirrorUsage>[];
     for (MetadataAnnotation metadata in tag.metadata) {
       metadata.ensureResolved(compiler);
-      Element element =
-          metadata.constant.value.getType(compiler.coreTypes).element;
+      ConstantValue value =
+          compiler.constants.getConstantValue(metadata.constant);
+      Element element = value.getType(compiler.coreTypes).element;
       if (element == compiler.mirrorsUsedClass) {
-        result.add(buildUsage(metadata.constant.value));
+        result.add(buildUsage(value));
       }
     }
     return result;
@@ -568,7 +570,7 @@
   Spannable positionOf(ConstantValue constant) {
     Node node;
     elements.forEachConstantNode((Node n, ConstantExpression c) {
-      if (node == null && c.value == constant) {
+      if (node == null && compiler.constants.getConstantValue(c) == constant) {
         node = n;
       }
     });
diff --git a/pkg/compiler/lib/src/native/behavior.dart b/pkg/compiler/lib/src/native/behavior.dart
index 6e6c53a..3fb1c4b 100644
--- a/pkg/compiler/lib/src/native/behavior.dart
+++ b/pkg/compiler/lib/src/native/behavior.dart
@@ -689,7 +689,8 @@
          !link.isEmpty;
          link = link.tail) {
       MetadataAnnotation annotation = link.head.ensureResolved(compiler);
-      ConstantValue value = annotation.constant.value;
+      ConstantValue value =
+          compiler.constants.getConstantValue(annotation.constant);
       if (!value.isConstructedObject) continue;
       ConstructedConstantValue constructedObject = value;
       if (constructedObject.type.element != annotationClass) continue;
diff --git a/pkg/compiler/lib/src/native/enqueue.dart b/pkg/compiler/lib/src/native/enqueue.dart
index 51041d5..f1339a1 100644
--- a/pkg/compiler/lib/src/native/enqueue.dart
+++ b/pkg/compiler/lib/src/native/enqueue.dart
@@ -319,7 +319,8 @@
          !link.isEmpty;
          link = link.tail) {
       MetadataAnnotation annotation = link.head.ensureResolved(compiler);
-      ConstantValue value = annotation.constant.value;
+      ConstantValue value =
+          compiler.constants.getConstantValue(annotation.constant);
       if (!value.isConstructedObject) continue;
       ConstructedConstantValue constructedObject = value;
       if (constructedObject.type.element != annotationClass) continue;
diff --git a/pkg/compiler/lib/src/patch_parser.dart b/pkg/compiler/lib/src/patch_parser.dart
index 1f03ad4..6957cec 100644
--- a/pkg/compiler/lib/src/patch_parser.dart
+++ b/pkg/compiler/lib/src/patch_parser.dart
@@ -362,8 +362,8 @@
   /// Checks [element] for metadata matching the [handler]. Return a non-null
   /// annotation marker matching metadata was found.
   static checkAnnotation(Compiler compiler,
-                              Element element,
-                              EagerAnnotationHandler handler) {
+                         Element element,
+                         EagerAnnotationHandler handler) {
     for (Link<MetadataAnnotation> link = element.metadata;
          !link.isEmpty;
          link = link.tail) {
@@ -375,7 +375,8 @@
         compiler.enqueuer.resolution.addDeferredAction(element, () {
           annotation.ensureResolved(compiler);
           handler.validate(
-              compiler, element, annotation, annotation.constant.value);
+              compiler, element, annotation,
+              compiler.constants.getConstantValue(annotation.constant));
         });
         return result;
       }
diff --git a/pkg/compiler/lib/src/resolution/access_semantics.dart b/pkg/compiler/lib/src/resolution/access_semantics.dart
index 0e1be6f..17ec4ad 100644
--- a/pkg/compiler/lib/src/resolution/access_semantics.dart
+++ b/pkg/compiler/lib/src/resolution/access_semantics.dart
@@ -474,6 +474,17 @@
   ///     m() => new C();
   ///
   ERRONEOUS_REDIRECTING_FACTORY,
+
+
+  /// An invocation of a constructor with incompatible arguments.
+  ///
+  /// For instance
+  ///     class C {
+  ///       C();
+  ///     }
+  ///     m() => new C(true);
+  ///
+  INCOMPATIBLE,
 }
 
 /// Data structure used to classify the semantics of a constructor invocation.
@@ -499,8 +510,11 @@
            kind == ConstructorAccessKind.UNRESOLVED_TYPE ||
            kind == ConstructorAccessKind.UNRESOLVED_CONSTRUCTOR ||
            kind == ConstructorAccessKind.NON_CONSTANT_CONSTRUCTOR ||
-           kind == ConstructorAccessKind.ERRONEOUS_REDIRECTING_FACTORY;
+           kind == ConstructorAccessKind.ERRONEOUS_REDIRECTING_FACTORY ||
+           kind == ConstructorAccessKind.INCOMPATIBLE;
   }
+
+  String toString() => 'ConstructorAccessSemantics($kind, $element, $type)';
 }
 
 /// Data structure used to classify the semantics of a redirecting factory
diff --git a/pkg/compiler/lib/src/resolution/members.dart b/pkg/compiler/lib/src/resolution/members.dart
index 8d05b11..6069d4c 100644
--- a/pkg/compiler/lib/src/resolution/members.dart
+++ b/pkg/compiler/lib/src/resolution/members.dart
@@ -1969,7 +1969,7 @@
         ConstantExpression constant =
             compiler.resolver.constantCompiler.compileNode(
                 argumentNode, registry.mapping);
-        ConstantValue name = constant.value;
+        ConstantValue name = compiler.constants.getConstantValue(constant);
         if (!name.isString) {
           DartType type = name.getType(compiler.coreTypes);
           compiler.reportError(argumentNode, MessageKind.STRING_EXPECTED,
@@ -2027,7 +2027,7 @@
       return;
     }
 
-    ConstantValue value = constant.value;
+    ConstantValue value = compiler.constants.getConstantValue(constant);
     if (value.isMap) {
       checkConstMapKeysDontOverrideEquals(node, value);
     }
@@ -2432,7 +2432,8 @@
         assert(invariant(node, constant != null,
             message: 'No constant computed for $node'));
 
-        DartType caseType = typeOfConstant(constant.value);
+        ConstantValue value = compiler.constants.getConstantValue(constant);
+        DartType caseType = typeOfConstant(value);
 
         if (firstCaseType == null) {
           firstCase = caseMatch;
@@ -2447,7 +2448,7 @@
           } else if (caseType.element == compiler.functionClass) {
             compiler.reportError(node, MessageKind.SWITCH_CASE_FORBIDDEN,
                                  {'type': "Function"});
-          } else if (constant.value.isObject && overridesEquals(caseType)) {
+          } else if (value.isObject && overridesEquals(caseType)) {
             compiler.reportError(firstCase.expression,
                 MessageKind.SWITCH_CASE_VALUE_OVERRIDES_EQUALS,
                 {'type': caseType});
diff --git a/pkg/compiler/lib/src/resolution/resolution_common.dart b/pkg/compiler/lib/src/resolution/resolution_common.dart
index d13b5f3..79741ad 100644
--- a/pkg/compiler/lib/src/resolution/resolution_common.dart
+++ b/pkg/compiler/lib/src/resolution/resolution_common.dart
@@ -533,8 +533,9 @@
   void _postProcessClassElement(BaseClassElementX element) {
     for (MetadataAnnotation metadata in element.metadata) {
       metadata.ensureResolved(compiler);
-      if (!element.isProxy &&
-          metadata.constant.value == compiler.proxyConstant) {
+      ConstantValue value =
+          compiler.constants.getConstantValue(metadata.constant);
+      if (!element.isProxy && value == compiler.proxyConstant) {
         element.isProxy = true;
       }
     }
diff --git a/pkg/compiler/lib/src/resolution/semantic_visitor.dart b/pkg/compiler/lib/src/resolution/semantic_visitor.dart
index 3cc1c22..791a259 100644
--- a/pkg/compiler/lib/src/resolution/semantic_visitor.dart
+++ b/pkg/compiler/lib/src/resolution/semantic_visitor.dart
@@ -3813,7 +3813,7 @@
       Node right,
       A arg);
 
-  /// Const invocation of a [constructor].
+  /// Const invocation of a [constant] constructor.
   ///
   /// For instance
   ///   class C<T> {
@@ -3826,6 +3826,36 @@
       ConstructedConstantExpression constant,
       A arg);
 
+  /// Const invocation of the `bool.fromEnvironment` constructor.
+  ///
+  /// For instance
+  ///   m() => const bool.fromEnvironment('foo', defaultValue: false);
+  ///
+  R visitBoolFromEnvironmentConstructorInvoke(
+      NewExpression node,
+      BoolFromEnvironmentConstantExpression constant,
+      A arg);
+
+  /// Const invocation of the `int.fromEnvironment` constructor.
+  ///
+  /// For instance
+  ///   m() => const int.fromEnvironment('foo', defaultValue: 42);
+  ///
+  R visitIntFromEnvironmentConstructorInvoke(
+      NewExpression node,
+      IntFromEnvironmentConstantExpression constant,
+      A arg);
+
+  /// Const invocation of the `String.fromEnvironment` constructor.
+  ///
+  /// For instance
+  ///   m() => const String.fromEnvironment('foo', defaultValue: 'bar');
+  ///
+  R visitStringFromEnvironmentConstructorInvoke(
+      NewExpression node,
+      StringFromEnvironmentConstantExpression constant,
+      A arg);
+
   /// Invocation of a generative [constructor] on [type] with [arguments].
   ///
   /// For instance
@@ -3995,6 +4025,22 @@
       NodeList arguments,
       CallStructure callStructure,
       A arg);
+
+  /// Invocation of [constructor] on [type] with incompatible [arguments].
+  ///
+  /// For instance
+  ///   class C {
+  ///     C(a);
+  ///   }
+  ///   m() => C(true, 42);
+  ///
+  R visitConstructorIncompatibleInvoke(
+      NewExpression node,
+      ConstructorElement constructor,
+      InterfaceType type,
+      NodeList arguments,
+      CallStructure callStructure,
+      A arg);
 }
 
 abstract class SemanticDeclarationVisitor<R, A> {
diff --git a/pkg/compiler/lib/src/resolution/semantic_visitor_mixins.dart b/pkg/compiler/lib/src/resolution/semantic_visitor_mixins.dart
index af43415..a3587f8 100644
--- a/pkg/compiler/lib/src/resolution/semantic_visitor_mixins.dart
+++ b/pkg/compiler/lib/src/resolution/semantic_visitor_mixins.dart
@@ -2870,6 +2870,41 @@
   }
 
   @override
+  R visitBoolFromEnvironmentConstructorInvoke(
+      NewExpression node,
+      BoolFromEnvironmentConstantExpression constant,
+      A arg) {
+    return bulkHandleNew(node, arg);
+  }
+
+  @override
+  R visitIntFromEnvironmentConstructorInvoke(
+      NewExpression node,
+      IntFromEnvironmentConstantExpression constant,
+      A arg) {
+    return bulkHandleNew(node, arg);
+  }
+
+  @override
+  R visitStringFromEnvironmentConstructorInvoke(
+      NewExpression node,
+      StringFromEnvironmentConstantExpression constant,
+      A arg) {
+    return bulkHandleNew(node, arg);
+  }
+
+  @override
+  R visitConstructorIncompatibleInvoke(
+      NewExpression node,
+      ConstructorElement constructor,
+      InterfaceType type,
+      NodeList arguments,
+      CallStructure callStructure,
+      A arg) {
+    return bulkHandleNew(node, arg);
+  }
+
+  @override
   R visitGenerativeConstructorInvoke(
       NewExpression node,
       ConstructorElement constructor,
@@ -4043,6 +4078,7 @@
       Selector selector,
       Node rhs,
       A arg) {
+    apply(receiver, arg);
     apply(rhs, arg);
     return null;
   }
@@ -5513,6 +5549,42 @@
   }
 
   @override
+  R visitBoolFromEnvironmentConstructorInvoke(
+      NewExpression node,
+      BoolFromEnvironmentConstantExpression constant,
+      A arg) {
+    return null;
+  }
+
+  @override
+  R visitIntFromEnvironmentConstructorInvoke(
+      NewExpression node,
+      IntFromEnvironmentConstantExpression constant,
+      A arg) {
+    return null;
+  }
+
+  @override
+  R visitStringFromEnvironmentConstructorInvoke(
+      NewExpression node,
+      StringFromEnvironmentConstantExpression constant,
+      A arg) {
+    return null;
+  }
+
+  @override
+  R visitConstructorIncompatibleInvoke(
+      NewExpression node,
+      ConstructorElement constructor,
+      InterfaceType type,
+      NodeList arguments,
+      CallStructure callStructure,
+      A arg) {
+    apply(arguments, arg);
+    return null;
+  }
+
+  @override
   R visitUnresolvedClassConstructorInvoke(
       NewExpression node,
       Element constructor,
@@ -7576,6 +7648,30 @@
   }
 
   @override
+  R visitBoolFromEnvironmentConstructorInvoke(
+      NewExpression node,
+      BoolFromEnvironmentConstantExpression constant,
+      A arg) {
+    return handleConstantGet(node, constant, arg);
+  }
+
+  @override
+  R visitIntFromEnvironmentConstructorInvoke(
+      NewExpression node,
+      IntFromEnvironmentConstantExpression constant,
+      A arg) {
+    return handleConstantGet(node, constant, arg);
+  }
+
+  @override
+  R visitStringFromEnvironmentConstructorInvoke(
+      NewExpression node,
+      StringFromEnvironmentConstantExpression constant,
+      A arg) {
+    return handleConstantGet(node, constant, arg);
+  }
+
+  @override
   R visitConstantGet(
       Send node,
       ConstantExpression constant,
diff --git a/pkg/compiler/lib/src/resolution/send_resolver.dart b/pkg/compiler/lib/src/resolution/send_resolver.dart
index 5910234..64d62dd 100644
--- a/pkg/compiler/lib/src/resolution/send_resolver.dart
+++ b/pkg/compiler/lib/src/resolution/send_resolver.dart
@@ -541,6 +541,7 @@
 
   ConstructorAccessSemantics computeConstructorAccessSemantics(
         ConstructorElement constructor,
+        CallStructure callStructure,
         DartType type,
         {bool mustBeConstant: false}) {
     if (mustBeConstant && !constructor.isConst) {
@@ -570,6 +571,7 @@
       ConstructorAccessSemantics effectiveTargetSemantics =
           computeConstructorAccessSemantics(
               effectiveTarget,
+              callStructure,
               constructor.computeEffectiveTargetType(type));
       if (effectiveTargetSemantics.isErroneous) {
         return new RedirectingFactoryConstructorAccessSemantics(
@@ -583,22 +585,29 @@
           constructor,
           type,
           effectiveTargetSemantics);
-    } else if (constructor.isFactoryConstructor) {
-      return new ConstructorAccessSemantics(
-          ConstructorAccessKind.FACTORY, constructor, type);
-    } else if (constructor.isRedirectingGenerative) {
-      if (constructor.enclosingClass.isAbstract) {
-          return new ConstructorAccessSemantics(
-              ConstructorAccessKind.ABSTRACT, constructor, type);
-      }
-      return new ConstructorAccessSemantics(
-          ConstructorAccessKind.REDIRECTING_GENERATIVE, constructor, type);
-    } else if (constructor.enclosingClass.isAbstract) {
-      return new ConstructorAccessSemantics(
-          ConstructorAccessKind.ABSTRACT, constructor, type);
     } else {
-      return new ConstructorAccessSemantics(
-          ConstructorAccessKind.GENERATIVE, constructor, type);
+      if (!callStructure.signatureApplies(constructor)) {
+        return new ConstructorAccessSemantics(
+            ConstructorAccessKind.INCOMPATIBLE,
+            constructor,
+            type);
+      } else if (constructor.isFactoryConstructor) {
+        return new ConstructorAccessSemantics(
+            ConstructorAccessKind.FACTORY, constructor, type);
+      } else if (constructor.isRedirectingGenerative) {
+        if (constructor.enclosingClass.isAbstract) {
+            return new ConstructorAccessSemantics(
+                ConstructorAccessKind.ABSTRACT, constructor, type);
+        }
+        return new ConstructorAccessSemantics(
+            ConstructorAccessKind.REDIRECTING_GENERATIVE, constructor, type);
+      } else if (constructor.enclosingClass.isAbstract) {
+        return new ConstructorAccessSemantics(
+            ConstructorAccessKind.ABSTRACT, constructor, type);
+      } else {
+        return new ConstructorAccessSemantics(
+            ConstructorAccessKind.GENERATIVE, constructor, type);
+      }
     }
   }
 
@@ -609,17 +618,37 @@
 
     ConstructorAccessSemantics constructorAccessSemantics =
         computeConstructorAccessSemantics(
-            element, type, mustBeConstant: node.isConst);
+            element, selector.callStructure, type,
+            mustBeConstant: node.isConst);
     if (node.isConst) {
       ConstantExpression constant = elements.getConstant(node);
       if (constructorAccessSemantics.isErroneous ||
-          constant is! ConstructedConstantExpression) {
+          constant == null ||
+          constant.kind == ConstantExpressionKind.ERRONEOUS) {
         // This is a non-constant constant constructor invocation, like
         // `const Const(method())`.
         constructorAccessSemantics = new ConstructorAccessSemantics(
             ConstructorAccessKind.NON_CONSTANT_CONSTRUCTOR, element, type);
       } else {
-        return new ConstInvokeStructure(constant);
+        ConstantInvokeKind kind;
+        switch (constant.kind) {
+          case ConstantExpressionKind.CONSTRUCTED:
+            kind = ConstantInvokeKind.CONSTRUCTED;
+            break;
+          case ConstantExpressionKind.BOOL_FROM_ENVIRONMENT:
+            kind = ConstantInvokeKind.BOOL_FROM_ENVIRONMENT;
+            break;
+          case ConstantExpressionKind.INT_FROM_ENVIRONMENT:
+            kind = ConstantInvokeKind.INT_FROM_ENVIRONMENT;
+            break;
+          case ConstantExpressionKind.STRING_FROM_ENVIRONMENT:
+            kind = ConstantInvokeKind.STRING_FROM_ENVIRONMENT;
+            break;
+          default:
+            return internalError(
+                node, "Unexpected constant kind $kind: ${constant.getText()}");
+        }
+        return new ConstInvokeStructure(kind, constant);
       }
     }
     return new NewInvokeStructure(constructorAccessSemantics, selector);
diff --git a/pkg/compiler/lib/src/resolution/send_structure.dart b/pkg/compiler/lib/src/resolution/send_structure.dart
index b5d0f71..60d6189 100644
--- a/pkg/compiler/lib/src/resolution/send_structure.dart
+++ b/pkg/compiler/lib/src/resolution/send_structure.dart
@@ -2359,21 +2359,47 @@
         return visitor.visitUnresolvedRedirectingFactoryConstructorInvoke(
             node, semantics.element, semantics.type,
             node.send.argumentsNode, callStructure, arg);
+      case ConstructorAccessKind.INCOMPATIBLE:
+        return visitor.visitConstructorIncompatibleInvoke(
+            node, semantics.element, semantics.type,
+            node.send.argumentsNode, callStructure, arg);
     }
     throw new SpannableAssertionFailure(node,
         "Unhandled constructor invocation kind: ${semantics.kind}");
   }
+
+  String toString() => 'new($semantics,$selector)';
+}
+
+enum ConstantInvokeKind {
+  CONSTRUCTED,
+  BOOL_FROM_ENVIRONMENT,
+  INT_FROM_ENVIRONMENT,
+  STRING_FROM_ENVIRONMENT,
 }
 
 /// The structure for a [NewExpression] of a constant invocation. For instance
 /// `const C()`.
 class ConstInvokeStructure<R, A> extends NewStructure<R, A> {
-  final ConstructedConstantExpression constant;
+  final ConstantInvokeKind kind;
+  final ConstantExpression constant;
 
-  ConstInvokeStructure(this.constant);
+  ConstInvokeStructure(this.kind, this.constant);
 
   R dispatch(SemanticSendVisitor<R, A> visitor, NewExpression node, A arg) {
-    return visitor.visitConstConstructorInvoke(node, constant, arg);
+    switch (kind) {
+      case ConstantInvokeKind.CONSTRUCTED:
+        return visitor.visitConstConstructorInvoke(node, constant, arg);
+      case ConstantInvokeKind.BOOL_FROM_ENVIRONMENT:
+        return visitor.visitBoolFromEnvironmentConstructorInvoke(
+            node, constant, arg);
+      case ConstantInvokeKind.INT_FROM_ENVIRONMENT:
+        return visitor.visitIntFromEnvironmentConstructorInvoke(
+            node, constant, arg);
+      case ConstantInvokeKind.STRING_FROM_ENVIRONMENT:
+        return visitor.visitStringFromEnvironmentConstructorInvoke(
+            node, constant, arg);
+    }
   }
 }
 
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index 331c750..98b0fca 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -141,7 +141,7 @@
           signature.forEachOptionalParameter((ParameterElement parameter) {
             // This ensures the default value will be computed.
             ConstantValue constant =
-                backend.constants.getConstantForVariable(parameter).value;
+                backend.constants.getConstantValueForVariable(parameter);
             CodegenRegistry registry = work.registry;
             registry.registerCompileTimeConstant(constant);
           });
@@ -1505,11 +1505,11 @@
   }
 
   HInstruction handleConstantForOptionalParameter(Element parameter) {
-    ConstantExpression constant =
-        backend.constants.getConstantForVariable(parameter);
-    assert(invariant(parameter, constant != null,
+    ConstantValue constantValue =
+        backend.constants.getConstantValueForVariable(parameter);
+    assert(invariant(parameter, constantValue != null,
         message: 'No constant computed for $parameter'));
-    return graph.addConstant(constant.value, compiler);
+    return graph.addConstant(constantValue, compiler);
   }
 
   Element get currentNonClosureClass {
@@ -1545,11 +1545,11 @@
   bool inTryStatement = false;
 
   ConstantValue getConstantForNode(ast.Node node) {
-    ConstantExpression constant =
-        backend.constants.getConstantForNode(node, elements);
-    assert(invariant(node, constant != null,
+    ConstantValue constantValue =
+        backend.constants.getConstantValueForNode(node, elements);
+    assert(invariant(node, constantValue != null,
         message: 'No constant computed for $node'));
-    return constant.value;
+    return constantValue;
   }
 
   HInstruction addConstant(ast.Node node) {
@@ -3310,7 +3310,7 @@
       ast.Send node,
       FieldElement field,
       ConstantExpression constant) {
-    ConstantValue value = constant.value;
+    ConstantValue value = backend.constants.getConstantValue(constant);
     HConstant instruction;
     // Constants that are referred via a deferred prefix should be referred
     // by reference.
@@ -4258,36 +4258,6 @@
       handleForeignRawFunctionRef(node, 'RAW_DART_FUNCTION_REF');
     } else if (name == 'JS_SET_CURRENT_ISOLATE') {
       handleForeignSetCurrentIsolate(node);
-    } else if (name == 'JS_OPERATOR_AS_PREFIX') {
-      // TODO(floitsch): this should be a JS_NAME.
-      stack.add(addConstantString(backend.namer.operatorAsPrefix));
-    } else if (name == 'JS_SIGNATURE_NAME') {
-      // TODO(floitsch): this should be a JS_NAME.
-      stack.add(addConstantString(backend.namer.operatorSignature));
-    } else if (name == 'JS_TYPEDEF_TAG') {
-      // TODO(floitsch): this should be a JS_NAME.
-      stack.add(addConstantString(backend.namer.typedefTag));
-    } else if (name == 'JS_FUNCTION_TYPE_VOID_RETURN_TAG') {
-      // TODO(floitsch): this should be a JS_NAME.
-      stack.add(addConstantString(backend.namer.functionTypeVoidReturnTag));
-    } else if (name == 'JS_FUNCTION_TYPE_RETURN_TYPE_TAG') {
-      // TODO(floitsch): this should be a JS_NAME.
-      stack.add(addConstantString(backend.namer.functionTypeReturnTypeTag));
-    } else if (name ==
-               'JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG') {
-      // TODO(floitsch): this should be a JS_NAME.
-      stack.add(addConstantString(
-          backend.namer.functionTypeRequiredParametersTag));
-    } else if (name ==
-               'JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG') {
-      // TODO(floitsch): this should be a JS_NAME.
-      stack.add(addConstantString(
-          backend.namer.functionTypeOptionalParametersTag));
-    } else if (name ==
-               'JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG') {
-      // TODO(floitsch): this should be a JS_NAME.
-      stack.add(addConstantString(
-          backend.namer.functionTypeNamedParametersTag));
     } else if (name == 'JS_IS_INDEXABLE_FIELD_NAME') {
       // TODO(floitsch): this should be a JS_NAME.
       Element element = backend.findHelper('JavaScriptIndexingBehavior');
@@ -4309,7 +4279,7 @@
     } else if (name == 'JS_STRING_CONCAT') {
       handleJsStringConcat(node);
     } else {
-      throw "Unknown foreign: ${element}";
+      compiler.internalError(node, "Unknown foreign: ${element}");
     }
   }
 
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart b/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
index 1f5fea0..691e206 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
@@ -347,8 +347,17 @@
   }
 
   Expression visitInvokeMethod(InvokeMethod node) {
-    _rewriteList(node.arguments);
-    node.receiver = visitExpression(node.receiver);
+    if (node.receiverIsNotNull) {
+      _rewriteList(node.arguments);
+      node.receiver = visitExpression(node.receiver);
+    } else {
+      // Impure expressions cannot be propagated across the method lookup,
+      // because it throws when the receiver is null.
+      inEmptyEnvironment(() {
+        _rewriteList(node.arguments);
+      });
+      node.receiver = visitExpression(node.receiver);
+    }
     return node;
   }
 
diff --git a/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart b/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
index 19c8a12..ec566d2 100644
--- a/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
+++ b/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
@@ -350,9 +350,10 @@
   }
 
   Statement visitInvokeMethod(cps_ir.InvokeMethod node) {
-    Expression invoke = new InvokeMethod(getVariableUse(node.receiver),
-                                         node.selector,
-                                         translateArguments(node.arguments));
+    InvokeMethod invoke = new InvokeMethod(getVariableUse(node.receiver),
+                                           node.selector,
+                                           translateArguments(node.arguments));
+    invoke.receiverIsNotNull = node.receiverIsNotNull;
     return continueWithExpression(node.continuation, invoke);
   }
 
@@ -490,7 +491,7 @@
   }
 
   Expression visitConstant(cps_ir.Constant node) {
-    return new Constant(node.expression);
+    return new Constant(node.expression, node.value);
   }
 
   Expression visitLiteralList(cps_ir.LiteralList node) {
diff --git a/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart b/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart
index d200e405..b8d554f 100644
--- a/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart
+++ b/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart
@@ -192,14 +192,17 @@
 /**
  * A call to a method, operator, getter, setter or index getter/setter.
  *
- * In contrast to the CPS-based IR, the receiver and arguments can be
- * arbitrary expressions.
+ * If [receiver] is `null`, an error is thrown before the arguments are
+ * evaluated. This corresponds to the JS evaluation order.
  */
 class InvokeMethod extends Expression implements Invoke {
   Expression receiver;
   final Selector selector;
   final List<Expression> arguments;
 
+  /// If true, it is known that the receiver cannot be `null`.
+  bool receiverIsNotNull = false;
+
   InvokeMethod(this.receiver, this.selector, this.arguments) {
     assert(receiver != null);
   }
@@ -211,6 +214,9 @@
 }
 
 /// Invoke [target] on [receiver], bypassing ordinary dispatch semantics.
+///
+/// Since the [receiver] is not used for method lookup, it may be `null`
+/// without an error being thrown.
 class InvokeMethodDirectly extends Expression implements Invoke {
   Expression receiver;
   final Element target;
@@ -269,17 +275,17 @@
  */
 class Constant extends Expression {
   final ConstantExpression expression;
+  final values.ConstantValue value;
 
-  Constant(this.expression);
+  Constant(this.expression, this.value);
 
   Constant.bool(values.BoolConstantValue constantValue)
       : expression = new BoolConstantExpression(
-          constantValue.primitiveValue, constantValue);
+          constantValue.primitiveValue),
+        value = constantValue;
 
   accept(ExpressionVisitor visitor) => visitor.visitConstant(this);
   accept1(ExpressionVisitor1 visitor, arg) => visitor.visitConstant(this, arg);
-
-  values.ConstantValue get value => expression.value;
 }
 
 class This extends Expression {
diff --git a/pkg/compiler/lib/src/typechecker.dart b/pkg/compiler/lib/src/typechecker.dart
index 4811e3f..85d82b3 100644
--- a/pkg/compiler/lib/src/typechecker.dart
+++ b/pkg/compiler/lib/src/typechecker.dart
@@ -1807,13 +1807,13 @@
         List<FieldElement> unreferencedFields = <FieldElement>[];
         EnumClassElement enumClass = expressionType.element;
         enumClass.enumValues.forEach((FieldElement field) {
-          ConstantExpression constantExpression =
-              compiler.constants.getConstantForVariable(field);
-          if (constantExpression == null) {
+          ConstantValue constantValue =
+              compiler.constants.getConstantValueForVariable(field);
+          if (constantValue == null) {
             // The field might not have been resolved.
             unreferencedFields.add(field);
           } else {
-            enumValues[constantExpression.value] = field;
+            enumValues[constantValue] = field;
           }
         });
 
@@ -1824,7 +1824,8 @@
               ConstantExpression caseConstant =
                   compiler.resolver.constantCompiler.compileNode(
                       caseMatch.expression, elements);
-              enumValues.remove(caseConstant.value);
+              enumValues.remove(
+                  compiler.constants.getConstantValue(caseConstant));
             }
           }
         }
diff --git a/pkg/compiler/lib/src/use_unused_api.dart b/pkg/compiler/lib/src/use_unused_api.dart
index d1359e6..998b39b 100644
--- a/pkg/compiler/lib/src/use_unused_api.dart
+++ b/pkg/compiler/lib/src/use_unused_api.dart
@@ -69,7 +69,7 @@
   useIo(null, null);
   usedByTests();
   useElements();
-  useIr(null, null);
+  useIr(null);
   useCompiler(null);
   useTypes();
   useCodeEmitterTask(null);
@@ -260,11 +260,7 @@
   l.forEachImport(null);
 }
 
-useIr(ir_builder.IrBuilderTask task,
-      ir_builder.IrBuilder builder) {
-  task
-    ..hasIr(null)
-    ..getIr(null);
+useIr(ir_builder.IrBuilder builder) {
   builder
     ..buildStringConstant(null)
     ..buildDynamicGet(null, null);
@@ -276,6 +272,7 @@
       ..resetAsync(null)
       ..lookupLibrary(null);
   compiler.forgetElement(null);
+  compiler.backend.constantCompilerTask.copyConstantValues(null);
 }
 
 useTypes() {
diff --git a/pkg/docgen/lib/src/models/model_helpers.dart b/pkg/docgen/lib/src/models/model_helpers.dart
index 70f158d..0aa8c9f 100644
--- a/pkg/docgen/lib/src/models/model_helpers.dart
+++ b/pkg/docgen/lib/src/models/model_helpers.dart
@@ -229,6 +229,12 @@
   }
 
   @override
+  Annotation visitStringLength(StringLengthConstantExpression exp,
+                               AnnotationInfo context) {
+    return null;
+  }
+
+  @override
   Annotation visitDeferred(DeferredConstantExpression exp,
                            AnnotationInfo context) {
     return exp.expression.accept(this, context);
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 1889628..78179ad 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -118,6 +118,7 @@
 crypto/test/sha1_test: Slow, Pass
 
 [ $browser ]
+analyzer_cli/*: SkipByDesign # Uses dart:io.
 */test/analyzer_test: SkipByDesign # No need to run analysis tests on browser bots
 analysis_server/test/*: SkipByDesign # Uses dart:io.
 analysis_server/tool/spec/check_all_test: SkipByDesign # Uses dart:io.
@@ -144,43 +145,45 @@
 analyzer/test/*: PubGetError
 
 [ $compiler == dart2js && $cps_ir ]
+analyzer_cli/test/error_test: Crash # (try {return fn(tempDir);}finally {new Directory(tempDir).deleteSync(recursive:true);}): try/finally
+analyzer_cli/test/options_test: Crash #  try/finally
 analysis_server/tool/spec/check_all_test: Crash #  Unhandled node
-analyzer/test/cancelable_future_test: Crash #  try/finally
-analyzer/test/enum_test: Crash #  try/finally
-analyzer/test/file_system/memory_file_system_test: Crash #  try/finally
-analyzer/test/file_system/physical_resource_provider_test: Crash #  try/finally
-analyzer/test/file_system/resource_uri_resolver_test: Crash #  try/finally
+analyzer/test/cancelable_future_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
+analyzer/test/enum_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
+analyzer/test/file_system/memory_file_system_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
+analyzer/test/file_system/physical_resource_provider_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
+analyzer/test/file_system/resource_uri_resolver_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
 analyzer/test/generated/all_the_rest_test: Crash #  try/finally
-analyzer/test/generated/ast_test: Crash #  try/finally
-analyzer/test/generated/compile_time_error_code_test: Crash #  try/finally
-analyzer/test/generated/element_test: Crash #  try/finally
-analyzer/test/generated/incremental_resolver_test: Crash #  try/finally
-analyzer/test/generated/incremental_scanner_test: Crash #  try/finally
+analyzer/test/generated/ast_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
+analyzer/test/generated/compile_time_error_code_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
+analyzer/test/generated/element_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
+analyzer/test/generated/incremental_resolver_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
+analyzer/test/generated/incremental_scanner_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
 analyzer/test/generated/java_core_test: Crash #  try/finally
 analyzer/test/generated/java_io_test: Crash #  try/finally
-analyzer/test/generated/non_error_resolver_test: Crash #  try/finally
-analyzer/test/generated/parser_test: Crash #  try/finally
-analyzer/test/generated/resolver_test: Crash #  try/finally
-analyzer/test/generated/scanner_test: Crash #  try/finally
-analyzer/test/generated/static_type_warning_code_test: Crash #  try/finally
-analyzer/test/generated/static_warning_code_test: Crash #  try/finally
-analyzer/test/generated/utilities_test: Crash #  try/finally
+analyzer/test/generated/non_error_resolver_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
+analyzer/test/generated/parser_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
+analyzer/test/generated/resolver_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
+analyzer/test/generated/scanner_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
+analyzer/test/generated/static_type_warning_code_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
+analyzer/test/generated/static_warning_code_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
+analyzer/test/generated/utilities_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
 analyzer/test/instrumentation/instrumentation_test: Crash #  try/finally
 analyzer/test/parse_compilation_unit_test: Crash # Instance of 'TypeOperator': type casts not implemented.
 analyzer/test/source/package_map_provider_test: Crash #  try/finally
-analyzer/test/source/package_map_resolver_test: Crash #  try/finally
+analyzer/test/source/package_map_resolver_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
 analyzer/test/src/context/cache_test: Crash #  try/finally
 analyzer/test/src/context/context_test: Crash #  try/finally
-analyzer/test/src/task/dart_test: Crash #  try/finally
+analyzer/test/src/task/dart_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
 analyzer/test/src/task/dart_work_manager_test: Crash #  try/finally
 analyzer/test/src/task/driver_test: Crash #  try/finally
 analyzer/test/src/task/general_test: Crash #  try/finally
-analyzer/test/src/task/incremental_element_builder_test: Crash #  try/finally
-analyzer/test/src/task/inputs_test: Crash #  try/finally
-analyzer/test/src/task/manager_test: Crash #  try/finally
-analyzer/test/src/task/model_test: Crash #  try/finally
-analyzer/test/src/util/asserts_test: Crash #  try/finally
-analyzer/test/src/util/lru_map_test: Crash #  try/finally
+analyzer/test/src/task/incremental_element_builder_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
+analyzer/test/src/task/inputs_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
+analyzer/test/src/task/manager_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
+analyzer/test/src/task/model_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
+analyzer/test/src/util/asserts_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
+analyzer/test/src/util/lru_map_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
 fixnum/test/int_32_test: Crash #  try/finally
 fixnum/test/int_64_test: Crash #  try/finally
 js_ast/test/printer_callback_test: Crash #  Unhandled node
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 544cf32..1aaf192 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -554,7 +554,8 @@
   }
 
   char* error;
-  Dart_Isolate isolate = Dart_CreateIsolate(NULL, NULL, NULL, NULL, &error);
+  Dart_Isolate isolate = Dart_CreateIsolate(
+      NULL, NULL, NULL, NULL, NULL, &error);
   if (isolate == NULL) {
     Log::PrintErr("Error: %s", error);
     free(error);
@@ -600,7 +601,7 @@
 
     // Now we create an isolate into which we load all the code that needs to
     // be in the snapshot.
-    if (Dart_CreateIsolate(NULL, NULL, NULL, NULL, &error) == NULL) {
+    if (Dart_CreateIsolate(NULL, NULL, NULL, NULL, NULL, &error) == NULL) {
       fprintf(stderr, "%s", error);
       free(error);
       exit(255);
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 7bb98a1..bb01402 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -579,6 +579,7 @@
 static Dart_Isolate CreateIsolateAndSetupHelper(const char* script_uri,
                                                 const char* main,
                                                 const char* package_root,
+                                                Dart_IsolateFlags* flags,
                                                 char** error,
                                                 int* exit_code) {
   ASSERT(script_uri != NULL);
@@ -588,6 +589,7 @@
   isolate = Dart_CreateIsolate(script_uri,
                                main,
                                isolate_snapshot_buffer,
+                               flags,
                                isolate_data,
                                error);
 
@@ -673,7 +675,11 @@
 static Dart_Isolate CreateIsolateAndSetup(const char* script_uri,
                                           const char* main,
                                           const char* package_root,
+                                          Dart_IsolateFlags* flags,
                                           void* data, char** error) {
+  // The VM should never call the isolate helper with a NULL flags.
+  ASSERT(flags != NULL);
+  ASSERT(flags->version == DART_FLAGS_CURRENT_VERSION);
   IsolateData* parent_isolate_data = reinterpret_cast<IsolateData*>(data);
   int exit_code = 0;
   if (script_uri == NULL) {
@@ -697,6 +703,7 @@
   return CreateIsolateAndSetupHelper(script_uri,
                                      main,
                                      package_root,
+                                     flags,
                                      error,
                                      &exit_code);
 }
@@ -834,8 +841,8 @@
 };
 
 
-static const char* ServiceRequestHandler(
-    const char* name,
+static const char* ServiceGetIOHandler(
+    const char* method,
     const char** param_keys,
     const char** param_values,
     intptr_t num_params,
@@ -957,7 +964,7 @@
   }
 
   Dart_RegisterIsolateServiceRequestCallback(
-        "io", &ServiceRequestHandler, NULL);
+        "getIO", &ServiceGetIOHandler, NULL);
 
   // Call CreateIsolateAndSetup which creates an isolate and loads up
   // the specified application script.
@@ -967,6 +974,7 @@
   Dart_Isolate isolate = CreateIsolateAndSetupHelper(script_name,
                                                      "main",
                                                      commandline_package_root,
+                                                     NULL,
                                                      &error,
                                                      &exit_code);
   if (isolate == NULL) {
diff --git a/runtime/bin/vmservice/server.dart b/runtime/bin/vmservice/server.dart
index 9818e58..bd84a2f 100644
--- a/runtime/bin/vmservice/server.dart
+++ b/runtime/bin/vmservice/server.dart
@@ -29,7 +29,7 @@
         return;
       }
       var serial = map['id'];
-      onMessage(serial, new Message.fromJsonRpc(map));
+      onMessage(serial, new Message.fromJsonRpc(this, map));
     } else {
       socket.close(BINARY_MESSAGE_ERROR_CODE, 'Message must be a string.');
     }
@@ -141,7 +141,7 @@
       request.response.close();
       return;
     }
-    var message = new Message.fromUri(request.uri);
+    var message = new Message.fromUri(this, request.uri);
     var client = new HttpRequestClient(request, _service);
     client.onMessage(null, message);
   }
diff --git a/runtime/bin/vmservice_dartium.cc b/runtime/bin/vmservice_dartium.cc
index 2df9a31..25af328 100644
--- a/runtime/bin/vmservice_dartium.cc
+++ b/runtime/bin/vmservice_dartium.cc
@@ -45,6 +45,7 @@
                                             "main",
                                             snapshot_buffer,
                                             NULL,
+                                            NULL,
                                             &error);
   if (!isolate) {
     fprintf(stderr, "Dart_CreateIsolate failed: %s\n", error);
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 7094b4b..89131ff 100755
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -685,6 +685,23 @@
  */
 DART_EXPORT const char* Dart_VersionString();
 
+
+/**
+ * Isolate specific flags are set when creating a new isolate using the
+ * Dart_IsolateFlags structure.
+ *
+ * Current version of flags is encoded in a 32-bit integer with 16 bits used
+ * for each part.
+ */
+
+#define DART_FLAGS_CURRENT_VERSION (0x00000001)
+
+typedef struct {
+  int32_t version;
+  bool enable_type_checks;
+  bool enable_asserts;
+} Dart_IsolateFlags;
+
 /**
  * An isolate creation and initialization callback function.
  *
@@ -723,6 +740,9 @@
  * \param package_root The package root path for this isolate to resolve
  *   package imports against. If this parameter is NULL, the package root path
  *   of the parent isolate should be used.
+ * \param flags Default flags for this isolate being spawned. Either inherited
+ *   from the spawning isolate or passed as parameters when spawning the
+ *   isolate from Dart code.
  * \param callback_data The callback data which was passed to the
  *   parent isolate when it was created by calling Dart_CreateIsolate().
  * \param error A structure into which the embedder can place a
@@ -734,6 +754,7 @@
 typedef Dart_Isolate (*Dart_IsolateCreateCallback)(const char* script_uri,
                                                    const char* main,
                                                    const char* package_root,
+                                                   Dart_IsolateFlags* flags,
                                                    void* callback_data,
                                                    char** error);
 
@@ -894,6 +915,7 @@
  *   Provided only for advisory purposes to improve debugging messages.
  * \param snapshot A buffer containing a snapshot of the isolate or
  *   NULL if no snapshot is provided.
+ * \param flags Pointer to VM specific flags or NULL for default flags.
  * \param callback_data Embedder data.  This data will be passed to
  *   the Dart_IsolateCreateCallback when new isolates are spawned from
  *   this parent isolate.
@@ -905,6 +927,7 @@
 DART_EXPORT Dart_Isolate Dart_CreateIsolate(const char* script_uri,
                                             const char* main,
                                             const uint8_t* snapshot,
+                                            Dart_IsolateFlags* flags,
                                             void* callback_data,
                                             char** error);
 /* TODO(turnidge): Document behavior when there is already a current
@@ -2817,35 +2840,36 @@
     void* user_data);
 
 /**
- * Register a Dart_ServiceRequestCallback to be called to handle requests
- * with name on a specific isolate. The callback will be invoked with the
- * current isolate set to the request target.
+ * Register a Dart_ServiceRequestCallback to be called to handle
+ * requests for the named rpc on a specific isolate. The callback will
+ * be invoked with the current isolate set to the request target.
  *
- * \param name The name of the command that this callback is responsible for.
+ * \param method The name of the method that this callback is responsible for.
  * \param callback The callback to invoke.
  * \param user_data The user data passed to the callback.
  *
- * NOTE: If multiple callbacks with the same name are registered, only the
- * last callback registered will be remembered.
+ * NOTE: If multiple callbacks with the same name are registered, only
+ * the last callback registered will be remembered.
  */
 DART_EXPORT void Dart_RegisterIsolateServiceRequestCallback(
-    const char* name,
+    const char* method,
     Dart_ServiceRequestCallback callback,
     void* user_data);
 
 /**
- * Register a Dart_ServiceRequestCallback to be called to handle requests
- * with name. The callback will be invoked without a current isolate.
+ * Register a Dart_ServiceRequestCallback to be called to handle
+ * requests for the named rpc. The callback will be invoked without a
+ * current isolate.
  *
- * \param name The name of the command that this callback is responsible for.
+ * \param method The name of the command that this callback is responsible for.
  * \param callback The callback to invoke.
  * \param user_data The user data passed to the callback.
  *
- * NOTE: If multiple callbacks with the same name are registered, only the
- * last callback registered will be remembered.
+ * NOTE: If multiple callbacks with the same name are registered, only
+ * the last callback registered will be remembered.
  */
 DART_EXPORT void Dart_RegisterRootServiceRequestCallback(
-    const char* name,
+    const char* method,
     Dart_ServiceRequestCallback callback,
     void* user_data);
 
diff --git a/runtime/lib/compact_hash.dart b/runtime/lib/compact_hash.dart
index 22af0a2..5bcb48e 100644
--- a/runtime/lib/compact_hash.dart
+++ b/runtime/lib/compact_hash.dart
@@ -13,15 +13,13 @@
   // The hash pattern is based on hashCode, but is guaranteed to be non-zero.
   // The length of _index is always a power of two, and there is always at
   // least one unoccupied entry.
+  // NOTE: When maps are deserialized, their _index and _hashMask is regenerated
+  // lazily by _regenerateIndex.
+  // TODO(koda): Consider also using null _index for tiny, linear-search tables.
   Uint32List _index = new Uint32List(_HashBase._INITIAL_INDEX_SIZE);
 
-  // Cached in-place mask for the hash pattern component. On 32-bit, the top
-  // bits are wasted to avoid Mint allocation.
-  // TODO(koda): Reclaim the bits by making the compiler treat hash patterns
-  // as unsigned words.
-  int _hashMask = internal.is64Bit ?
-      (1 << (32 - _HashBase._INITIAL_INDEX_BITS)) - 1 :
-      (1 << (30 - _HashBase._INITIAL_INDEX_BITS)) - 1;
+  // Cached in-place mask for the hash pattern component. 
+  int _hashMask = _HashBase._indexSizeToHashMask(_HashBase._INITIAL_INDEX_SIZE);
 
   // Fixed-length list of keys (set) or key/value at even/odd indices (map).
   List _data = new List(_HashBase._INITIAL_INDEX_SIZE);
@@ -67,7 +65,16 @@
   // Unused and deleted entries are marked by 0 and 1, respectively.
   static const int _UNUSED_PAIR = 0;
   static const int _DELETED_PAIR = 1;
-  
+
+  // On 32-bit, the top bits are wasted to avoid Mint allocation.
+  // TODO(koda): Reclaim the bits by making the compiler treat hash patterns
+  // as unsigned words.
+  static int _indexSizeToHashMask(int indexSize) {
+    int indexBits = indexSize.bitLength - 2;
+    return internal.is64Bit ? (1 << (32 - indexBits)) - 1 :
+                              (1 << (30 - indexBits)) - 1;
+  }
+
   static int _hashPattern(int fullHash, int hashMask, int size) {
     final int maskedHash = fullHash & hashMask;
     // TODO(koda): Consider keeping bit length and use left shift.
@@ -132,7 +139,8 @@
   
   void clear() {
     if (!isEmpty) {
-      _init(_index.length, _hashMask);
+      // Use _data.length, since _index might be null.
+      _init(_data.length, _hashMask);
     }
   }
 
@@ -155,6 +163,24 @@
       }
     }
   }
+
+  int _getIndexLength() {
+    return (_index == null) ? _regenerateIndex() : _index.length;
+  }
+
+  int _regenerateIndex() {
+    assert(_index == null);
+    _index = new Uint32List(_data.length);
+    assert(_hashMask == 0);
+    _hashMask = _HashBase._indexSizeToHashMask(_index.length);
+    final int tmpUsed = _usedData;
+    _usedData = 0;
+    for (int i = 0; i < tmpUsed; i += 2) {
+      // TODO(koda): Avoid redundant equality tests and stores into _data.
+      this[_data[i]] = _data[i + 1];
+    }
+    return _index.length;
+  }
   
   void _insert(K key, V value, int hashPattern, int i) {
     if (_usedData == _data.length) {
@@ -199,7 +225,7 @@
   }
   
   void operator[]=(K key, V value) {
-    final int size = _index.length;
+    final int size = _getIndexLength();
     final int sizeMask = size - 1;
     final int fullHash = _hashCode(key);
     final int hashPattern = _HashBase._hashPattern(fullHash, _hashMask, size);
@@ -213,7 +239,7 @@
   }
   
   V putIfAbsent(K key, V ifAbsent()) {
-    final int size = _index.length;
+    final int size = _getIndexLength();
     final int sizeMask = size - 1;
     final int maxEntries = size >> 1;
     final int fullHash = _hashCode(key);
@@ -236,7 +262,7 @@
   }
   
   V remove(Object key) {
-    final int size = _index.length;
+    final int size = _getIndexLength();
     final int sizeMask = size - 1;
     final int maxEntries = size >> 1;
     final int fullHash = _hashCode(key);
@@ -266,7 +292,7 @@
   
   // If key is absent, return _data (which is never a value).
   Object _getValueOrData(Object key) {
-    final int size = _index.length;
+    final int size = _getIndexLength();
     final int sizeMask = size - 1;
     final int maxEntries = size >> 1;
     final int fullHash = _hashCode(key);
diff --git a/runtime/lib/convert_patch.dart b/runtime/lib/convert_patch.dart
index 7b143ac..6d83969 100644
--- a/runtime/lib/convert_patch.dart
+++ b/runtime/lib/convert_patch.dart
@@ -31,7 +31,7 @@
     return super.fuse(next);
   }
 
-  // Allow intercepting of UTF8 decoding when builtin lists are passed.
+  // Allow intercepting of UTF-8 decoding when built-in lists are passed.
   /* patch */
   static String _convertIntercepted(
       bool allowMalformed, List<int> codeUnits, int start, int end) {
@@ -77,6 +77,13 @@
   void beginArray() {}
   void arrayElement() {}
   void endArray() {}
+
+  /**
+   * Read out the final result of parsing a JSON string.
+   *
+   * Must only be called when the entire input has been parsed.
+   */
+  get result;
 }
 
 /**
@@ -268,38 +275,41 @@
   // gets to the next state (not empty, doesn't allow a value).
 
   // State building-block constants.
-  static const int INSIDE_ARRAY = 1;
-  static const int INSIDE_OBJECT = 2;
-  static const int AFTER_COLON = 3;  // Always inside object.
+  static const int TOP_LEVEL         = 0;
+  static const int INSIDE_ARRAY      = 1;
+  static const int INSIDE_OBJECT     = 2;
+  static const int AFTER_COLON       = 3;  // Always inside object.
 
   static const int ALLOW_STRING_MASK = 8;  // Allowed if zero.
-  static const int ALLOW_VALUE_MASK = 4;  // Allowed if zero.
-  static const int ALLOW_VALUE = 0;
-  static const int STRING_ONLY = 4;
-  static const int NO_VALUES = 12;
+  static const int ALLOW_VALUE_MASK  = 4;  // Allowed if zero.
+  static const int ALLOW_VALUE       = 0;
+  static const int STRING_ONLY       = 4;
+  static const int NO_VALUES         = 12;
 
   // Objects and arrays are "empty" until their first property/element.
   // At this position, they may either have an entry or a close-bracket.
-  static const int EMPTY = 0;
-  static const int NON_EMPTY = 16;
-  static const int EMPTY_MASK = 16;  // Empty if zero.
+  static const int EMPTY             =  0;
+  static const int NON_EMPTY         = 16;
+  static const int EMPTY_MASK        = 16;  // Empty if zero.
 
-  static const int VALUE_READ_BITS = NO_VALUES | NON_EMPTY;
+  // Actual states                    : Context       | Is empty? | Next?
+  static const int STATE_INITIAL      = TOP_LEVEL     | EMPTY     | ALLOW_VALUE;
+  static const int STATE_END          = TOP_LEVEL     | NON_EMPTY | NO_VALUES;
 
-  // Actual states.
-  static const int STATE_INITIAL      = EMPTY | ALLOW_VALUE;
-  static const int STATE_END          = NON_EMPTY | NO_VALUES;
+  static const int STATE_ARRAY_EMPTY  = INSIDE_ARRAY  | EMPTY     | ALLOW_VALUE;
+  static const int STATE_ARRAY_VALUE  = INSIDE_ARRAY  | NON_EMPTY | NO_VALUES;
+  static const int STATE_ARRAY_COMMA  = INSIDE_ARRAY  | NON_EMPTY | ALLOW_VALUE;
 
-  static const int STATE_ARRAY_EMPTY  = INSIDE_ARRAY | EMPTY | ALLOW_VALUE;
-  static const int STATE_ARRAY_VALUE  = INSIDE_ARRAY | NON_EMPTY | NO_VALUES;
-  static const int STATE_ARRAY_COMMA  = INSIDE_ARRAY | NON_EMPTY | ALLOW_VALUE;
-
-  static const int STATE_OBJECT_EMPTY = INSIDE_OBJECT | EMPTY | STRING_ONLY;
+  static const int STATE_OBJECT_EMPTY = INSIDE_OBJECT | EMPTY     | STRING_ONLY;
   static const int STATE_OBJECT_KEY   = INSIDE_OBJECT | NON_EMPTY | NO_VALUES;
-  static const int STATE_OBJECT_COLON = AFTER_COLON | NON_EMPTY | ALLOW_VALUE;
-  static const int STATE_OBJECT_VALUE = AFTER_COLON | NON_EMPTY | NO_VALUES;
+  static const int STATE_OBJECT_COLON = AFTER_COLON   | NON_EMPTY | ALLOW_VALUE;
+  static const int STATE_OBJECT_VALUE = AFTER_COLON   | NON_EMPTY | NO_VALUES;
   static const int STATE_OBJECT_COMMA = INSIDE_OBJECT | NON_EMPTY | STRING_ONLY;
 
+  // Bits set in state after successfully reading a value.
+  // This transitions the state to expect the next punctuation.
+  static const int VALUE_READ_BITS    = NON_EMPTY | NO_VALUES;
+
   // Character code constants.
   static const int BACKSPACE       = 0x08;
   static const int TAB             = 0x09;
@@ -334,40 +344,40 @@
   static const int RBRACE          = 0x7d;
 
   // State of partial value at chunk split.
-  static const int NO_PARTIAL      = 0;
-  static const int PARTIAL_STRING  = 1;
-  static const int PARTIAL_NUMERAL = 2;
-  static const int PARTIAL_KEYWORD = 3;
-  static const int MASK_PARTIAL    = 3;
+  static const int NO_PARTIAL        =  0;
+  static const int PARTIAL_STRING    =  1;
+  static const int PARTIAL_NUMERAL   =  2;
+  static const int PARTIAL_KEYWORD   =  3;
+  static const int MASK_PARTIAL      =  3;
 
   // Partial states for numerals. Values can be |'ed with PARTIAL_NUMERAL.
-  static const int NUM_SIGN        =  0;  // After initial '-'.
-  static const int NUM_ZERO        =  4;  // After '0' as first digit.
-  static const int NUM_DIGIT       =  8;  // After digit, no '.' or 'e' seen.
-  static const int NUM_DOT         = 12;  // After '.'.
-  static const int NUM_DOT_DIGIT   = 16;  // After a decimal digit (after '.').
-  static const int NUM_E           = 20;  // After 'e' or 'E'.
-  static const int NUM_E_SIGN      = 24;  // After '-' or '+' after 'e' or 'E'.
-  static const int NUM_E_DIGIT     = 28;  // After exponent digit.
-  static const int NUM_SUCCESS     = 32;  // Never stored as partial state.
+  static const int NUM_SIGN          =  0;  // After initial '-'.
+  static const int NUM_ZERO          =  4;  // After '0' as first digit.
+  static const int NUM_DIGIT         =  8;  // After digit, no '.' or 'e' seen.
+  static const int NUM_DOT           = 12;  // After '.'.
+  static const int NUM_DOT_DIGIT     = 16;  // After a decimal digit (after '.').
+  static const int NUM_E             = 20;  // After 'e' or 'E'.
+  static const int NUM_E_SIGN        = 24;  // After '-' or '+' after 'e' or 'E'.
+  static const int NUM_E_DIGIT       = 28;  // After exponent digit.
+  static const int NUM_SUCCESS       = 32;  // Never stored as partial state.
 
   // Partial states for strings.
   static const int STR_PLAIN         =  0;   // Inside string, but not escape.
   static const int STR_ESCAPE        =  4;   // After '\'.
-  static const int STR_U             =  16;  // After '\u' and 0-3 hex digits.
+  static const int STR_U             = 16;   // After '\u' and 0-3 hex digits.
   static const int STR_U_COUNT_SHIFT =  2;   // Hex digit count in bits 2-3.
   static const int STR_U_VALUE_SHIFT =  5;   // Hex digit value in bits 5+.
 
   // Partial states for keywords.
   static const int KWD_TYPE_MASK     = 12;
-  static const int KWD_TYPE_SHIFT    = 2;
-  static const int KWD_NULL          = 0;  // Prefix of "null" seen.
-  static const int KWD_TRUE          = 4;  // Prefix of "true" seen.
-  static const int KWD_FALSE         = 8;  // Prefix of "false" seen.
-  static const int KWD_COUNT_SHIFT   = 4;  // Prefix length in bits 4+.
+  static const int KWD_TYPE_SHIFT    =  2;
+  static const int KWD_NULL          =  0;  // Prefix of "null" seen.
+  static const int KWD_TRUE          =  4;  // Prefix of "true" seen.
+  static const int KWD_FALSE         =  8;  // Prefix of "false" seen.
+  static const int KWD_COUNT_SHIFT   =  4;  // Prefix length in bits 4+.
 
   // Mask used to mask off two lower bits.
-  static const int TWO_BIT_MASK = 3;
+  static const int TWO_BIT_MASK      = 3;
 
   final _JsonListener listener;
 
@@ -514,7 +524,7 @@
    *
    * Used for number buffer (always copies ASCII, so encoding is not important).
    */
-  void copyCharsToList(int start, int end, List<int> target);
+  void copyCharsToList(int start, int end, List<int> target, int offset);
 
   /**
    * Build a string using input code units.
@@ -592,7 +602,7 @@
     assert(start < chunkEnd);
     int length = chunkEnd - start;
     var buffer = new _NumberBuffer(length);
-    copyCharsToList(start, chunkEnd, buffer.list);
+    copyCharsToList(start, chunkEnd, buffer.list, 0);
     buffer.length = length;
     return buffer;
   }
@@ -800,9 +810,6 @@
     int state = this.state;
     while (position < length) {
       int char = getChar(position);
-      if (char == null) {
-        print("[[[$chunk]]] - $position - ${chunk.runtimeType}");
-      }
       switch (char) {
         case SPACE:
         case CARRIAGE_RETURN:
@@ -901,7 +908,7 @@
   /**
    * Parses a "true" literal starting at [position].
    *
-   * [:source[position]:] must be "t".
+   * The character `source[position]` must be "t".
    */
   int parseTrue(int position) {
     assert(getChar(position) == CHAR_t);
@@ -920,7 +927,7 @@
   /**
    * Parses a "false" literal starting at [position].
    *
-   * [:source[position]:] must be "f".
+   * The character `source[position]` must be "f".
    */
   int parseFalse(int position) {
     assert(getChar(position) == CHAR_f);
@@ -940,7 +947,7 @@
   /**
    * Parses a "null" literal starting at [position].
    *
-   * [:source[position]:] must be "n".
+   * The character `source[position]` must be "n".
    */
   int parseNull(int position) {
     assert(getChar(position) == CHAR_n);
@@ -1000,7 +1007,7 @@
         return position;
       }
       if (char < SPACE) {
-        fail(position - 1, "Control character in string");
+        return fail(position - 1, "Control character in string");
       }
     }
     beginString();
@@ -1059,8 +1066,7 @@
       int char = getChar(position++);
       if (char > BACKSLASH) continue;
       if (char < SPACE) {
-        fail(position - 1);  // Control character in string.
-        return;
+        return fail(position - 1);  // Control character in string.
       }
       if (char == QUOTE) {
         int quotePosition = position - 1;
@@ -1171,7 +1177,7 @@
   int finishChunkNumber(int state, int start, int end, _NumberBuffer buffer) {
     if (state == NUM_ZERO) {
       listener.handleNumber(0);
-      return;
+      return end;
     }
     if (end > start) {
       addNumberChunk(buffer, start, end, 0);
@@ -1201,86 +1207,84 @@
     // Break this block when the end of the number literal is reached.
     // At that time, position points to the next character, and isDouble
     // is set if the literal contains a decimal point or an exponential.
-    parsing: {
-      if (char == MINUS) {
-        sign = -1;
-        position++;
-        if (position == length) return beginChunkNumber(NUM_SIGN, start);
-        char = getChar(position);
+    if (char == MINUS) {
+      sign = -1;
+      position++;
+      if (position == length) return beginChunkNumber(NUM_SIGN, start);
+      char = getChar(position);
+    }
+    int digit = char ^ CHAR_0;
+    if (digit > 9) {
+      if (sign < 0) {
+        fail(position, "Missing expected digit");
+      } else {
+        // If it doesn't even start out as a numeral.
+        fail(position, "Unexpected character");
       }
-      int digit = char ^ CHAR_0;
-      if (digit > 9) {
-        if (sign < 0) {
-          fail(position, "Missing expected digit");
-        } else {
-          // If it doesn't even start out as a numeral.
-          fail(position, "Unexpected character");
-        }
-      }
-      if (digit == 0) {
+    }
+    if (digit == 0) {
+      position++;
+      if (position == length) return beginChunkNumber(NUM_ZERO, start);
+      char = getChar(position);
+      digit = char ^ CHAR_0;
+      // If starting with zero, next character must not be digit.
+      if (digit <= 9) fail(position);
+    } else {
+      do {
+        intValue = 10 * intValue + digit;
         position++;
-        if (position == length) return beginChunkNumber(NUM_ZERO, start);
+        if (position == length) return beginChunkNumber(NUM_DIGIT, start);
         char = getChar(position);
         digit = char ^ CHAR_0;
-        // If starting with zero, next character must not be digit.
-        if (digit <= 9) fail(position);
-      } else {
-        do {
-          intValue = 10 * intValue + digit;
-          position++;
-          if (position == length) return beginChunkNumber(NUM_DIGIT, start);
-          char = getChar(position);
-          digit = char ^ CHAR_0;
-        } while (digit <= 9);
-      }
-      if (char == DECIMALPOINT) {
-        isDouble = true;
+      } while (digit <= 9);
+    }
+    if (char == DECIMALPOINT) {
+      isDouble = true;
+      doubleValue = intValue.toDouble();
+      intValue = 0;
+      position++;
+      if (position == length) return beginChunkNumber(NUM_DOT, start);
+      char = getChar(position);
+      digit = char ^ CHAR_0;
+      if (digit > 9) fail(position);
+      do {
+        doubleValue = 10.0 * doubleValue + digit;
+        intValue -= 1;
+        position++;
+        if (position == length) return beginChunkNumber(NUM_DOT_DIGIT, start);
+        char = getChar(position);
+        digit = char ^ CHAR_0;
+      } while (digit <= 9);
+    }
+    if ((char | 0x20) == CHAR_e) {
+      if (!isDouble) {
         doubleValue = intValue.toDouble();
         intValue = 0;
+        isDouble = true;
+      }
+      position++;
+      if (position == length) return beginChunkNumber(NUM_E, start);
+      char = getChar(position);
+      int expSign = 1;
+      int exponent = 0;
+      if (char == PLUS || char == MINUS) {
+        expSign = 0x2C - char;  // -1 for MINUS, +1 for PLUS
         position++;
-        if (position == length) return beginChunkNumber(NUM_DOT, start);
+        if (position == length) return beginChunkNumber(NUM_E_SIGN, start);
+        char = getChar(position);
+      }
+      digit = char ^ CHAR_0;
+      if (digit > 9) {
+        fail(position, "Missing expected digit");
+      }
+      do {
+        exponent = 10 * exponent + digit;
+        position++;
+        if (position == length) return beginChunkNumber(NUM_E_DIGIT, start);
         char = getChar(position);
         digit = char ^ CHAR_0;
-        if (digit > 9) fail(position);
-        do {
-          doubleValue = 10.0 * doubleValue + digit;
-          intValue -= 1;
-          position++;
-          if (position == length) return beginChunkNumber(NUM_DOT_DIGIT, start);
-          char = getChar(position);
-          digit = char ^ CHAR_0;
-        } while (digit <= 9);
-      }
-      if ((char | 0x20) == CHAR_e) {
-        if (!isDouble) {
-          doubleValue = intValue.toDouble();
-          intValue = 0;
-          isDouble = true;
-        }
-        position++;
-        if (position == length) return beginChunkNumber(NUM_E, start);
-        char = getChar(position);
-        int expSign = 1;
-        int exponent = 0;
-        if (char == PLUS || char == MINUS) {
-          expSign = 0x2C - char;  // -1 for MINUS, +1 for PLUS
-          position++;
-          if (position == length) return beginChunkNumber(NUM_E_SIGN, start);
-          char = getChar(position);
-        }
-        digit = char ^ CHAR_0;
-        if (digit > 9) {
-          fail(position, "Missing expected digit");
-        }
-        do {
-          exponent = 10 * exponent + digit;
-          position++;
-          if (position == length) return beginChunkNumber(NUM_E_DIGIT, start);
-          char = getChar(position);
-          digit = char ^ CHAR_0;
-        } while (digit <= 9);
-        intValue += expSign * exponent;
-      }
+      } while (digit <= 9);
+      intValue += expSign * exponent;
     }
     if (!isDouble) {
       listener.handleNumber(sign * intValue);
@@ -1314,7 +1318,7 @@
     return position;
   }
 
-  int fail(int position, [String message]) {
+  fail(int position, [String message]) {
     if (message == null) {
       message = "Unexpected character";
       if (position == chunkEnd) message = "Unexpected end of input";
diff --git a/runtime/lib/double.cc b/runtime/lib/double.cc
index 4173c140..dbeb447 100644
--- a/runtime/lib/double.cc
+++ b/runtime/lib/double.cc
@@ -300,6 +300,14 @@
   return Bool::Get(signbit(dval) && !isnan(dval)).raw();
 }
 
+
+DEFINE_NATIVE_ENTRY(Double_flipSignBit, 1) {
+  const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0));
+  const double in_val = arg.value();
+  const int64_t bits = bit_cast<int64_t, double>(in_val) ^ kSignBitDouble;
+  return Double::New(bit_cast<double, int64_t>(bits));
+}
+
 // Add here only functions using/referring to old-style casts.
 
 }  // namespace dart
diff --git a/runtime/lib/double.dart b/runtime/lib/double.dart
index 95f026d..280bf3b 100644
--- a/runtime/lib/double.dart
+++ b/runtime/lib/double.dart
@@ -47,12 +47,11 @@
   }
   double _remainder(double other) native "Double_remainder";
   double operator -() {
-    if (this == 0.0) {
-      // -0.0 is canonicalized by the VM's parser, therefore no cycles.
-      return isNegative ? 0.0 : -0.0;
-    }
-    return 0.0 - this;
+    // Handles properly 0.0, NAN, and other doubles.
+    return this._flipSignBit;
   }
+  double get _flipSignBit native "Double_flipSignBit";
+
   bool operator ==(other) {
     if (!(other is num)) return false;
     return _equal(other.toDouble());
diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc
index 1e08dad..378e6eb 100644
--- a/runtime/lib/isolate.cc
+++ b/runtime/lib/isolate.cc
@@ -171,18 +171,22 @@
     return false;
   }
 
+  Dart_IsolateFlags api_flags;
+  state->isolate_flags()->CopyTo(&api_flags);
+
   void* init_data = parent_isolate->init_callback_data();
   Isolate* child_isolate = reinterpret_cast<Isolate*>(
       (callback)(state->script_url(),
                  state->function_name(),
                  state->package_root(),
+                 &api_flags,
                  init_data,
                  error));
   if (child_isolate == NULL) {
     return false;
   }
   if (!state->is_spawn_uri()) {
-    // For isolates spawned using the spawnFunction semantics we set
+    // For isolates spawned using the spawn semantics we set
     // the origin_id to the origin_id of the parent isolate.
     child_isolate->set_origin_id(parent_isolate->origin_id());
   }
@@ -243,13 +247,14 @@
 }
 
 
-DEFINE_NATIVE_ENTRY(Isolate_spawnUri, 6) {
+DEFINE_NATIVE_ENTRY(Isolate_spawnUri, 7) {
   GET_NON_NULL_NATIVE_ARGUMENT(SendPort, port, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(String, uri, arguments->NativeArgAt(1));
   GET_NON_NULL_NATIVE_ARGUMENT(Instance, args, arguments->NativeArgAt(2));
   GET_NON_NULL_NATIVE_ARGUMENT(Instance, message, arguments->NativeArgAt(3));
   GET_NON_NULL_NATIVE_ARGUMENT(Bool, paused, arguments->NativeArgAt(4));
-  GET_NATIVE_ARGUMENT(String, package_root, arguments->NativeArgAt(5));
+  GET_NATIVE_ARGUMENT(Bool, checked, arguments->NativeArgAt(5));
+  GET_NATIVE_ARGUMENT(String, package_root, arguments->NativeArgAt(6));
 
   // Canonicalize the uri with respect to the current isolate.
   char* error = NULL;
@@ -270,12 +275,19 @@
     utf8_package_root[len] = '\0';
   }
 
-  Spawn(isolate, new IsolateSpawnState(port.Id(),
-                                       canonical_uri,
-                                       utf8_package_root,
-                                       args,
-                                       message,
-                                       paused.value()));
+  IsolateSpawnState* state = new IsolateSpawnState(port.Id(),
+                                                   canonical_uri,
+                                                   utf8_package_root,
+                                                   args,
+                                                   message,
+                                                   paused.value());
+  // If we were passed a value then override the default flags state for
+  // checked mode.
+  if (!checked.IsNull()) {
+    state->isolate_flags()->set_checked(checked.value());
+  }
+
+  Spawn(isolate, state);
   return Object::null();
 }
 
diff --git a/runtime/lib/isolate_patch.dart b/runtime/lib/isolate_patch.dart
index 100d951..1fd87bf 100644
--- a/runtime/lib/isolate_patch.dart
+++ b/runtime/lib/isolate_patch.dart
@@ -303,8 +303,7 @@
 
   /* patch */ static Future<Isolate> spawnUri(
       Uri uri, List<String> args, var message,
-      { bool paused: false, Uri packageRoot }) {
-    // `paused` isn't handled yet.
+      { bool paused: false, bool checked, Uri packageRoot }) {
     RawReceivePort readyPort;
     try {
       // The VM will invoke [_startIsolate] and not `main`.
@@ -312,7 +311,7 @@
       var packageRootString =
           (packageRoot == null) ? null : packageRoot.toString();
       _spawnUri(readyPort.sendPort, uri.toString(), args, message,
-                paused, packageRootString);
+                paused, checked, packageRootString);
       Completer completer = new Completer<Isolate>.sync();
       readyPort.handler = (readyMessage) {
         readyPort.close();
@@ -354,7 +353,7 @@
 
   static void _spawnUri(SendPort readyPort, String uri,
                         List<String> args, var message,
-                        bool paused, String packageRoot)
+                        bool paused, bool checked, String packageRoot)
       native "Isolate_spawnUri";
 
   static void _sendOOB(port, msg) native "Isolate_sendOOB";
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index d90f69c..a7c11d7 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -2072,11 +2072,5 @@
   return Bool::Get(a.IsSubtypeOf(b, NULL)).raw();
 }
 
-DEFINE_NATIVE_ENTRY(TypeMirror_moreSpecificTest, 2) {
-  GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, a, arguments->NativeArgAt(0));
-  GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, b, arguments->NativeArgAt(1));
-  return Bool::Get(a.IsMoreSpecificThan(b, NULL)).raw();
-}
-
 
 }  // namespace dart
diff --git a/runtime/lib/mirrors_impl.dart b/runtime/lib/mirrors_impl.dart
index ee139b6..2e55bfd 100644
--- a/runtime/lib/mirrors_impl.dart
+++ b/runtime/lib/mirrors_impl.dart
@@ -75,9 +75,6 @@
 bool _subtypeTest(Type a, Type b)
     native 'TypeMirror_subtypeTest';
 
-bool _moreSpecificTest(Type a, Type b)
-    native 'TypeMirror_moreSpecificTest';
-
 class _AccessorCacheAssociation {
   String key;
   Function value;
@@ -392,7 +389,7 @@
   }
 
   // LocalInstanceMirrors always reflect local instances
-  bool hasReflectee = true;
+  bool get hasReflectee => true;
 
   get reflectee => _reflectee;
 
@@ -878,8 +875,8 @@
   bool isAssignableTo(TypeMirror other) {
     if (other == currentMirrorSystem().dynamicType) return true;
     if (other == currentMirrorSystem().voidType) return false;
-    return _moreSpecificTest(_reflectedType, other._reflectedType)
-        || _moreSpecificTest(other._reflectedType, _reflectedType);
+    return _subtypeTest(_reflectedType, other._reflectedType)
+        || _subtypeTest(other._reflectedType, _reflectedType);
   }
 
   bool isSubclassOf(ClassMirror other) {
@@ -1093,8 +1090,8 @@
   bool isAssignableTo(TypeMirror other) {
     if (other == currentMirrorSystem().dynamicType) return true;
     if (other == currentMirrorSystem().voidType) return false;
-    return _moreSpecificTest(_reflectedType, other._reflectedType)
-        || _moreSpecificTest(other._reflectedType, _reflectedType);
+    return _subtypeTest(_reflectedType, other._reflectedType)
+        || _subtypeTest(other._reflectedType, _reflectedType);
   }
 
   static DeclarationMirror _TypeVariableMirror_owner(reflectee)
@@ -1198,8 +1195,8 @@
   bool isAssignableTo(TypeMirror other) {
     if (other == currentMirrorSystem().dynamicType) return true;
     if (other == currentMirrorSystem().voidType) return false;
-    return _moreSpecificTest(_reflectedType, other._reflectedType)
-        || _moreSpecificTest(other._reflectedType, _reflectedType);
+    return _subtypeTest(_reflectedType, other._reflectedType)
+        || _subtypeTest(other._reflectedType, _reflectedType);
   }
 
   static _nativeReferent(reflectedType)
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index d67dafc..fe88b85 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -271,7 +271,7 @@
           location, instance_type_name, type_name,
           dst_name, Object::null_string());
     } else {
-      ASSERT(Isolate::Current()->TypeChecksEnabled());
+      ASSERT(isolate->flags().type_checks());
       bound_error_message = String::New(bound_error.ToErrorCString());
       Exceptions::CreateAndThrowTypeError(
           location, instance_type_name, Symbols::Empty(),
diff --git a/runtime/observatory/lib/debugger.dart b/runtime/observatory/lib/debugger.dart
index d432e88..628b2a9 100644
--- a/runtime/observatory/lib/debugger.dart
+++ b/runtime/observatory/lib/debugger.dart
@@ -8,4 +8,4 @@
 import 'package:observatory/service.dart';
 
 part 'src/debugger/debugger.dart';
-part 'src/debugger/source_location.dart';
+part 'src/debugger/debugger_location.dart';
diff --git a/runtime/observatory/lib/src/debugger/source_location.dart b/runtime/observatory/lib/src/debugger/debugger_location.dart
similarity index 87%
rename from runtime/observatory/lib/src/debugger/source_location.dart
rename to runtime/observatory/lib/src/debugger/debugger_location.dart
index 91da581..cca7a1c 100644
--- a/runtime/observatory/lib/src/debugger/source_location.dart
+++ b/runtime/observatory/lib/src/debugger/debugger_location.dart
@@ -4,10 +4,10 @@
 
 part of debugger;
 
-class SourceLocation {
-  SourceLocation.file(this.script, this.line, this.col);
-  SourceLocation.func(this.function);
-  SourceLocation.error(this.errorMessage);
+class DebuggerLocation {
+  DebuggerLocation.file(this.script, this.line, this.col);
+  DebuggerLocation.func(this.function);
+  DebuggerLocation.error(this.errorMessage);
 
   static RegExp sourceLocMatcher = new RegExp(r'^([^\d:][^:]+:)?(\d+)(:\d+)?');
   static RegExp functionMatcher = new RegExp(r'^([^.]+)([.][^.]+)?');
@@ -23,7 +23,7 @@
   ///   main              -  function
   ///   FormatException   -  constructor
   ///   _SHA1._updateHash -  method
-  static Future<SourceLocation> parse(Debugger debugger, String locDesc) {
+  static Future<DebuggerLocation> parse(Debugger debugger, String locDesc) {
     if (locDesc == '') {
       // Special case: '' means return current location.
       return _currentLocation(debugger);
@@ -38,27 +38,27 @@
     if (match != null) {
       return _parseFunction(debugger, match);
     }
-    return new Future.value(new SourceLocation.error(
+    return new Future.value(new DebuggerLocation.error(
         "Invalid source location '${locDesc}'"));
   }
 
-  static Future<SourceLocation> _currentLocation(Debugger debugger) {
+  static Future<DebuggerLocation> _currentLocation(Debugger debugger) {
     ServiceMap stack = debugger.stack;
     if (stack == null || stack['frames'].length == 0) {
-      return new Future.value(new SourceLocation.error(
+      return new Future.value(new DebuggerLocation.error(
           'A script must be provided when the stack is empty'));
     }
     var frame = stack['frames'][debugger.currentFrame];
-    Script script = frame['script'];
+    Script script = frame.location.script;
     return script.load().then((_) {
-      var line = script.tokenToLine(frame['tokenPos']);
+      var line = script.tokenToLine(frame.location.tokenPos);
       // TODO(turnidge): Pass in the column here once the protocol supports it.
-      return new Future.value(new SourceLocation.file(script, line, null));
+      return new Future.value(new DebuggerLocation.file(script, line, null));
     });
   }
 
-  static Future<SourceLocation> _parseScriptLine(Debugger debugger,
-                                                 Match match) {
+  static Future<DebuggerLocation> _parseScriptLine(Debugger debugger,
+                                                   Match match) {
     var scriptName = match.group(1);
     if (scriptName != null) {
       scriptName = scriptName.substring(0, scriptName.length - 1);
@@ -74,11 +74,11 @@
                ? int.parse(colStr, onError:(_) => -1)
                : null);
     if (line == -1) {
-      return new Future.value(new SourceLocation.error(
+      return new Future.value(new DebuggerLocation.error(
           "Line '${lineStr}' must be an integer"));
     }
     if (col == -1) {
-      return new Future.value(new SourceLocation.error(
+      return new Future.value(new DebuggerLocation.error(
           "Column '${colStr}' must be an integer"));
     }
 
@@ -86,23 +86,23 @@
       // Resolve the script.
       return _lookupScript(debugger.isolate, scriptName).then((scripts) {
         if (scripts.length == 0) {
-          return new SourceLocation.error("Script '${scriptName}' not found");
+          return new DebuggerLocation.error("Script '${scriptName}' not found");
         } else if (scripts.length == 1) {
-          return new SourceLocation.file(scripts[0], line, col);
+          return new DebuggerLocation.file(scripts[0], line, col);
         } else {
           // TODO(turnidge): Allow the user to disambiguate.
-          return new SourceLocation.error("Script '${scriptName}' is ambigous");
+          return new DebuggerLocation.error("Script '${scriptName}' is ambigous");
         }
       });
     } else {
       // No script provided.  Default to top of stack for now.
       ServiceMap stack = debugger.stack;
       if (stack == null || stack['frames'].length == 0) {
-        return new Future.value(new SourceLocation.error(
+        return new Future.value(new DebuggerLocation.error(
             'A script must be provided when the stack is empty'));
       }
-      Script script = stack['frames'][0]['script'];
-      return new Future.value(new SourceLocation.file(script, line, col));
+      Script script = stack['frames'][0].location.script;
+      return new Future.value(new DebuggerLocation.file(script, line, col));
     }
   }
 
@@ -198,7 +198,7 @@
 
   // TODO(turnidge): This does not handle named functions which are
   // inside of named functions, e.g. foo.bar.baz.
-  static Future<SourceLocation> _parseFunction(Debugger debugger,
+  static Future<DebuggerLocation> _parseFunction(Debugger debugger,
                                                Match match) {
     Isolate isolate = debugger.isolate;
     var base = match.group(1);
@@ -238,16 +238,16 @@
         }
       }
       if (functions.length == 0) {
-        return new SourceLocation.error(
+        return new DebuggerLocation.error(
             "Function '${match.group(0)}' not found");
       } else if (functions.length == 1) {
-        return new SourceLocation.func(functions[0]);
+        return new DebuggerLocation.func(functions[0]);
       } else {
         // TODO(turnidge): Allow the user to disambiguate.
-        return new SourceLocation.error(
+        return new DebuggerLocation.error(
             "Function '${match.group(0)}' is ambigous");
       }
-      return new SourceLocation.error('foo');
+      return new DebuggerLocation.error('foo');
     });
   }
 
diff --git a/runtime/observatory/lib/src/elements/class_view.dart b/runtime/observatory/lib/src/elements/class_view.dart
index a7cdf07..d839614 100644
--- a/runtime/observatory/lib/src/elements/class_view.dart
+++ b/runtime/observatory/lib/src/elements/class_view.dart
@@ -45,7 +45,7 @@
   }
 
   void attached() {
-    library.variables.forEach((variable) => variable.reload());
+    cls.fields.forEach((field) => field.reload());
   }
 
   Future refresh() {
@@ -54,7 +54,7 @@
     mostRetained = null;
     var loads = [];
     loads.add(cls.reload());
-    cls.variables.forEach((variable) => loads.add(variable.reload()));
+    cls.fields.forEach((field) => loads.add(field.reload()));
     return Future.wait(loads);
   }
 
diff --git a/runtime/observatory/lib/src/elements/class_view.html b/runtime/observatory/lib/src/elements/class_view.html
index dc4121e..10f67fc 100644
--- a/runtime/observatory/lib/src/elements/class_view.html
+++ b/runtime/observatory/lib/src/elements/class_view.html
@@ -45,8 +45,7 @@
         <div class="memberItem">
           <div class="memberName">script</div>
           <div class="memberValue">
-            <script-ref ref="{{ cls.script }}" pos="{{ cls.tokenPos }}">
-            </script-ref>
+            <source-link location="{{ cls.location }}"></source-link>
           </div>
         </div>
 
@@ -208,10 +207,8 @@
     <hr>
 
     <div class="content-centered-big">
-      <script-inset script="{{ cls.script }}"
-                    startPos="{{ cls.tokenPos }}"
-                    endPos="{{ cls.endTokenPos }}">
-      </script-inset>
+      <source-inset location="{{ cls.location }}">
+      </source-inset>
     </div>
 
     <view-footer></view-footer>
diff --git a/runtime/observatory/lib/src/elements/context_ref.html b/runtime/observatory/lib/src/elements/context_ref.html
index deb767b..82e313d 100644
--- a/runtime/observatory/lib/src/elements/context_ref.html
+++ b/runtime/observatory/lib/src/elements/context_ref.html
@@ -16,11 +16,12 @@
               <any-service-ref ref="{{ ref.parentContext }}"></any-service-ref>
             </div>
           </div>
-          <template repeat="{{ variable in ref.variables }}">
+          <template repeat="{{ index in ref.variables.asMap().keys }}">
             <div class="memberItem">
-              <div class="memberName">[{{ variable['index']}}]</div>
+              <div class="memberName">[{{ index }}]</div>
               <div class="memberValue">
-                <any-service-ref ref="{{ variable['value'] }}"></any-service-ref>
+                <any-service-ref ref="{{ ref.variables[index]['value'] }}">
+                </any-service-ref>
               </div>
             </div>
           </template>
diff --git a/runtime/observatory/lib/src/elements/context_view.html b/runtime/observatory/lib/src/elements/context_view.html
index bf61815..efffcb1 100644
--- a/runtime/observatory/lib/src/elements/context_view.html
+++ b/runtime/observatory/lib/src/elements/context_view.html
@@ -31,12 +31,14 @@
         <div class="memberList">
           <div class="memberItem">&nbsp;</div>
 
-          <div class="memberItem">
-            <div class="memberName">parent context</div>
-            <div class="memberValue">
-              <any-service-ref ref="{{ context.parentContext }}"></any-service-ref>
+          <template if="{{ context.parentContext != null }}">
+            <div class="memberItem">
+              <div class="memberName">parent context</div>
+              <div class="memberValue">
+                <any-service-ref ref="{{ context.parentContext }}"></any-service-ref>
+              </div>
             </div>
-          </div>
+          </template>
         </div>
       </div>
 
@@ -47,11 +49,13 @@
           variables ({{ context.variables.length }})
           <curly-block expand="{{ context.variables.length <= 8 }}">
             <div class="memberList">
-              <template repeat="{{ variable in context.variables }}">
+              <template repeat="{{ index in context.variables.asMap().keys }}">
                 <div class="memberItem">
-                  <div class="memberName">[{{ variable['index']}}]</div>
+                  <div class="memberName">[{{ index }}]</div>
                   <div class="memberValue">
-                    <any-service-ref ref="{{ variable['value'] }}"></any-service-ref>
+                    <any-service-ref
+                       ref="{{ context.variables[index]['value'] }}">
+                    </any-service-ref>
                   </div>
                 </div>
               </template>
diff --git a/runtime/observatory/lib/src/elements/debugger.dart b/runtime/observatory/lib/src/elements/debugger.dart
index 9fc8df5..70d8516 100644
--- a/runtime/observatory/lib/src/elements/debugger.dart
+++ b/runtime/observatory/lib/src/elements/debugger.dart
@@ -375,7 +375,7 @@
       return new Future.value(null);
     }
     var arg = (args.length == 0 ? '' : args[0]);
-    var loc = await SourceLocation.parse(debugger, arg);
+    var loc = await DebuggerLocation.parse(debugger, arg);
     if (loc.valid) {
       if (loc.function != null) {
         try {
@@ -414,8 +414,8 @@
     if (args.length != 1) {
       return new Future.value([args.join('')]);
     }
-    // TODO - fix SourceLocation complete
-    return new Future.value(SourceLocation.complete(debugger, args[0]));
+    // TODO - fix DebuggerLocation complete
+    return new Future.value(DebuggerLocation.complete(debugger, args[0]));
   }
 
   String helpShort = 'Add a breakpoint by source location or function name';
@@ -456,7 +456,7 @@
       return new Future.value(null);
     }
     var arg = (args.length == 0 ? '' : args[0]);
-    return SourceLocation.parse(debugger, arg).then((loc) {
+    return DebuggerLocation.parse(debugger, arg).then((loc) {
       if (loc.valid) {
         if (loc.function != null) {
           debugger.console.print(
@@ -472,10 +472,10 @@
         }
 
         for (var bpt in debugger.isolate.breakpoints.values) {
-          var script = bpt.script;
+          var script = bpt.location.script;
           if (script.id == loc.script.id) {
             assert(script.loaded);
-            var line = script.tokenToLine(bpt.tokenPos);
+            var line = script.tokenToLine(bpt.location.tokenPos);
             if (line == loc.line) {
               return debugger.isolate.removeBreakpoint(bpt).then((result) {
                 if (result is DartError) {
@@ -498,7 +498,7 @@
     if (args.length != 1) {
       return new Future.value([args.join('')]);
     }
-    return new Future.value(SourceLocation.complete(debugger, args[0]));
+    return new Future.value(DebuggerLocation.complete(debugger, args[0]));
   }
 
   String helpShort = 'Remove a breakpoint by source location or function name';
@@ -583,8 +583,8 @@
     bpts.sort((a, b) => a.number - b.number);
     for (var bpt in bpts) {
       var bpId = bpt.number;
-      var script = bpt.script;
-      var tokenPos = bpt.tokenPos;
+      var script = bpt.location.script;
+      var tokenPos = bpt.location.tokenPos;
       var line = script.tokenToLine(tokenPos);
       var col = script.tokenToCol(tokenPos);
       if (!bpt.resolved) {
@@ -982,11 +982,11 @@
           "Paused at isolate exit (type 'continue' to exit the isolate')");
     }
     if (stack['frames'].length > 0) {
-      var frame = stack['frames'][0];
-      var script = frame['script'];
+      Frame frame = stack['frames'][0];
+      var script = frame.location.script;
       script.load().then((_) {
-        var line = script.tokenToLine(frame['tokenPos']);
-        var col = script.tokenToCol(frame['tokenPos']);
+        var line = script.tokenToLine(frame.location.tokenPos);
+        var col = script.tokenToCol(frame.location.tokenPos);
         if (event.breakpoint != null) {
           var bpId = event.breakpoint.number;
           console.print('Paused at breakpoint ${bpId} at '
@@ -1018,10 +1018,10 @@
       default:
         break;
     }
-    var script = bpt.script;
+    var script = bpt.location.script;
     return script.load().then((_) {
       var bpId = bpt.number;
-      var tokenPos = bpt.tokenPos;
+      var tokenPos = bpt.location.tokenPos;
       var line = script.tokenToLine(tokenPos);
       var col = script.tokenToCol(tokenPos);
       if (bpt.resolved) {
@@ -1226,11 +1226,11 @@
   @observable int currentFrame;
   ObservatoryDebugger debugger;
 
-  _addFrame(List frameList, ObservableMap frameInfo) {
+  _addFrame(List frameList, Frame frameInfo) {
     DebuggerFrameElement frameElement = new Element.tag('debugger-frame');
     frameElement.frame = frameInfo;
 
-    if (frameInfo['index'] == currentFrame) {
+    if (frameInfo.index == currentFrame) {
       frameElement.setCurrent(true);
     } else {
       frameElement.setCurrent(false);
@@ -1243,7 +1243,7 @@
     frameList.insert(0, li);
   }
 
-  _addMessage(List messageList, ServiceMap messageInfo) {
+  _addMessage(List messageList, ServiceMessage messageInfo) {
     DebuggerMessageElement messageElement = new Element.tag('debugger-message');
     messageElement.message = messageInfo;
 
@@ -1347,7 +1347,7 @@
     List frameElements = $['frameList'].children;
     for (var frameElement in frameElements) {
       var dbgFrameElement = frameElement.children[0];
-      if (dbgFrameElement.frame['index'] == currentFrame) {
+      if (dbgFrameElement.frame.index == currentFrame) {
         dbgFrameElement.setCurrent(true);
       } else {
         dbgFrameElement.setCurrent(false);
@@ -1385,7 +1385,7 @@
 
 @CustomTag('debugger-frame')
 class DebuggerFrameElement extends ObservatoryElement {
-  @published ObservableMap frame;
+  @published Frame frame;
 
   // Is this the current frame?
   bool _current = false;
@@ -1395,7 +1395,7 @@
 
   void setCurrent(bool value) {
     busy = true;
-    frame['function'].load().then((func) {
+    frame.function.load().then((func) {
       _current = value;
       var frameOuter = $['frameOuter'];
       if (_current) {
@@ -1423,18 +1423,16 @@
 
   DebuggerFrameElement.created() : super.created();
 
-  bool matchFrame(ObservableMap newFrame) {
-    return newFrame['function'].id == frame['function'].id;
+  bool matchFrame(Frame newFrame) {
+    return newFrame.function.id == frame.function.id;
   }
 
-  void updateFrame(ObservableMap newFrame) {
+  void updateFrame(Frame newFrame) {
     assert(matchFrame(newFrame));
-    frame['index'] = newFrame['index'];
-    frame['tokenPos'] = newFrame['tokenPos'];
-    frame['vars'] = newFrame['vars'];
+    frame = newFrame;
   }
 
-  Script get script => frame['script'];
+  Script get script => frame.location.script;
 
   @override
   void attached() {
@@ -1448,7 +1446,7 @@
       return;
     }
     busy = true;
-    frame['function'].load().then((func) {
+    frame.function.load().then((func) {
         _pinned = !_pinned;
         var frameOuter = $['frameOuter'];
         if (_pinned) {
@@ -1465,7 +1463,7 @@
 
 @CustomTag('debugger-message')
 class DebuggerMessageElement extends ObservatoryElement {
-  @published ServiceMap message;
+  @published ServiceMessage message;
   @observable ServiceObject preview;
 
   // Is this the current message?
@@ -1500,12 +1498,10 @@
 
   DebuggerMessageElement.created() : super.created();
 
-  void updateMessage(ServiceMap newMessage) {
+  void updateMessage(ServiceMessage newMessage) {
     bool messageChanged =
-        (message['messageObjectId'] != newMessage['messageObjectId']);
-    message['index'] = newMessage['index'];
-    message['handlerFunction'] = newMessage['handlerFunction'];
-    message['messageObjectId'] = newMessage['messageObjectId'];
+        (message.messageObjectId != newMessage.messageObjectId);
+    message = newMessage;
     if (messageChanged) {
       // Message object id has changed: clear preview and collapse.
       preview = null;
@@ -1527,7 +1523,7 @@
       return;
     }
     busy = true;
-    var function = message['handlerFunction'];
+    var function = message.handler;
     var loadedFunction;
     if (function == null) {
       // Complete immediately.
@@ -1550,7 +1546,7 @@
   }
 
   Future<ServiceObject> previewMessage(_) {
-    return message.isolate.getObject(message['messageObjectId']).then((result) {
+    return message.isolate.getObject(message.messageObjectId).then((result) {
       preview = result;
       return result;
     });
diff --git a/runtime/observatory/lib/src/elements/debugger.html b/runtime/observatory/lib/src/elements/debugger.html
index e324955..08948cf 100644
--- a/runtime/observatory/lib/src/elements/debugger.html
+++ b/runtime/observatory/lib/src/elements/debugger.html
@@ -241,11 +241,9 @@
       <a on-click="{{ toggleExpand }}">
         <div class="frameSummary">
           <div class="frameSummaryText">
-            <div class="frameId"><b>frame {{ frame['index'] }}</b></div>
-            <function-ref ref="{{ frame['function'] }}"></function-ref>
-            ( <script-ref ref="{{ frame['script'] }}"
-                          pos="{{ frame['tokenPos'] }}">
-            </script-ref> )
+            <div class="frameId"><b>frame {{ frame.index }}</b></div>
+            <function-ref ref="{{ frame.function }}"></function-ref>
+            ( <source-link location="{{ frame.location }}"></source-link> )
           </div>
           <template if="{{ !expanded }}">
             <div class="frameExpander">
@@ -259,18 +257,16 @@
         <div class="frameDetails">
           <div class="flex-row-wrap">
             <div class="flex-item-script">
-              <script-inset height="{{ scriptHeight }}"
-                            script="{{ frame['function'].script }}"
-                            startPos="{{ frame['function'].tokenPos }}"
-                            endPos="{{ frame['function'].endTokenPos }}"
-                            currentPos="{{ frame['tokenPos'] }}"
+              <source-inset height="{{ scriptHeight }}"
+                            location="{{ frame.function.location }}"
+                            currentPos="{{ frame.location.tokenPos }}"
                             inDebuggerContext="{{ true }}"
-                            variables="{{ frame['vars'] }}">
-              </script-inset>
+                            variables="{{ frame.variables }}">
+              </source-inset>
             </div>
             <div class="flex-item-vars">
               <div style="padding:10px;" class="memberList">
-                <template repeat="{{ v in frame['vars'] }}">
+                <template repeat="{{ v in frame.variables }}">
                   <div class="memberItem">
                     <div class="memberName">{{ v['name']}}</div>
                     <div class="memberValue">
@@ -355,11 +351,10 @@
       <a on-click="{{ toggleExpand }}">
         <div class="messageSummary">
           <div class="messageSummaryText">
-            <div class="messageId"><b>message {{ message['index'] }}</b></div>
-            <function-ref ref="{{ message['handlerFunction'] }}"></function-ref>
-            ( <script-ref ref="{{ message['handlerScript'] }}"
-                          pos="{{ message['handlerTokenPos'] }}">
-            </script-ref> )
+            <div class="messageId"><b>message {{ message.index }}</b></div>
+            <function-ref ref="{{ message.handler }}"></function-ref>
+            ( <source-link location="{{ message.location }}">
+            </source-link> )
           </div>
           <template if="{{ !expanded }}">
             <div class="messageExpander">
@@ -373,13 +368,11 @@
         <div class="messageDetails">
           <div class="flex-row-wrap">
             <div class="flex-item-script">
-              <template if="{{ message['handlerFunction'] != null }}">
-              <script-inset height="{{ scriptHeight }}"
-                            script="{{ message['handlerFunction'].script }}"
-                            startPos="{{ message['handlerFunction'].tokenPos }}"
-                            endPos="{{ message['handlerFunction'].endTokenPos }}"
-                            inDebuggerContext="{{ true }}">
-              </script-inset>
+              <template if="{{ message.handler != null }}">
+              <source-inset height="{{ scriptHeight }}"
+                              location="{{ message.handler.location }}"
+                              inDebuggerContext="{{ true }}">
+              </source-inset>
               </template>
             </div>
             <div class="flex-item-vars">
diff --git a/runtime/observatory/lib/src/elements/field_view.html b/runtime/observatory/lib/src/elements/field_view.html
index ecb9b93..3e16d1b 100644
--- a/runtime/observatory/lib/src/elements/field_view.html
+++ b/runtime/observatory/lib/src/elements/field_view.html
@@ -46,7 +46,7 @@
         <div class="memberItem">
           <div class="memberName">script</div>
           <div class="memberValue">
-            <script-ref ref="{{ field.script }}"></script-ref>
+            <source-link location="{{ field.location }}"></source-link>
           </div>
         </div>
         <template if="{{ !field.isStatic }}">
diff --git a/runtime/observatory/lib/src/elements/flag_list.dart b/runtime/observatory/lib/src/elements/flag_list.dart
index b38ad08..f2d1cfc 100644
--- a/runtime/observatory/lib/src/elements/flag_list.dart
+++ b/runtime/observatory/lib/src/elements/flag_list.dart
@@ -13,6 +13,16 @@
 class FlagListElement extends ObservatoryElement {
   @published ServiceMap flagList;
 
+  void flagListChanged(oldValue) {
+    modifiedFlags =
+        flagList['flags'].where((flag) => flag['modified']).toList();
+    unmodifiedFlags =
+        flagList['flags'].where((flag) => !flag['modified']).toList();
+  }
+
+  @observable List<ServiceMap> modifiedFlags = new List<ServiceMap>();
+  @observable List<ServiceMap> unmodifiedFlags = new List<ServiceMap>();
+
   FlagListElement.created() : super.created();
 
   Future refresh() {
diff --git a/runtime/observatory/lib/src/elements/flag_list.html b/runtime/observatory/lib/src/elements/flag_list.html
index 58bd8fe..017e28d 100644
--- a/runtime/observatory/lib/src/elements/flag_list.html
+++ b/runtime/observatory/lib/src/elements/flag_list.html
@@ -13,10 +13,10 @@
     </nav-bar>
 
     <div class="content-centered">
-      <template if="{{ flagList['modifiedFlags'].isNotEmpty }}">
+      <template if="{{ modifiedFlags.isNotEmpty }}">
         <h1>Modified Flags</h1>
         <br>
-        <template repeat="{{ flag in flagList['modifiedFlags'] }}">
+        <template repeat="{{ flag in modifiedFlags }}">
           <flag-item flag="{{ flag }}"></flag-item>
           <br>
         </template>
@@ -25,11 +25,11 @@
 
       <h1>Unmodified Flags</h1>
       <br>
-      <template if="{{ flagList['unmodifiedFlags'].isEmpty }}">
+      <template if="{{ unmodifiedFlags.isEmpty }}">
         <em>None</em>
       </template>
-      <template if="{{ flagList['unmodifiedFlags'].isNotEmpty }}">
-        <template repeat="{{ flag in flagList['unmodifiedFlags'] }}">
+      <template if="{{ unmodifiedFlags.isNotEmpty }}">
+        <template repeat="{{ flag in unmodifiedFlags }}">
           <flag-item flag="{{ flag }}"></flag-item>
           <br>
         </template>
diff --git a/runtime/observatory/lib/src/elements/function_view.html b/runtime/observatory/lib/src/elements/function_view.html
index 47342f4..813fb2a 100644
--- a/runtime/observatory/lib/src/elements/function_view.html
+++ b/runtime/observatory/lib/src/elements/function_view.html
@@ -46,9 +46,7 @@
         <div class="memberItem">
           <div class="memberName">script</div>
           <div class="memberValue">
-            <script-ref ref="{{ function.script }}"
-                        pos="{{ function.tokenPos }}">
-            </script-ref>
+            <source-link location="{{ function.location }}"></source-link>
           </div>
         </div>
 
@@ -98,10 +96,7 @@
 
     <div class="content-centered-big">
       <hr>
-      <script-inset script="{{ function.script }}"
-                    startPos="{{ function.tokenPos }}"
-                    endPos="{{ function.endTokenPos }}">
-      </script-inset>
+      <source-inset location="{{ function.location }}"></source-inset>
     </div>
 
     <view-footer></view-footer>
diff --git a/runtime/observatory/lib/src/elements/instance_ref.html b/runtime/observatory/lib/src/elements/instance_ref.html
index 0a60ee9..b6e86f4 100644
--- a/runtime/observatory/lib/src/elements/instance_ref.html
+++ b/runtime/observatory/lib/src/elements/instance_ref.html
@@ -42,8 +42,7 @@
         </a>
       </template>
 
-      <!-- TODO(rmacnak): Specialized view for maps. -->
-      <template if="{{ ref.isPlainInstance || ref.isMap }}">
+      <template if="{{ ref.isPlainInstance }}">
         <a on-click="{{ goto }}" _href="{{ url }}"><em>{{ ref.clazz.name }}</em></a>
         <curly-block callback="{{ expander() }}">
           <div class="memberList">
@@ -65,11 +64,30 @@
         <a on-click="{{ goto }}" _href="{{ url }}"><em>{{ ref.clazz.name }}</em> ({{ ref.length }})</a>
         <curly-block callback="{{ expander() }}">
           <div class="memberList">
-            <template repeat="{{ element in ref.elements }}">
+            <template repeat="{{ index in ref.elements.asMap().keys }}">
               <div class="memberItem">
-                <div class="memberName">[{{ element['index']}}]</div>
+                <div class="memberName">[{{ index }}]</div>
                 <div class="memberValue">
-                  <any-service-ref ref="{{ element['value'] }}"></any-service-ref>
+                  <any-service-ref ref="{{ ref.elements[index] }}">
+                  </any-service-ref>
+                </div>
+              </div>
+            </template>
+          </div>
+        </curly-block>
+      </template>
+
+      <template if="{{ ref.isMap }}">
+        <a on-click="{{ goto }}" _href="{{ url }}"><em>{{ ref.clazz.name }}</em> ({{ ref.length }})</a>
+        <curly-block callback="{{ expander() }}">
+          <div class="memberList">
+            <template repeat="{{ association in ref.associations }}">
+              <div class="memberItem">
+                <div class="memberName">
+                  [<any-service-ref ref="{{ association['key'] }}"></any-service-ref>]
+                </div>
+                <div class="memberValue">
+                  <any-service-ref ref="{{ association['value'] }}"></any-service-ref>
                 </div>
               </div>
             </template>
diff --git a/runtime/observatory/lib/src/elements/instance_view.html b/runtime/observatory/lib/src/elements/instance_view.html
index 2745e9b..fb39377 100644
--- a/runtime/observatory/lib/src/elements/instance_view.html
+++ b/runtime/observatory/lib/src/elements/instance_view.html
@@ -166,19 +166,39 @@
 
         <template if="{{ instance.elements.isNotEmpty }}">
           elements ({{ instance.elements.length }})
-          <curly-block expand="{{ instance.elements.length <= 8 }}">
+          <curly-block expand="{{ instance.elements.length <= 100 }}">
             <div class="memberList">
-              <template repeat="{{ element in instance.elements }}">
+              <template repeat="{{ index in instance.elements.asMap().keys }}">
                 <div class="memberItem">
-                  <div class="memberName">[{{ element['index']}}]</div>
+                  <div class="memberName">[{{ index }}]</div>
                   <div class="memberValue">
-                    <any-service-ref ref="{{ element['value'] }}"></any-service-ref>
+                    <any-service-ref ref="{{ instance.elements[index] }}">
+                    </any-service-ref>
                   </div>
                 </div>
               </template>
             </div>
           </curly-block><br><br>
         </template>
+
+        <template if="{{ instance.associations.isNotEmpty }}">
+          associations ({{ instance.elements.length }})
+          <curly-block expand="{{ instance.associations.length <= 100 }}">
+            <div class="memberList">
+              <template repeat="{{ association in instance.associations }}">
+                <div class="memberItem">
+                  <div class="memberValue">
+                    [<any-service-ref ref="{{ association['key'] }}"></any-service-ref>]
+                  </div>
+                  <div class="memberValue">
+                    <any-service-ref ref="{{ association['value'] }}"></any-service-ref>
+                  </div>
+                </div>
+              </template>
+            </div>
+          </curly-block><br><br>
+        </template>
+
       </div>
 
     </template>
diff --git a/runtime/observatory/lib/src/elements/isolate_summary.html b/runtime/observatory/lib/src/elements/isolate_summary.html
index 618b42e..2840e2a 100644
--- a/runtime/observatory/lib/src/elements/isolate_summary.html
+++ b/runtime/observatory/lib/src/elements/isolate_summary.html
@@ -83,19 +83,18 @@
           by exception
         </template>
         at
-        <function-ref ref="{{ isolate.topFrame['function'] }}">
+        <function-ref ref="{{ isolate.topFrame.function }}">
         </function-ref>
-        (<script-ref ref="{{ isolate.topFrame['script'] }}"
-                     pos="{{ isolate.topFrame['tokenPos'] }}"></script-ref>)
+        (<source-link location="{{ isolate.topFrame.location }}">
+        </source-link>)
       </template>
     </template>
 
     <template if="{{ isolate.running }}">
       at
-      <function-ref ref="{{ isolate.topFrame['function'] }}">
+      <function-ref ref="{{ isolate.topFrame.function }}">
       </function-ref>
-      (<script-ref ref="{{ isolate.topFrame['script'] }}"
-                   pos="{{ isolate.topFrame['tokenPos'] }}"></script-ref>)
+      (<source-link location="{{ isolate.topFrame.location }}"></source-link>)
     </template>
 
   </template>
diff --git a/runtime/observatory/lib/src/elements/isolate_view.dart b/runtime/observatory/lib/src/elements/isolate_view.dart
index 766f287..fc6116b 100644
--- a/runtime/observatory/lib/src/elements/isolate_view.dart
+++ b/runtime/observatory/lib/src/elements/isolate_view.dart
@@ -103,6 +103,9 @@
     super.attached();
     // Start a timer to update the isolate summary once a second.
     _updateTimer = new Timer(new Duration(seconds: 1), _updateTagProfile);
+    if (isolate.topFrame != null) {
+      isolate.topFrame.function.load();
+    }
   }
 
   @override
@@ -121,8 +124,11 @@
     }
   }
 
-  Future refresh() {
-    return isolate.reload();
+  Future refresh() async {
+    await isolate.reload();
+    if (isolate.topFrame != null) {
+      await isolate.topFrame.function.load();
+    }
   }
 
   Future refreshCoverage() {
diff --git a/runtime/observatory/lib/src/elements/isolate_view.html b/runtime/observatory/lib/src/elements/isolate_view.html
index b9f5e811..014c191 100644
--- a/runtime/observatory/lib/src/elements/isolate_view.html
+++ b/runtime/observatory/lib/src/elements/isolate_view.html
@@ -54,10 +54,10 @@
     <template if="{{ isolate.topFrame != null }}">
       <br>
       <div class="content-centered-big">
-         <script-inset script="{{ isolate.topFrame['script'] }}"
-                       currentPos="{{ isolate.topFrame['tokenPos'] }}"
-                       height="200px">
-         </script-inset>
+        <source-inset location="{{ isolate.topFrame.function.location }}"
+                      currentPos="{{ isolate.topFrame.location.tokenPos }}"
+                      height="200px">
+        </source-inset>
       </div>
     </template>
 
diff --git a/runtime/observatory/lib/src/elements/observatory_element.dart b/runtime/observatory/lib/src/elements/observatory_element.dart
index 8efc7b5..164f079 100644
--- a/runtime/observatory/lib/src/elements/observatory_element.dart
+++ b/runtime/observatory/lib/src/elements/observatory_element.dart
@@ -130,12 +130,6 @@
 
   String formatSize(int bytes) => Utils.formatSize(bytes);
 
-  String fileAndLine(Map frame) {
-    var file = frame['script'].name;
-    var shortFile = file.substring(file.lastIndexOf('/') + 1);
-    return "${shortFile}:${frame['line']}";
-  }
-
   int parseInt(String value) => int.parse(value);
 
   String asStringLiteral(String value, [bool wasTruncated=false]) {
diff --git a/runtime/observatory/lib/src/elements/script_inset.dart b/runtime/observatory/lib/src/elements/script_inset.dart
index d35c86e..3a2cb6c 100644
--- a/runtime/observatory/lib/src/elements/script_inset.dart
+++ b/runtime/observatory/lib/src/elements/script_inset.dart
@@ -162,9 +162,16 @@
 abstract class DeclarationAnnotation extends Annotation {
   DeclarationAnnotation(decl) {
     assert(decl.loaded);
-    var script = decl.script;
-    line = script.tokenToLine(decl.tokenPos);
-    columnStart = script.tokenToCol(decl.tokenPos);
+    SourceLocation location = decl.location;
+    if (location == null) {
+      line = 0;
+      columnStart = 0;
+      columnStop = 0;
+      return;
+    }
+    Script script = location.script;
+    line = script.tokenToLine(location.tokenPos);
+    columnStart = script.tokenToCol(location.tokenPos);
     if ((line == null) || (columnStart == null)) {
       line = 0;
       columnStart = 0;
@@ -309,14 +316,14 @@
 @CustomTag('script-inset')
 class ScriptInsetElement extends ObservatoryElement {
   @published Script script;
+  @published int startPos;
+  @published int endPos;
 
   /// Set the height to make the script inset scroll.  Otherwise it
   /// will show from startPos to endPos.
   @published String height = null;
 
   @published int currentPos;
-  @published int startPos;
-  @published int endPos;
   @published bool inDebuggerContext = false;
   @published ObservableList variables;
 
@@ -491,7 +498,7 @@
 
   void addClassAnnotations() {
     for (var cls in script.library.classes) {
-      if (cls.script == script) {
+      if ((cls.location != null) && (cls.location.script == script)) {
         annotations.add(new ClassDeclarationAnnotation(cls));
       }
     }
@@ -499,13 +506,13 @@
 
   void addFieldAnnotations() {
     for (var field in script.library.variables) {
-      if (field.script == script) {
+      if ((field.location != null) && (field.location.script == script)) {
         annotations.add(new FieldDeclarationAnnotation(field));
       }
     }
     for (var cls in script.library.classes) {
       for (var field in cls.fields) {
-        if (field.script == script) {
+        if ((field.location != null) && (field.location.script == script)) {
           annotations.add(new FieldDeclarationAnnotation(field));
         }
       }
@@ -514,13 +521,13 @@
 
   void addFunctionAnnotations() {
     for (var func in script.library.functions) {
-      if (func.script == script) {
+      if ((func.location != null) && (func.location.script == script)) {
         annotations.add(new FunctionDeclarationAnnotation(func));
       }
     }
     for (var cls in script.library.classes) {
       for (var func in cls.functions) {
-        if (func.script == script) {
+        if ((func.location != null) && (func.location.script == script)) {
           annotations.add(new FunctionDeclarationAnnotation(func));
         }
       }
@@ -540,7 +547,9 @@
       for (var variable in variables) {
         // Find variable usage locations.
         var locations = script.scanForLocalVariableLocations(
-              variable['name'], variable['tokenPos'], variable['endTokenPos']);
+              variable['name'],
+              variable['_tokenPos'],
+              variable['_endTokenPos']);
 
         // Annotate locations.
         for (var location in locations) {
@@ -747,3 +756,15 @@
     _updateTask = new Task(update);
   }
 }
+
+@CustomTag('source-inset')
+class SourceInsetElement extends PolymerElement {
+  SourceInsetElement.created() : super.created();
+
+  @published SourceLocation location;
+  @published String height = null;
+  @published int currentPos;
+  @published bool inDebuggerContext = false;
+  @published ObservableList variables;
+}
+
diff --git a/runtime/observatory/lib/src/elements/script_inset.html b/runtime/observatory/lib/src/elements/script_inset.html
index 7fdbcbf..30b20d8 100644
--- a/runtime/observatory/lib/src/elements/script_inset.html
+++ b/runtime/observatory/lib/src/elements/script_inset.html
@@ -79,4 +79,20 @@
   </template>
 </polymer-element>
 
+
+<polymer-element name="source-inset">
+<template>
+  <template if="{{ location != null }}">
+    <script-inset script="{{ location.script }}"
+                  startPos="{{ location.tokenPos }}"
+                  endPos="{{ location.endTokenPos }}"
+                  height="{{ height }}"
+                  currentPos="{{ currentPos }}"
+                  inDebuggerContext="{{ inDebuggerContext }}"
+                  variables="{{ variables }}">
+    </script-inset>
+  </template>
+</template>
+</polymer-element>
+
 <script type="application/dart" src="script_inset.dart"></script>
diff --git a/runtime/observatory/lib/src/elements/script_ref.dart b/runtime/observatory/lib/src/elements/script_ref.dart
index 1058e32..c11f26d 100644
--- a/runtime/observatory/lib/src/elements/script_ref.dart
+++ b/runtime/observatory/lib/src/elements/script_ref.dart
@@ -63,3 +63,10 @@
 
   ScriptRefElement.created() : super.created();
 }
+
+@CustomTag('source-link')
+class SourceLinkElement extends PolymerElement {
+  SourceLinkElement.created() : super.created();
+
+  @published SourceLocation location;
+}
diff --git a/runtime/observatory/lib/src/elements/script_ref.html b/runtime/observatory/lib/src/elements/script_ref.html
index 79f0449..ccbb177 100644
--- a/runtime/observatory/lib/src/elements/script_ref.html
+++ b/runtime/observatory/lib/src/elements/script_ref.html
@@ -9,4 +9,14 @@
 </template>
 </polymer-element>
 
+<polymer-element name="source-link">
+<template>
+  <template if="{{ location != null }}">
+    <script-ref ref="{{ location.script }}"
+                pos="{{ location.tokenPos }}"></script-ref>
+  </template>
+</template>
+</polymer-element>
+
+
 <script type="application/dart" src="script_ref.dart"></script>
diff --git a/runtime/observatory/lib/src/elements/service_ref.dart b/runtime/observatory/lib/src/elements/service_ref.dart
index ba00201..7c5ff02 100644
--- a/runtime/observatory/lib/src/elements/service_ref.dart
+++ b/runtime/observatory/lib/src/elements/service_ref.dart
@@ -121,7 +121,7 @@
       Logger.root.info('Viewing null object.');
       return;
     }
-    var type = ref.vmType;
+    var type = ref.type;
     var element = _constructElementForRef();
     if (element == null) {
       Logger.root.info('Unable to find a ref element for \'${type}\'');
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index 1e744a3..75c0918 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -20,9 +20,11 @@
   static const kMethodNotFound = -32601;
   static const kInvalidParams  = -32602;
   static const kInternalError  = -32603;
-  static const kFeatureDisabled   = 100;
-  static const kVMMustBePaused    = 101;
-  static const kCannotAddBreakpoint = 102;
+  static const kFeatureDisabled         = 100;
+  static const kVMMustBePaused          = 101;
+  static const kCannotAddBreakpoint     = 102;
+  static const kStreamAlreadySubscribed = 103;
+  static const kStreamNotSubscribed     = 104;
 
   int code;
   Map data;
@@ -175,6 +177,9 @@
       case 'Field':
         obj = new Field._empty(owner);
         break;
+      case 'Frame':
+        obj = new Frame._empty(owner);
+        break;
       case 'Function':
         obj = new ServiceFunction._empty(owner);
         break;
@@ -187,6 +192,12 @@
       case 'Library':
         obj = new Library._empty(owner);
         break;
+      case 'Message':
+        obj = new ServiceMessage._empty(owner);
+        break;
+      case 'SourceLocation':
+        obj = new SourceLocation._empty(owner);
+        break;
       case 'Object':
         switch (vmType) {
           case 'PcDescriptors':
@@ -365,6 +376,32 @@
   ServiceObject getFromMap(ObservableMap map);
 }
 
+/// A [SourceLocation] represents a location or range in the source code.
+class SourceLocation extends ServiceObject {
+  Script script;
+  int tokenPos;
+  int endTokenPos;
+
+  SourceLocation._empty(ServiceObject owner) : super._empty(owner);
+
+  void _update(ObservableMap map, bool mapIsRef) {
+    assert(!mapIsRef);
+    _upgradeCollection(map, owner);
+    script = map['script'];
+    tokenPos = map['tokenPos'];
+    assert(script != null && tokenPos != null);
+    endTokenPos = map['endTokenPos'];
+  }
+
+  String toString() {
+    if (endTokenPos == null) {
+      return '${script.name}:token(${tokenPos})';
+    } else {
+      return '${script.name}:tokens(${tokenPos}-${endTokenPos})';
+    }
+  }
+}
+
 /// State for a VM being inspected.
 abstract class VM extends ServiceObjectOwner {
   @reflectable VM get vm => this;
@@ -525,14 +562,31 @@
     });
   }
 
-  Future<ObservableMap> _fetchDirect() {
-    return invokeRpcNoUpgrade('getVM', {});
+  Future<ObservableMap> _fetchDirect() async {
+    if (!loaded) {
+      // TODO(turnidge): Instead of always listening to all streams,
+      // implement a stream abstraction in the service library so
+      // that we only subscribe to the streams we want.
+      await _streamListen('Isolate');
+      await _streamListen('Debug');
+      await _streamListen('GC');
+      await _streamListen('_Echo');
+      await _streamListen('_Graph');
+    }
+    return await invokeRpcNoUpgrade('getVM', {});
   }
 
   Future<ServiceObject> getFlagList() {
     return invokeRpc('getFlagList', {});
   }
 
+  Future<ServiceObject> _streamListen(String streamId) {
+    Map params = {
+      'streamId': streamId,
+    };
+    return invokeRpc('streamListen', params);
+  }
+
   /// Force the VM to disconnect.
   void disconnect();
   /// Completes when the VM first connects.
@@ -930,7 +984,7 @@
   @observable Library rootLibrary;
   @observable ObservableList<Library> libraries =
       new ObservableList<Library>();
-  @observable ObservableMap topFrame;
+  @observable Frame topFrame;
 
   @observable String name;
   @observable String vmName;
@@ -1157,7 +1211,7 @@
       Breakpoint bpt = await invokeRpc('addBreakpoint', params);
       if (bpt.resolved &&
           script.loaded &&
-          script.tokenToLine(bpt.tokenPos) != line) {
+          script.tokenToLine(bpt.location.tokenPos) != line) {
         // TODO(turnidge): Can this still happen?
         script.getLine(line).possibleBpt = false;
       }
@@ -1425,7 +1479,7 @@
 
   @observable String kind;
   @observable Breakpoint breakpoint;
-  @observable ServiceMap topFrame;
+  @observable Frame topFrame;
   @observable ServiceMap exception;
   @observable ServiceObject inspectee;
   @observable ByteData data;
@@ -1452,9 +1506,15 @@
     if (map['breakpoint'] != null) {
       breakpoint = map['breakpoint'];
     }
-    if (map['topFrame'] != null) {
-      topFrame = map['topFrame'];
+    // TODO(turnidge): Expose the full list of breakpoints.  For now
+    // we just pretend like there is only one active breakpoint.
+    if (map['pauseBreakpoints'] != null) {
+      var pauseBpts = map['pauseBreakpoints'];
+      if (pauseBpts.length > 0) {
+        breakpoint = pauseBpts[0];
+      }
     }
+    topFrame = map['topFrame'];
     if (map['exception'] != null) {
       exception = map['exception'];
     }
@@ -1500,8 +1560,7 @@
   @observable int number;
 
   // Source location information.
-  @observable Script script;
-  @observable int tokenPos;
+  @observable SourceLocation location;
 
   // The breakpoint has been assigned to a final source location.
   @observable bool resolved;
@@ -1511,34 +1570,46 @@
     _upgradeCollection(map, owner);
 
     var newNumber = map['breakpointNumber'];
-    var newScript = map['location']['script'];
-    var newTokenPos = map['location']['tokenPos'];
-
-    // number and script never change.
+    // number never changes.
     assert((number == null) || (number == newNumber));
-    assert((script == null) || (script == newScript));
+    number = newNumber;
 
-    number = map['breakpointNumber'];
-    script = map['location']['script'];
     resolved = map['resolved'];
-    bool tokenPosChanged = tokenPos != newTokenPos;
 
-    if (script.loaded &&
-        (tokenPos != null) &&
+    var oldLocation = location;
+    var newLocation = map['location'];
+    var oldScript;
+    var newScript;
+    var oldTokenPos;
+    var newTokenPos;
+    if (oldLocation != null) {
+      oldScript = location.script;
+      oldTokenPos = location.tokenPos;
+    }
+    if (newLocation != null) {
+      newScript = newLocation.script;
+      newTokenPos = newLocation.tokenPos;
+    }
+    // script never changes
+    assert((oldScript == null) || (oldScript == newScript));
+    bool tokenPosChanged = oldTokenPos != newTokenPos;
+    if (newScript.loaded &&
+        (newTokenPos != null) &&
         tokenPosChanged) {
       // The breakpoint has moved.  Remove it and add it later.
-      script._removeBreakpoint(this);
+      if (oldScript != null) {
+        oldScript._removeBreakpoint(this);
+      }
     }
-
-    tokenPos = newTokenPos;
-    if (script.loaded && tokenPosChanged) {
-      script._addBreakpoint(this);
+    location = newLocation;
+    if (newScript.loaded && tokenPosChanged) {
+      newScript._addBreakpoint(this);
     }
   }
 
   void remove() {
     // Remove any references to this breakpoint.  It has been removed.
-    script._removeBreakpoint(this);
+    location.script._removeBreakpoint(this);
     if ((isolate.pauseEvent != null) &&
         (isolate.pauseEvent.breakpoint != null) &&
         (isolate.pauseEvent.breakpoint.id == id)) {
@@ -1548,7 +1619,7 @@
 
   String toString() {
     if (number != null) {
-      return 'Breakpoint ${number} at ${script.name}(token:${tokenPos})';
+      return 'Breakpoint ${number} at ${location})';
     } else {
       return 'Uninitialized breakpoint';
     }
@@ -1664,7 +1735,6 @@
 
 class Class extends ServiceObject with Coverage {
   @observable Library library;
-  @observable Script script;
 
   @observable bool isAbstract;
   @observable bool isConst;
@@ -1672,8 +1742,7 @@
   @observable bool isPatch;
   @observable bool isImplemented;
 
-  @observable int tokenPos;
-  @observable int endTokenPos;
+  @observable SourceLocation location;
 
   @observable ServiceMap error;
   @observable int vmCid;
@@ -1720,17 +1789,13 @@
       library = null;
     }
 
-    script = map['script'];
-
+    location = map['location'];
     isAbstract = map['abstract'];
     isConst = map['const'];
     isFinalized = map['_finalized'];
     isPatch = map['_patch'];
     isImplemented = map['_implemented'];
 
-    tokenPos = map['tokenPos'];
-    endTokenPos = map['endTokenPos'];
-
     subclasses.clear();
     subclasses.addAll(map['subclasses']);
     subclasses.sort(ServiceObject.LexicalSortName);
@@ -1789,12 +1854,13 @@
   @observable ServiceFunction function;  // If a closure.
   @observable Context context;  // If a closure.
   @observable String name;  // If a Type.
-  @observable int length; // If a List.
+  @observable int length; // If a List or Map.
 
   @observable var typeClass;
   @observable var fields;
   @observable var nativeFields;
-  @observable var elements;
+  @observable var elements;  // If a List.
+  @observable var associations;  // If a Map.
   @observable var referent;  // If a MirrorReference.
   @observable Instance key;  // If a WeakProperty.
   @observable Instance value;  // If a WeakProperty.
@@ -1842,6 +1908,7 @@
     nativeFields = map['_nativeFields'];
     fields = map['fields'];
     elements = map['elements'];
+    associations = map['associations'];
     typeClass = map['typeClass'];
     referent = map['mirrorReferent'];
     key = map['propertyKey'];
@@ -1961,9 +2028,7 @@
   @observable Library library;
   @observable bool isStatic;
   @observable bool isConst;
-  @observable Script script;
-  @observable int tokenPos;
-  @observable int endTokenPos;
+  @observable SourceLocation location;
   @observable Code code;
   @observable Code unoptimizedCode;
   @observable bool isOptimizable;
@@ -2012,9 +2077,7 @@
     _loaded = true;
     isStatic = map['static'];
     isConst = map['const'];
-    script = map['script'];
-    tokenPos = map['tokenPos'];
-    endTokenPos = map['endTokenPos'];
+    location = map['location'];
     code = map['code'];
     isOptimizable = map['_optimizable'];
     isInlinable = map['_inlinable'];
@@ -2040,8 +2103,7 @@
   @observable bool guardNullable;
   @observable String guardClass;
   @observable String guardLength;
-  @observable Script script;
-  @observable int tokenPos;
+  @observable SourceLocation location;
 
   Field._empty(ServiceObjectOwner owner) : super._empty(owner);
 
@@ -2073,9 +2135,7 @@
     guardNullable = map['_guardNullable'];
     guardClass = map['_guardClass'];
     guardLength = map['_guardLength'];
-    script = map['script'];
-    tokenPos = map['tokenPos'];
-
+    location = map['location'];
     _loaded = true;
   }
 
@@ -2162,6 +2222,7 @@
 
 class CallSite {
   final String name;
+  // TODO(turnidge): Use SourceLocation here instead.
   final Script script;
   final int tokenPos;
   final List<CallSiteEntry> entries;
@@ -2350,7 +2411,7 @@
       lines.add(new ScriptLine(this, i + lineOffset + 1, sourceLines[i]));
     }
     for (var bpt in isolate.breakpoints.values) {
-      if (bpt.script == this) {
+      if (bpt.location.script == this) {
         _addBreakpoint(bpt);
       }
     }
@@ -2368,12 +2429,12 @@
   }
 
   void _addBreakpoint(Breakpoint bpt) {
-    var line = tokenToLine(bpt.tokenPos);
+    var line = tokenToLine(bpt.location.tokenPos);
     getLine(line).addBreakpoint(bpt);
   }
 
   void _removeBreakpoint(Breakpoint bpt) {
-    var line = tokenToLine(bpt.tokenPos);
+    var line = tokenToLine(bpt.location.tokenPos);
     if (line != null) {
       getLine(line).removeBreakpoint(bpt);
     }
@@ -2758,10 +2819,10 @@
     if (function == null) {
       return;
     }
-    if (function.script == null) {
+    if (function.location.script == null) {
       // Attempt to load the function.
       function.load().then((func) {
-        var script = function.script;
+        var script = function.location.script;
         if (script == null) {
           // Function doesn't have an associated script.
           return;
@@ -2772,7 +2833,7 @@
       return;
     }
     // Load the script and then update descriptors.
-    function.script.load().then(_updateDescriptors);
+    function.location.script.load().then(_updateDescriptors);
   }
 
   /// Reload [this]. Returns a future which completes to [this] or an
@@ -3122,6 +3183,50 @@
   }
 }
 
+class Frame extends ServiceObject {
+  @observable int index;
+  @observable ServiceFunction function;
+  @observable SourceLocation location;
+  @observable Code code;
+  @observable List<ServiceMap> variables = new ObservableList<ServiceMap>();
+
+  Frame._empty(ServiceObject owner) : super._empty(owner);
+
+  void _update(ObservableMap map, bool mapIsRef) {
+    assert(!mapIsRef);
+    _loaded = true;
+    _upgradeCollection(map, owner);
+    this.index = map['index'];
+    this.function = map['function'];
+    this.location = map['location'];
+    this.code = map['code'];
+    this.variables = map['vars'];
+  }
+}
+
+
+class ServiceMessage extends ServiceObject {
+  @observable int index;
+  @observable String messageObjectId;
+  @observable int size;
+  @observable ServiceFunction handler;
+  @observable SourceLocation location;
+
+  ServiceMessage._empty(ServiceObject owner) : super._empty(owner);
+
+  void _update(ObservableMap map, bool mapIsRef) {
+    assert(!mapIsRef);
+    _loaded = true;
+    _upgradeCollection(map, owner);
+    this.messageObjectId = map['messageObjectId'];
+    this.index = map['index'];
+    this.size = map['size'];
+    this.handler = map['handler'];
+    this.location = map['location'];
+  }
+}
+
+
 // Returns true if [map] is a service map. i.e. it has the following keys:
 // 'id' and a 'type'.
 bool _isServiceMap(ObservableMap m) {
diff --git a/runtime/observatory/observatory_sources.gypi b/runtime/observatory/observatory_sources.gypi
index 98cbca2..ea6c1e2 100644
--- a/runtime/observatory/observatory_sources.gypi
+++ b/runtime/observatory/observatory_sources.gypi
@@ -27,7 +27,7 @@
     'lib/src/cli/command.dart',
     'lib/src/cpu_profile/cpu_profile.dart',
     'lib/src/debugger/debugger.dart',
-    'lib/src/debugger/source_location.dart',
+    'lib/src/debugger/debugger_location.dart',
     'lib/src/elements/action_link.dart',
     'lib/src/elements/action_link.html',
     'lib/src/elements/class_ref.dart',
diff --git a/runtime/observatory/tests/service/code_test.dart b/runtime/observatory/tests/service/code_test.dart
index 6b74b39..28e2f86 100644
--- a/runtime/observatory/tests/service/code_test.dart
+++ b/runtime/observatory/tests/service/code_test.dart
@@ -59,10 +59,10 @@
       var frame0 = stack['frames'][0];
       var frame1 = stack['frames'][1];
       print(frame0);
-      expect(frame0['function'].name, equals('funcB'));
-      expect(frame1['function'].name, equals('funcA'));
-      var codeId0 = frame0['code'].id;
-      var codeId1 = frame1['code'].id;
+      expect(frame0.function.name, equals('funcB'));
+      expect(frame1.function.name, equals('funcA'));
+      var codeId0 = frame0.code.id;
+      var codeId1 = frame1.code.id;
 
       List tests = [];
       // Load code from frame 0.
diff --git a/runtime/observatory/tests/service/contexts_test.dart b/runtime/observatory/tests/service/contexts_test.dart
index 6b3e8c9..bf593f4 100644
--- a/runtime/observatory/tests/service/contexts_test.dart
+++ b/runtime/observatory/tests/service/contexts_test.dart
@@ -59,7 +59,7 @@
         expect(block.context.isContext, isTrue);
         expect(block.context.length, equals(0));
         return block.context.load().then((Context ctxt) {
-          expect(ctxt.parentContext.isNull, isTrue);
+          expect(ctxt.parentContext, isNull);
         });
       });
     });
@@ -79,7 +79,7 @@
           expect(ctxt.parentContext.isContext, isTrue);
           expect(ctxt.parentContext.length, equals(0));
           return ctxt.parentContext.load().then((Context outerCtxt) {
-            expect(outerCtxt.parentContext.isNull, isTrue);
+            expect(outerCtxt.parentContext, isNull);
           });
         });
       });
@@ -100,7 +100,7 @@
           expect(ctxt.parentContext.isContext, isTrue);
           expect(ctxt.parentContext.length, equals(0));
           return ctxt.parentContext.load().then((Context outerCtxt) {
-            expect(outerCtxt.parentContext.isNull, isTrue);
+            expect(outerCtxt.parentContext, isNull);
           });
         });
       });
@@ -126,7 +126,7 @@
             expect(outerCtxt.parentContext.isContext, isTrue);
             expect(outerCtxt.parentContext.length, equals(0));
             return outerCtxt.parentContext.load().then((Context outerCtxt2) {
-              expect(outerCtxt2.parentContext.isNull, isTrue);
+                expect(outerCtxt2.parentContext, isNull);
             });
           });
         });
diff --git a/runtime/observatory/tests/service/coverage_test.dart b/runtime/observatory/tests/service/coverage_test.dart
index 1f75644..45a60a8 100644
--- a/runtime/observatory/tests/service/coverage_test.dart
+++ b/runtime/observatory/tests/service/coverage_test.dart
@@ -83,13 +83,13 @@
       // Make sure we are in the right place.
       expect(stack.type, equals('Stack'));
       expect(stack['frames'].length, greaterThanOrEqualTo(2));
-      expect(stack['frames'][0]['function'].name, equals('myFunction'));
-      expect(stack['frames'][0]['function'].dartOwner.name, equals('MyClass'));
+      expect(stack['frames'][0].function.name, equals('myFunction'));
+      expect(stack['frames'][0].function.dartOwner.name, equals('MyClass'));
 
       var lib = isolate.rootLibrary;
-      var func = stack['frames'][0]['function'];
+      var func = stack['frames'][0].function;
       expect(func.name, equals('myFunction'));
-      var cls = stack['frames'][0]['function'].dartOwner;
+      var cls = func.dartOwner;
       expect(cls.name, equals('MyClass'));
 
       List tests = [];
@@ -126,8 +126,9 @@
                 }));
       // Script
       tests.add(cls.load().then((_) {
-            return isolate.invokeRpcNoUpgrade('_getCoverage',
-                                              { 'targetId': cls.script.id })
+            return isolate.invokeRpcNoUpgrade(
+                '_getCoverage',
+                { 'targetId': cls.location.script.id })
                 .then((Map coverage) {
                     expect(coverage['type'], equals('CodeCoverage'));
                     expect(coverage['coverage'].length, equals(3));
diff --git a/runtime/observatory/tests/service/source_location_test.dart b/runtime/observatory/tests/service/debugger_location_test.dart
similarity index 67%
rename from runtime/observatory/tests/service/source_location_test.dart
rename to runtime/observatory/tests/service/debugger_location_test.dart
index 128452c..7c4de5b 100644
--- a/runtime/observatory/tests/service/source_location_test.dart
+++ b/runtime/observatory/tests/service/debugger_location_test.dart
@@ -27,12 +27,12 @@
   int currentFrame = 0;
 }
 
-void source_location_dummy_function() {
+void debugger_location_dummy_function() {
 }
 
-class SourceLocationTestFoo {
-  SourceLocationTestFoo(this.field);
-  SourceLocationTestFoo.named();
+class DebuggerLocationTestFoo {
+  DebuggerLocationTestFoo(this.field);
+  DebuggerLocationTestFoo.named();
 
   void method() {}
   void madness() {}
@@ -40,7 +40,7 @@
   int field;
 }
 
-class SourceLocationTestBar {
+class DebuggerLocationTestBar {
 }
 
 Future<Debugger> initDebugger(Isolate isolate) {
@@ -73,9 +73,9 @@
 // Parse '' => current position
 (Isolate isolate) {
   return initDebugger(isolate).then((debugger) {
-    return SourceLocation.parse(debugger, '').then((SourceLocation loc) {
+    return DebuggerLocation.parse(debugger, '').then((DebuggerLocation loc) {
       expect(loc.valid, isTrue);
-      expect(loc.toString(), equals('source_location_test.dart:15'));
+      expect(loc.toString(), equals('debugger_location_test.dart:15'));
     });
   });
 },
@@ -83,9 +83,9 @@
 // Parse line
 (Isolate isolate) {
   return initDebugger(isolate).then((debugger) {
-    return SourceLocation.parse(debugger, '16').then((SourceLocation loc) {
+    return DebuggerLocation.parse(debugger, '16').then((DebuggerLocation loc) {
       expect(loc.valid, isTrue);
-      expect(loc.toString(), equals('source_location_test.dart:16'));
+      expect(loc.toString(), equals('debugger_location_test.dart:16'));
     });
   });
 },
@@ -93,9 +93,9 @@
 // Parse line + col
 (Isolate isolate) {
   return initDebugger(isolate).then((debugger) {
-    return SourceLocation.parse(debugger, '16:11').then((SourceLocation loc) {
+    return DebuggerLocation.parse(debugger, '16:11').then((DebuggerLocation loc) {
       expect(loc.valid, isTrue);
-      expect(loc.toString(), equals('source_location_test.dart:16:11'));
+      expect(loc.toString(), equals('debugger_location_test.dart:16:11'));
     });
   });
 },
@@ -103,8 +103,8 @@
 // Parse script + line
 (Isolate isolate) {
   return initDebugger(isolate).then((debugger) {
-    return SourceLocation.parse(debugger, 'unittest.dart:15')
-      .then((SourceLocation loc) {
+    return DebuggerLocation.parse(debugger, 'unittest.dart:15')
+      .then((DebuggerLocation loc) {
         expect(loc.valid, isTrue);
         expect(loc.toString(), equals('unittest.dart:15'));
       });
@@ -114,8 +114,8 @@
 // Parse script + line + col
 (Isolate isolate) {
   return initDebugger(isolate).then((debugger) {
-    return SourceLocation.parse(debugger, 'unittest.dart:15:10')
-      .then((SourceLocation loc) {
+    return DebuggerLocation.parse(debugger, 'unittest.dart:15:10')
+      .then((DebuggerLocation loc) {
         expect(loc.valid, isTrue);
         expect(loc.toString(), equals('unittest.dart:15:10'));
       });
@@ -125,8 +125,8 @@
 // Parse bad script
 (Isolate isolate) {
   return initDebugger(isolate).then((debugger) {
-    return SourceLocation.parse(debugger, 'bad.dart:15')
-      .then((SourceLocation loc) {
+    return DebuggerLocation.parse(debugger, 'bad.dart:15')
+      .then((DebuggerLocation loc) {
         expect(loc.valid, isFalse);
         expect(loc.toString(), equals(
             'invalid source location (Script \'bad.dart\' not found)'));
@@ -137,8 +137,8 @@
 // Parse function
 (Isolate isolate) {
   return initDebugger(isolate).then((debugger) {
-    return SourceLocation.parse(debugger, 'testFunction')
-      .then((SourceLocation loc) {
+    return DebuggerLocation.parse(debugger, 'testFunction')
+      .then((DebuggerLocation loc) {
         expect(loc.valid, isTrue);
         expect(loc.toString(), equals('testFunction'));
       });
@@ -148,8 +148,8 @@
 // Parse bad function
 (Isolate isolate) {
   return initDebugger(isolate).then((debugger) {
-    return SourceLocation.parse(debugger, 'doesNotReallyExit')
-      .then((SourceLocation loc) {
+    return DebuggerLocation.parse(debugger, 'doesNotReallyExit')
+      .then((DebuggerLocation loc) {
         expect(loc.valid, isFalse);
         expect(loc.toString(), equals(
             'invalid source location (Function \'doesNotReallyExit\' not found)'));
@@ -160,14 +160,14 @@
 // Parse constructor
 (Isolate isolate) {
   return initDebugger(isolate).then((debugger) {
-    return SourceLocation.parse(debugger, 'SourceLocationTestFoo')
-      .then((SourceLocation loc) {
+    return DebuggerLocation.parse(debugger, 'DebuggerLocationTestFoo')
+      .then((DebuggerLocation loc) {
         expect(loc.valid, isTrue);
         // TODO(turnidge): Printing a constructor currently adds
         // another class qualifier at the front.  Do we want to change
         // this to be more consistent?
         expect(loc.toString(), equals(
-            'SourceLocationTestFoo.SourceLocationTestFoo'));
+            'DebuggerLocationTestFoo.DebuggerLocationTestFoo'));
       });
   });
 },
@@ -175,14 +175,14 @@
 // Parse named constructor
 (Isolate isolate) {
   return initDebugger(isolate).then((debugger) {
-    return SourceLocation.parse(debugger, 'SourceLocationTestFoo.named')
-      .then((SourceLocation loc) {
+    return DebuggerLocation.parse(debugger, 'DebuggerLocationTestFoo.named')
+      .then((DebuggerLocation loc) {
         expect(loc.valid, isTrue);
         // TODO(turnidge): Printing a constructor currently adds
         // another class qualifier at the front.  Do we want to change
         // this to be more consistent?
         expect(loc.toString(), equals(
-            'SourceLocationTestFoo.SourceLocationTestFoo.named'));
+            'DebuggerLocationTestFoo.DebuggerLocationTestFoo.named'));
       });
   });
 },
@@ -190,10 +190,10 @@
 // Parse method
 (Isolate isolate) {
   return initDebugger(isolate).then((debugger) {
-    return SourceLocation.parse(debugger, 'SourceLocationTestFoo.method')
-      .then((SourceLocation loc) {
+    return DebuggerLocation.parse(debugger, 'DebuggerLocationTestFoo.method')
+      .then((DebuggerLocation loc) {
         expect(loc.valid, isTrue);
-        expect(loc.toString(), equals('SourceLocationTestFoo.method'));
+        expect(loc.toString(), equals('DebuggerLocationTestFoo.method'));
       });
   });
 },
@@ -201,10 +201,10 @@
 // Parse method
 (Isolate isolate) {
   return initDebugger(isolate).then((debugger) {
-    return SourceLocation.parse(debugger, 'SourceLocationTestFoo.field=')
-      .then((SourceLocation loc) {
+    return DebuggerLocation.parse(debugger, 'DebuggerLocationTestFoo.field=')
+      .then((DebuggerLocation loc) {
         expect(loc.valid, isTrue);
-        expect(loc.toString(), equals('SourceLocationTestFoo.field='));
+        expect(loc.toString(), equals('DebuggerLocationTestFoo.field='));
       });
   });
 },
@@ -212,12 +212,12 @@
 // Parse bad method
 (Isolate isolate) {
   return initDebugger(isolate).then((debugger) {
-    return SourceLocation.parse(debugger, 'SourceLocationTestFoo.missing')
-      .then((SourceLocation loc) {
+    return DebuggerLocation.parse(debugger, 'DebuggerLocationTestFoo.missing')
+      .then((DebuggerLocation loc) {
         expect(loc.valid, isFalse);
         expect(loc.toString(), equals(
             'invalid source location '
-            '(Function \'SourceLocationTestFoo.missing\' not found)'));
+            '(Function \'DebuggerLocationTestFoo.missing\' not found)'));
       });
   });
 },
@@ -225,11 +225,11 @@
 // Complete function + script
 (Isolate isolate) {
   return initDebugger(isolate).then((debugger) {
-    return SourceLocation.complete(debugger, 'source_loc')
+    return DebuggerLocation.complete(debugger, 'debugger_loc')
       .then((List<String> completions) {
         expect(completions.toString(), equals(
-            '[source_location_dummy_function, '
-             'source_location.dart:, source_location_test.dart:]'));
+            '[debugger_location_dummy_function, '
+             'debugger_location.dart:, debugger_location_test.dart:]'));
       });
   });
 },
@@ -237,10 +237,10 @@
 // Complete class
 (Isolate isolate) {
   return initDebugger(isolate).then((debugger) {
-    return SourceLocation.complete(debugger, 'SourceLocationTe')
+    return DebuggerLocation.complete(debugger, 'DebuggerLocationTe')
       .then((List<String> completions) {
         expect(completions.toString(), equals(
-            '[SourceLocationTestBar, SourceLocationTestFoo]'));
+            '[DebuggerLocationTestBar, DebuggerLocationTestFoo]'));
       });
   });
 },
@@ -248,7 +248,7 @@
 // No completions: unqualified name
 (Isolate isolate) {
   return initDebugger(isolate).then((debugger) {
-    return SourceLocation.complete(debugger, 'source_locXYZZY')
+    return DebuggerLocation.complete(debugger, 'debugger_locXYZZY')
       .then((List<String> completions) {
         expect(completions.toString(), equals('[]'));
       });
@@ -258,10 +258,10 @@
 // Complete method
 (Isolate isolate) {
   return initDebugger(isolate).then((debugger) {
-    return SourceLocation.complete(debugger, 'SourceLocationTestFoo.m')
+    return DebuggerLocation.complete(debugger, 'DebuggerLocationTestFoo.m')
       .then((List<String> completions) {
         expect(completions.toString(), equals(
-            '[SourceLocationTestFoo.madness, SourceLocationTestFoo.method]'));
+          '[DebuggerLocationTestFoo.madness, DebuggerLocationTestFoo.method]'));
       });
   });
 },
@@ -269,7 +269,7 @@
 // No completions: qualified name
 (Isolate isolate) {
   return initDebugger(isolate).then((debugger) {
-    return SourceLocation.complete(debugger, 'SourceLocationTestFoo.q')
+    return DebuggerLocation.complete(debugger, 'DebuggerLocationTestFoo.q')
       .then((List<String> completions) {
         expect(completions.toString(), equals('[]'));
       });
diff --git a/runtime/observatory/tests/service/debugging_inlined_finally_test.dart b/runtime/observatory/tests/service/debugging_inlined_finally_test.dart
new file mode 100644
index 0000000..85d910b
--- /dev/null
+++ b/runtime/observatory/tests/service/debugging_inlined_finally_test.dart
@@ -0,0 +1,126 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+import 'dart:async';
+import 'dart:developer';
+
+testFunction() {
+  debugger();
+  var a;
+  try {
+    var b;
+    try {
+      for (int i = 0; i < 10; i++) {
+        var x = () => i + a + b;
+        return x;  // line 20
+      }
+    } finally {
+      b = 10;  // line 23
+    }
+  } finally {
+    a = 1;  // line 26
+  }
+}
+
+testMain() {
+  var f = testFunction();
+  expect(f(), equals(11));
+}
+
+var tests = [
+
+hasStoppedAtBreakpoint,
+
+// Add breakpoint
+(Isolate isolate) async {
+  await isolate.rootLibrary.load();
+
+  var script = isolate.rootLibrary.scripts[0];
+  await script.load();
+
+  // Add 3 breakpoints.
+  {
+    var result = await isolate.addBreakpoint(script, 20);
+    expect(result is Breakpoint, isTrue);
+    Breakpoint bpt = result;
+    expect(bpt.type, equals('Breakpoint'));
+    expect(bpt.location.script.id, equals(script.id));
+    expect(bpt.location.script.tokenToLine(bpt.location.tokenPos), equals(20));
+    expect(isolate.breakpoints.length, equals(1));
+  }
+
+  {
+    var result = await isolate.addBreakpoint(script, 23);
+    expect(result is Breakpoint, isTrue);
+    Breakpoint bpt = result;
+    expect(bpt.type, equals('Breakpoint'));
+    expect(bpt.location.script.id, equals(script.id));
+    expect(bpt.location.script.tokenToLine(bpt.location.tokenPos), equals(23));
+    expect(isolate.breakpoints.length, equals(2));
+  }
+
+  {
+    var result = await isolate.addBreakpoint(script, 26);
+    expect(result is Breakpoint, isTrue);
+    Breakpoint bpt = result;
+    expect(bpt.type, equals('Breakpoint'));
+    expect(bpt.location.script.id, equals(script.id));
+    expect(bpt.location.script.tokenToLine(bpt.location.tokenPos), equals(26));
+    expect(isolate.breakpoints.length, equals(3));
+  }
+
+  // Wait for breakpoint events.
+},
+
+resumeIsolate,
+
+hasStoppedAtBreakpoint,
+
+// We are at the breakpoint on line 20.
+(Isolate isolate) async {
+  ServiceMap stack = await isolate.getStack();
+  expect(stack.type, equals('Stack'));
+  expect(stack['frames'].length, greaterThanOrEqualTo(1));
+
+  Script script = stack['frames'][0].location.script;
+  expect(script.tokenToLine(stack['frames'][0].location.tokenPos), equals(20));
+},
+
+resumeIsolate,
+
+hasStoppedAtBreakpoint,
+
+// We are at the breakpoint on line 23.
+(Isolate isolate) async {
+  ServiceMap stack = await isolate.getStack();
+  expect(stack.type, equals('Stack'));
+  expect(stack['frames'].length, greaterThanOrEqualTo(1));
+
+  Script script = stack['frames'][0].location.script;
+  expect(script.tokenToLine(stack['frames'][0].location.tokenPos), equals(23));
+},
+
+resumeIsolate,
+
+hasStoppedAtBreakpoint,
+
+// We are at the breakpoint on line 26.
+(Isolate isolate) async {
+  ServiceMap stack = await isolate.getStack();
+  expect(stack.type, equals('Stack'));
+  expect(stack['frames'].length, greaterThanOrEqualTo(1));
+
+  Script script = stack['frames'][0].location.script;
+  expect(script.tokenToLine(stack['frames'][0].location.tokenPos), equals(26));
+},
+
+resumeIsolate,
+
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory/tests/service/debugging_test.dart b/runtime/observatory/tests/service/debugging_test.dart
index 9685707..e9e2c11 100644
--- a/runtime/observatory/tests/service/debugging_test.dart
+++ b/runtime/observatory/tests/service/debugging_test.dart
@@ -76,8 +76,8 @@
   expect(result is Breakpoint, isTrue);
   Breakpoint bpt = result;
   expect(bpt.type, equals('Breakpoint'));
-  expect(bpt.script.id, equals(script.id));
-  expect(bpt.script.tokenToLine(bpt.tokenPos), equals(15));
+  expect(bpt.location.script.id, equals(script.id));
+  expect(bpt.location.script.tokenToLine(bpt.location.tokenPos), equals(15));
   expect(isolate.breakpoints.length, equals(1));
 
   await completer.future;  // Wait for breakpoint events.
@@ -89,9 +89,9 @@
   expect(stack.type, equals('Stack'));
   expect(stack['frames'].length, greaterThanOrEqualTo(1));
 
-  Script script = stack['frames'][0]['script'];
+  Script script = stack['frames'][0].location.script;
   expect(script.name,endsWith('debugging_test.dart'));
-  expect(script.tokenToLine(stack['frames'][0]['tokenPos']), equals(15));
+  expect(script.tokenToLine(stack['frames'][0].location.tokenPos), equals(15));
 },
 
 // Stepping
@@ -117,9 +117,9 @@
   expect(stack.type, equals('Stack'));
   expect(stack['frames'].length, greaterThanOrEqualTo(1));
 
-  Script script = stack['frames'][0]['script'];
+  Script script = stack['frames'][0].location.script;
   expect(script.name,endsWith('debugging_test.dart'));
-  expect(script.tokenToLine(stack['frames'][0]['tokenPos']), equals(16));
+  expect(script.tokenToLine(stack['frames'][0].location.tokenPos), equals(16));
 },
 
 // Remove breakpoint
@@ -179,8 +179,8 @@
   expect(result is Breakpoint, isTrue);
   Breakpoint bpt = result;
   expect(bpt.type, equals('Breakpoint'));
-  expect(bpt.script.name, equals('debugging_test.dart'));
-  expect(bpt.script.tokenToLine(bpt.tokenPos), equals(14));
+  expect(bpt.location.script.name, equals('debugging_test.dart'));
+  expect(bpt.location.script.tokenToLine(bpt.location.tokenPos), equals(14));
   expect(isolate.breakpoints.length, equals(1));
 
   await completer.future;  // Wait for breakpoint events.
@@ -192,9 +192,9 @@
   expect(stack.type, equals('Stack'));
   expect(stack['frames'].length, greaterThanOrEqualTo(1));
 
-  Script script = stack['frames'][0]['script'];
+  Script script = stack['frames'][0].location.script;
   expect(script.name,endsWith('debugging_test.dart'));
-  expect(script.tokenToLine(stack['frames'][0]['tokenPos']), equals(14));
+  expect(script.tokenToLine(stack['frames'][0].location.tokenPos), equals(14));
 },
 
 ];
diff --git a/runtime/observatory/tests/service/eval_test.dart b/runtime/observatory/tests/service/eval_test.dart
index 1893b00..aac5d3f 100644
--- a/runtime/observatory/tests/service/eval_test.dart
+++ b/runtime/observatory/tests/service/eval_test.dart
@@ -56,12 +56,12 @@
       // Make sure we are in the right place.
       expect(stack.type, equals('Stack'));
       expect(stack['frames'].length, greaterThanOrEqualTo(2));
-      expect(stack['frames'][0]['function'].name, equals('printValue'));
-      expect(stack['frames'][0]['function'].dartOwner.name, equals('MyClass'));
+      expect(stack['frames'][0].function.name, equals('printValue'));
+      expect(stack['frames'][0].function.dartOwner.name, equals('MyClass'));
 
       var lib = isolate.rootLibrary;
-      var cls = stack['frames'][0]['function'].dartOwner;
-      var instance = stack['frames'][0]['vars'][0]['value'];
+      var cls = stack['frames'][0].function.dartOwner;
+      var instance = stack['frames'][0].variables[0]['value'];
 
       List evals = [];
       evals.add(lib.evaluate('globalVar + 5').then((result) {
diff --git a/runtime/observatory/tests/service/get_object_rpc_test.dart b/runtime/observatory/tests/service/get_object_rpc_test.dart
index d95346e..b1df709 100644
--- a/runtime/observatory/tests/service/get_object_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_object_rpc_test.dart
@@ -100,10 +100,41 @@
     expect(result['size'], isPositive);
     expect(result['fields'], isEmpty);
     expect(result['elements'].length, equals(3));
-    expect(result['elements'][0]['index'], equals(0));
-    expect(result['elements'][0]['value']['type'], equals('@Instance'));
-    expect(result['elements'][0]['value']['kind'], equals('Int'));
-    expect(result['elements'][0]['value']['valueAsString'], equals('3'));
+    expect(result['elements'][0]['type'], equals('@Instance'));
+    expect(result['elements'][0]['kind'], equals('Int'));
+    expect(result['elements'][0]['valueAsString'], equals('3'));
+  },
+
+  // A built-in Map.
+  (Isolate isolate) async {
+    // Call eval to get a Dart map.
+    var evalResult = await eval(isolate, '{"x": 3, "y": 4}');
+    var params = {
+      'objectId': evalResult['id'],
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Instance'));
+    expect(result['kind'], equals('Map'));
+    expect(result['_vmType'], equals('LinkedHashMap'));
+    expect(result['id'], startsWith('objects/'));
+    expect(result['valueAsString'], isNull);
+    expect(result['class']['type'], equals('@Class'));
+    expect(result['class']['name'], equals('_InternalLinkedHashMap'));
+    expect(result['size'], isPositive);
+    expect(result['fields'], isEmpty);
+    expect(result['associations'].length, equals(2));
+    expect(result['associations'][0]['key']['type'], equals('@Instance'));
+    expect(result['associations'][0]['key']['kind'], equals('String'));
+    expect(result['associations'][0]['key']['valueAsString'], equals('x'));
+    expect(result['associations'][0]['value']['type'], equals('@Instance'));
+    expect(result['associations'][0]['value']['kind'], equals('Int'));
+    expect(result['associations'][0]['value']['valueAsString'], equals('3'));
+    expect(result['associations'][1]['key']['type'], equals('@Instance'));
+    expect(result['associations'][1]['key']['kind'], equals('String'));
+    expect(result['associations'][1]['key']['valueAsString'], equals('y'));
+    expect(result['associations'][1]['value']['type'], equals('@Instance'));
+    expect(result['associations'][1]['value']['kind'], equals('Int'));
+    expect(result['associations'][1]['value']['valueAsString'], equals('4'));
   },
 
   // An expired object.
@@ -222,7 +253,7 @@
     expect(result['_implemented'], equals(false));
     expect(result['_patch'], equals(false));
     expect(result['library']['type'], equals('@Library'));
-    expect(result['script']['type'], equals('@Script'));
+    expect(result['location']['type'], equals('SourceLocation'));
     expect(result['super']['type'], equals('@Class'));
     expect(result['interfaces'].length, isZero);
     expect(result['fields'].length, isPositive);
@@ -306,8 +337,7 @@
     expect(result['_kind'], equals('RegularFunction'));
     expect(result['static'], equals(false));
     expect(result['const'], equals(false));
-    expect(result['script']['type'], equals('@Script'));
-    expect(result['tokenPos'], isPositive);
+    expect(result['location']['type'], equals('SourceLocation'));
     expect(result['code']['type'], equals('@Code'));
     expect(result['_optimizable'], equals(true));
     expect(result['_inlinable'], equals(true));
@@ -352,8 +382,7 @@
     expect(result['const'], equals(false));
     expect(result['static'], equals(true));
     expect(result['final'], equals(false));
-    expect(result['script']['type'], equals('@Script'));
-    expect(result['tokenPos'], isPositive);
+    expect(result['location']['type'], equals('SourceLocation'));
     expect(result['staticValue']['valueAsString'], equals('11'));
     expect(result['_guardNullable'], isNotNull);
     expect(result['_guardClass'], isNotNull);
diff --git a/runtime/observatory/tests/service/get_stack_rpc_test.dart b/runtime/observatory/tests/service/get_stack_rpc_test.dart
index bba5575..45b3112 100644
--- a/runtime/observatory/tests/service/get_stack_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_stack_rpc_test.dart
@@ -49,8 +49,8 @@
 
   // Sanity check.
   expect(stack['frames'].length, greaterThanOrEqualTo(1));
-  Script script = stack['frames'][0]['script'];
-  expect(script.tokenToLine(stack['frames'][0]['tokenPos']),
+  Script script = stack['frames'][0].location.script;
+  expect(script.tokenToLine(stack['frames'][0].location.tokenPos),
          equals(stoppedAtLine));
 
   // Iterate over frames.
@@ -58,11 +58,10 @@
   for (var frame in stack['frames']) {
     print('checking frame $frameDepth');
     expect(frame.type, equals('Frame'));
-    expect(frame['index'], equals(frameDepth++));
-    expect(frame['code'].type, equals('Code'));
-    expect(frame['function'].type, equals('Function'));
-    expect(frame['script'].type, equals('Script'));
-    expect(frame['tokenPos'], isNotNull);
+    expect(frame.index, equals(frameDepth++));
+    expect(frame.code.type, equals('Code'));
+    expect(frame.function.type, equals('Function'));
+    expect(frame.location.type, equals('SourceLocation'));
   }
 
   // Sanity check.
@@ -74,14 +73,12 @@
   var msgHandlerObjectId;
   for (var message in stack['messages']) {
     print('checking message $messageDepth');
-    expect(message['index'], equals(messageDepth++));
-    expect(message['name'], isNotNull);
-    expect(message['size'], greaterThanOrEqualTo(1));
-    expect(message['_priority'], isNotNull);
-    expect(message['_destinationPort'], isNotNull);
-    expect(message['handlerFunction'].type, equals('Function'));
-    if (message['handlerFunction'].name.contains('msgHandler')) {
-      msgHandlerObjectId = message['messageObjectId'];
+    expect(message.index, equals(messageDepth++));
+    expect(message.size, greaterThanOrEqualTo(1));
+    expect(message.handler.type, equals('Function'));
+    expect(message.location.type, equals('SourceLocation'));
+    if (message.handler.name.contains('msgHandler')) {
+      msgHandlerObjectId = message.messageObjectId;
     }
   }
   expect(msgHandlerObjectId, isNotNull);
diff --git a/runtime/observatory/tests/service/steal_breakpoint_test.dart b/runtime/observatory/tests/service/steal_breakpoint_test.dart
index 5efc7de..bbe25d9 100644
--- a/runtime/observatory/tests/service/steal_breakpoint_test.dart
+++ b/runtime/observatory/tests/service/steal_breakpoint_test.dart
@@ -52,10 +52,10 @@
   expect(stack.type, equals('Stack'));
   expect(stack['frames'].length, greaterThanOrEqualTo(1));
 
-  Script script = stack['frames'][0]['script'];
+  Script script = stack['frames'][0].location.script;
   await script.load();
   expect(script.name,endsWith('steal_breakpoint_test.dart'));
-  expect(script.tokenToLine(stack['frames'][0]['tokenPos']), equals(14));
+  expect(script.tokenToLine(stack['frames'][0].location.tokenPos), equals(14));
 },
 
 // Resume
diff --git a/runtime/observatory/tests/service/test_helper.dart b/runtime/observatory/tests/service/test_helper.dart
index 96828ae..e69a257 100644
--- a/runtime/observatory/tests/service/test_helper.dart
+++ b/runtime/observatory/tests/service/test_helper.dart
@@ -173,6 +173,21 @@
   return completer.future;  // Will complete when breakpoint hit.
 }
 
+
+Future<Isolate> resumeIsolate(Isolate isolate) {
+  Completer completer = new Completer();
+  var subscription;
+  subscription = isolate.vm.events.stream.listen((ServiceEvent event) {
+    if (event.kind == ServiceEvent.kResume) {
+      subscription.cancel();
+      completer.complete();
+    }
+  });
+  isolate.resume();
+  return completer.future;
+}
+
+
 /// Runs [tests] in sequence, each of which should take an [Isolate] and
 /// return a [Future]. Code for setting up state can run before and/or
 /// concurrently with the tests. Uses [mainArgs] to determine whether
diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h
index 72a0737..c4343b5 100644
--- a/runtime/platform/globals.h
+++ b/runtime/platform/globals.h
@@ -334,6 +334,7 @@
 const int64_t kMinInt64 = DART_INT64_C(0x8000000000000000);
 const int64_t kMaxInt64 = DART_INT64_C(0x7FFFFFFFFFFFFFFF);
 const uint64_t kMaxUint64 = DART_2PART_UINT64_C(0xFFFFFFFF, FFFFFFFF);
+const int64_t kSignBitDouble = DART_INT64_C(0x8000000000000000);
 
 // Types for native machine words. Guaranteed to be able to hold pointers and
 // integers.
diff --git a/runtime/vm/ast.cc b/runtime/vm/ast.cc
index 613b46c..fdd39e4 100644
--- a/runtime/vm/ast.cc
+++ b/runtime/vm/ast.cc
@@ -517,7 +517,7 @@
   if (field().is_final()) {
     return NULL;
   }
-  if (Isolate::Current()->TypeChecksEnabled()) {
+  if (Isolate::Current()->flags().type_checks()) {
     rhs = new AssignableNode(
         field().token_pos(),
         rhs,
@@ -557,11 +557,14 @@
 
 
 AstNode* StaticGetterNode::MakeAssignmentNode(AstNode* rhs) {
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
+  Isolate* isolate = thread->isolate();
   if (is_super_getter()) {
     ASSERT(receiver() != NULL);
     const String& setter_name =
-        String::ZoneHandle(Field::SetterSymbol(field_name_));
-    Function& setter = Function::ZoneHandle(
+        String::ZoneHandle(zone, Field::SetterSymbol(field_name_));
+    Function& setter = Function::ZoneHandle(zone,
         Resolver::ResolveDynamicAnyArgs(cls(), setter_name));
     if (setter.IsNull() || setter.is_abstract()) {
       // No instance setter found in super class chain,
@@ -591,14 +594,14 @@
       return new StaticSetterNode(token_pos(), NULL, cls(), field_name_, rhs);
     }
 
-    Object& obj = Object::Handle(prefix.LookupObject(field_name_));
+    Object& obj = Object::Handle(zone, prefix.LookupObject(field_name_));
     if (obj.IsField()) {
-      const Field& field = Field::ZoneHandle(Field::Cast(obj).raw());
+      const Field& field = Field::ZoneHandle(zone, Field::Cast(obj).raw());
       if (!field.is_final()) {
-        if (Isolate::Current()->TypeChecksEnabled()) {
+        if (isolate->flags().type_checks()) {
           rhs = new AssignableNode(field.token_pos(),
                                    rhs,
-                                   AbstractType::ZoneHandle(field.type()),
+                                   AbstractType::ZoneHandle(zone, field.type()),
                                    field_name_);
         }
         return new StoreStaticFieldNode(token_pos(), field, rhs);
@@ -606,10 +609,12 @@
     }
 
     // No field found in prefix. Look for a setter function.
-    const String& setter_name = String::Handle(Field::SetterName(field_name_));
+    const String& setter_name = String::Handle(zone,
+                                               Field::SetterName(field_name_));
     obj = prefix.LookupObject(setter_name);
     if (obj.IsFunction()) {
-      const Function& setter = Function::ZoneHandle(Function::Cast(obj).raw());
+      const Function& setter = Function::ZoneHandle(zone,
+                                                    Function::Cast(obj).raw());
       ASSERT(setter.is_static() && setter.IsSetterFunction());
       return new StaticSetterNode(
           token_pos(), NULL, field_name_, setter, rhs);
@@ -622,14 +627,14 @@
 
   if (owner().IsLibrary()) {
     const Library& library = Library::Cast(owner());
-    Object& obj = Object::Handle(library.ResolveName(field_name_));
+    Object& obj = Object::Handle(zone, library.ResolveName(field_name_));
     if (obj.IsField()) {
-      const Field& field = Field::ZoneHandle(Field::Cast(obj).raw());
+      const Field& field = Field::ZoneHandle(zone, Field::Cast(obj).raw());
       if (!field.is_final()) {
-        if (Isolate::Current()->TypeChecksEnabled()) {
+        if (isolate->flags().type_checks()) {
           rhs = new AssignableNode(field.token_pos(),
                                    rhs,
-                                   AbstractType::ZoneHandle(field.type()),
+                                   AbstractType::ZoneHandle(zone, field.type()),
                                    field_name_);
         }
         return new StoreStaticFieldNode(token_pos(), field, rhs);
@@ -637,10 +642,12 @@
     }
 
     // No field found in library. Look for a setter function.
-    const String& setter_name = String::Handle(Field::SetterName(field_name_));
+    const String& setter_name = String::Handle(zone,
+                                               Field::SetterName(field_name_));
     obj = library.ResolveName(setter_name);
     if (obj.IsFunction()) {
-      const Function& setter = Function::ZoneHandle(Function::Cast(obj).raw());
+      const Function& setter = Function::ZoneHandle(zone,
+                                                    Function::Cast(obj).raw());
       ASSERT(setter.is_static() && setter.IsSetterFunction());
       return new StaticSetterNode(token_pos(), NULL, field_name_, setter, rhs);
     }
@@ -651,7 +658,7 @@
   }
 
   const Function& setter =
-      Function::ZoneHandle(cls().LookupSetterFunction(field_name_));
+      Function::ZoneHandle(zone, cls().LookupSetterFunction(field_name_));
   if (!setter.IsNull() && setter.IsStaticFunction()) {
     return new StaticSetterNode(token_pos(), NULL, field_name_, setter, rhs);
   }
@@ -659,7 +666,8 @@
   // Access to a lazily initialized static field that has not yet been
   // initialized is compiled to a static implicit getter.
   // A setter may not exist for such a field.
-  const Field& field = Field::ZoneHandle(cls().LookupStaticField(field_name_));
+  const Field& field = Field::ZoneHandle(zone,
+                                         cls().LookupStaticField(field_name_));
   if (!field.IsNull()) {
     if (field.is_final()) {
       // Attempting to assign to a final variable will cause a NoSuchMethodError
@@ -668,18 +676,19 @@
       return new StaticSetterNode(token_pos(), NULL, cls(), field_name_, rhs);
     }
 #if defined(DEBUG)
-    const String& getter_name = String::Handle(Field::GetterName(field_name_));
+    const String& getter_name = String::Handle(zone,
+                                               Field::GetterName(field_name_));
     const Function& getter =
-        Function::Handle(cls().LookupStaticFunction(getter_name));
+        Function::Handle(zone, cls().LookupStaticFunction(getter_name));
     ASSERT(!getter.IsNull() &&
            (getter.kind() == RawFunction::kImplicitStaticFinalGetter));
 #endif
-    if (Isolate::Current()->TypeChecksEnabled()) {
+    if (isolate->flags().type_checks()) {
       rhs = new AssignableNode(
           field.token_pos(),
           rhs,
-          AbstractType::ZoneHandle(field.type()),
-          String::ZoneHandle(field.name()));
+          AbstractType::ZoneHandle(zone, field.type()),
+          String::ZoneHandle(zone, field.name()));
     }
     return new StoreStaticFieldNode(token_pos(), field, rhs);
   }
diff --git a/runtime/vm/ast.h b/runtime/vm/ast.h
index 6da90a5..4848a3f 100644
--- a/runtime/vm/ast.h
+++ b/runtime/vm/ast.h
@@ -1972,7 +1972,7 @@
 class InlinedFinallyNode : public AstNode {
  public:
   InlinedFinallyNode(intptr_t token_pos,
-                     AstNode* finally_block,
+                     SequenceNode* finally_block,
                      const LocalVariable* context_var,
                      intptr_t try_index)
       : AstNode(token_pos),
@@ -1983,7 +1983,7 @@
     ASSERT(context_var != NULL);
   }
 
-  AstNode* finally_block() const { return finally_block_; }
+  SequenceNode* finally_block() const { return finally_block_; }
   const LocalVariable& context_var() const { return context_var_; }
   intptr_t try_index() const { return try_index_; }
 
@@ -1994,7 +1994,7 @@
   DECLARE_COMMON_NODE_FUNCTIONS(InlinedFinallyNode);
 
  private:
-  AstNode* finally_block_;
+  SequenceNode* finally_block_;
   const LocalVariable& context_var_;
   const intptr_t try_index_;
 
diff --git a/runtime/vm/benchmark_test.h b/runtime/vm/benchmark_test.h
index b26a139..de7d6ae 100644
--- a/runtime/vm/benchmark_test.h
+++ b/runtime/vm/benchmark_test.h
@@ -81,7 +81,7 @@
 
   Dart_Isolate CreateIsolate(const uint8_t* buffer) {
     char* err = NULL;
-    isolate_ = Dart_CreateIsolate(NULL, NULL, buffer, NULL, &err);
+    isolate_ = Dart_CreateIsolate(NULL, NULL, buffer, NULL, NULL, &err);
     EXPECT(isolate_ != NULL);
     free(err);
     return isolate_;
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 270b76b..227a32b 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -89,6 +89,7 @@
   V(Double_toStringAsFixed, 2)                                                 \
   V(Double_toStringAsExponential, 2)                                           \
   V(Double_toStringAsPrecision, 2)                                             \
+  V(Double_flipSignBit, 1)                                                     \
   V(JSSyntaxRegExp_factory, 4)                                                 \
   V(JSSyntaxRegExp_getPattern, 1)                                              \
   V(JSSyntaxRegExp_getIsMultiLine, 1)                                          \
@@ -293,7 +294,7 @@
   V(Int32x4_setFlagW, 2)                                                       \
   V(Int32x4_select, 3)                                                         \
   V(Isolate_spawnFunction, 4)                                                  \
-  V(Isolate_spawnUri, 6)                                                       \
+  V(Isolate_spawnUri, 7)                                                       \
   V(Isolate_getPortAndCapabilitiesOfCurrentIsolate, 0)                         \
   V(Isolate_sendOOB, 2)                                                        \
   V(Mirrors_evalInLibraryWithPrivateKey, 2)                                    \
@@ -309,7 +310,6 @@
   V(InstanceMirror_computeType, 1)                                             \
   V(ClosureMirror_function, 1)                                                 \
   V(TypeMirror_subtypeTest, 2)                                                 \
-  V(TypeMirror_moreSpecificTest, 2)                                            \
   V(ClassMirror_libraryUri, 1)                                                 \
   V(ClassMirror_supertype, 1)                                                  \
   V(ClassMirror_supertype_instantiated, 1)                                     \
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index d4b3e6d..c3c152b 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -15,10 +15,6 @@
 
 namespace dart {
 
-DEFINE_FLAG(bool, error_on_bad_override, false,
-            "Report error for bad overrides.");
-DEFINE_FLAG(bool, error_on_bad_type, false,
-            "Report error for malformed types.");
 DEFINE_FLAG(bool, print_classes, false, "Prints details about loaded classes.");
 DEFINE_FLAG(bool, trace_class_finalization, false, "Trace class finalization.");
 DEFINE_FLAG(bool, trace_type_finalization, false, "Trace type finalization.");
@@ -377,7 +373,7 @@
     return;
   }
 
-  if (Isolate::Current()->ErrorOnBadOverrideEnabled()) {
+  if (Isolate::Current()->flags().error_on_bad_override()) {
     // Verify that the target is compatible with the redirecting factory.
     Error& error = Error::Handle();
     if (!target.HasCompatibleParametersWith(factory, &error)) {
@@ -1000,7 +996,7 @@
       TypeArguments::Handle(isolate, parameterized_type.arguments());
   if (!arguments.IsNull() && (arguments.Length() != num_type_parameters)) {
     // Wrong number of type arguments. The type is mapped to the raw type.
-    if (Isolate::Current()->ErrorOnBadTypeEnabled()) {
+    if (Isolate::Current()->flags().error_on_bad_type()) {
       const String& type_class_name =
           String::Handle(isolate, type_class.Name());
       ReportError(cls, parameterized_type.token_pos(),
@@ -1371,7 +1367,7 @@
            !const_value.IsInstanceOf(type,
                                      Object::null_type_arguments(),
                                      &error))) {
-        if (Isolate::Current()->ErrorOnBadTypeEnabled()) {
+        if (Isolate::Current()->flags().error_on_bad_type()) {
           const AbstractType& const_value_type = AbstractType::Handle(
               I, const_value.GetType());
           const String& const_value_type_name = String::Handle(
@@ -1435,7 +1431,7 @@
     ResolveAndFinalizeSignature(cls, function);
     name = function.name();
     // Report signature conflicts only.
-    if (Isolate::Current()->ErrorOnBadOverrideEnabled() &&
+    if (Isolate::Current()->flags().error_on_bad_override() &&
         !function.is_static() && !function.IsGenerativeConstructor()) {
       // A constructor cannot override anything.
       for (intptr_t i = 0; i < interfaces.Length(); i++) {
@@ -2595,7 +2591,7 @@
       }
       return;
     }
-    if (Isolate::Current()->ErrorOnBadTypeEnabled()) {
+    if (Isolate::Current()->flags().error_on_bad_type()) {
       const String& type_class_name = String::Handle(type_class.Name());
       ReportError(cls, type.token_pos(),
                   "wrong number of type arguments for class '%s'",
@@ -3018,7 +3014,7 @@
           prev_error, script, type.token_pos(),
           Report::kMalformedType, Heap::kOld,
           format, args));
-  if (Isolate::Current()->ErrorOnBadTypeEnabled()) {
+  if (Isolate::Current()->flags().error_on_bad_type()) {
     ReportError(error);
   }
   type.set_error(error);
@@ -3080,7 +3076,7 @@
           Report::kMalboundedType, Heap::kOld,
           format, args));
   va_end(args);
-  if (Isolate::Current()->ErrorOnBadTypeEnabled()) {
+  if (Isolate::Current()->flags().error_on_bad_type()) {
     ReportError(error);
   }
   type.set_error(error);
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index 08e9e16..4485c58 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -225,7 +225,7 @@
   // Code inlined in the caller should have optimized the case where the
   // instantiator can be reused as type argument vector.
   ASSERT(instantiator.IsNull() || !type_arguments.IsUninstantiatedIdentity());
-  if (Isolate::Current()->TypeChecksEnabled()) {
+  if (isolate->flags().type_checks()) {
     Error& bound_error = Error::Handle();
     type_arguments =
         type_arguments.InstantiateAndCanonicalizeFrom(instantiator,
@@ -530,7 +530,7 @@
     }
     String& bound_error_message =  String::Handle();
     if (!bound_error.IsNull()) {
-      ASSERT(Isolate::Current()->TypeChecksEnabled());
+      ASSERT(isolate->flags().type_checks());
       bound_error_message = String::New(bound_error.ToErrorCString());
     }
     if (src_type_name.Equals(dst_type_name)) {
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index 57cfa7f..05093ea 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -790,6 +790,9 @@
           }
         }
       }
+      // Mark that this isolate now has compiled code.
+      isolate->set_has_compiled(true);
+      // Exit the loop and the function with the correct result value.
       is_compiled = true;
       done = true;
     } else {
@@ -1191,6 +1194,7 @@
       if (!error.IsNull()) {
         return error.raw();
       }
+      func.ClearICDataArray();
       func.ClearCode();
     }
   }
@@ -1207,6 +1211,7 @@
         if (!error.IsNull()) {
           return error.raw();
         }
+        func.ClearICDataArray();
         func.ClearCode();
       }
     }
diff --git a/runtime/vm/compiler_test.cc b/runtime/vm/compiler_test.cc
index 1351fbc..7b6ada7 100644
--- a/runtime/vm/compiler_test.cc
+++ b/runtime/vm/compiler_test.cc
@@ -13,8 +13,6 @@
 
 namespace dart {
 
-DECLARE_FLAG(bool, enable_type_checks);
-
 TEST_CASE(CompileScript) {
   const char* kScriptChars =
       "class A {\n"
@@ -81,8 +79,7 @@
             "  return unOpt();\n"
             "}\n";
 
-  bool old_enable_type_checks = FLAG_enable_type_checks;
-  FLAG_enable_type_checks = true;
+  // Isolate::Current()->flags().set_checked(true);
   Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
   Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
   EXPECT_VALID(result);
@@ -109,8 +106,6 @@
   owner.DisableAllocationStub();
   result = Dart_Invoke(lib, NewString("main"), 0, NULL);
   EXPECT_VALID(result);
-
-  FLAG_enable_type_checks = old_enable_type_checks;
 }
 
 
diff --git a/runtime/vm/cpuinfo_macos.cc b/runtime/vm/cpuinfo_macos.cc
index 6300d7c..6352391 100644
--- a/runtime/vm/cpuinfo_macos.cc
+++ b/runtime/vm/cpuinfo_macos.cc
@@ -85,7 +85,7 @@
   ASSERT(method_ != kCpuInfoDefault);
   ASSERT(field != NULL);
   int ret = sysctlbyname(field, NULL, NULL, NULL, 0);
-  return (ret != ENOENT);
+  return (ret == 0);
 }
 
 }  // namespace dart
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 4b6b5fb..d49b7f4 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -118,7 +118,13 @@
     ASSERT(Flags::Initialized());
     const bool is_vm_isolate = true;
     Thread::EnsureInit();
-    vm_isolate_ = Isolate::Init("vm-isolate", is_vm_isolate);
+
+    // Setup default flags for the VM isolate.
+    Isolate::Flags vm_flags;
+    Dart_IsolateFlags api_flags;
+    vm_flags.CopyTo(&api_flags);
+    vm_isolate_ = Isolate::Init("vm-isolate", api_flags, is_vm_isolate);
+
     StackZone zone(vm_isolate_);
     HandleScope handle_scope(vm_isolate_);
     Heap::Init(vm_isolate_,
@@ -226,9 +232,10 @@
 }
 
 
-Isolate* Dart::CreateIsolate(const char* name_prefix) {
+Isolate* Dart::CreateIsolate(const char* name_prefix,
+                             const Dart_IsolateFlags& api_flags) {
   // Create a new isolate.
-  Isolate* isolate = Isolate::Init(name_prefix);
+  Isolate* isolate = Isolate::Init(name_prefix, api_flags);
   ASSERT(isolate != NULL);
   return isolate;
 }
diff --git a/runtime/vm/dart.h b/runtime/vm/dart.h
index 470b3ff..a3234ca 100644
--- a/runtime/vm/dart.h
+++ b/runtime/vm/dart.h
@@ -32,7 +32,8 @@
       Dart_EntropySource entropy_source);
   static const char* Cleanup();
 
-  static Isolate* CreateIsolate(const char* name_prefix);
+  static Isolate* CreateIsolate(const char* name_prefix,
+                                const Dart_IsolateFlags& api_flags);
   static RawError* InitializeIsolate(const uint8_t* snapshot, void* data);
   static void RunShutdownCallback();
   static void ShutdownIsolate();
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index a913a12..bc36704 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -47,7 +47,7 @@
 DECLARE_FLAG(bool, print_class_table);
 DECLARE_FLAG(bool, verify_handles);
 #if defined(DART_NO_SNAPSHOT)
-DEFINE_FLAG(bool, check_function_fingerprints, false,
+DEFINE_FLAG(bool, check_function_fingerprints, true,
             "Check function fingerprints");
 #endif  // defined(DART_NO_SNAPSHOT).
 DEFINE_FLAG(bool, trace_api, false,
@@ -1287,12 +1287,21 @@
 DART_EXPORT Dart_Isolate Dart_CreateIsolate(const char* script_uri,
                                             const char* main,
                                             const uint8_t* snapshot,
+                                            Dart_IsolateFlags* flags,
                                             void* callback_data,
                                             char** error) {
   CHECK_NO_ISOLATE(Isolate::Current());
   char* isolate_name = BuildIsolateName(script_uri, main);
   Thread::EnsureInit();
-  Isolate* isolate = Dart::CreateIsolate(isolate_name);
+
+  // Setup default flags in case none were passed.
+  Dart_IsolateFlags api_flags;
+  if (flags == NULL) {
+    Isolate::Flags vm_flags;
+    vm_flags.CopyTo(&api_flags);
+    flags = &api_flags;
+  }
+  Isolate* isolate = Dart::CreateIsolate(isolate_name, *flags);
   free(isolate_name);
   StackZone zone(isolate);
   HANDLESCOPE(isolate);
@@ -1405,6 +1414,7 @@
 }
 
 
+// TODO(iposva): Remove this API and instead expose the underlying flags.
 DART_EXPORT Dart_Handle Dart_IsolateSetStrictCompilation(bool value) {
   CHECK_ISOLATE(Isolate::Current());
   Isolate* isolate = Isolate::Current();
@@ -1412,7 +1422,11 @@
     return Api::NewError(
         "%s expects that the isolate has not yet compiled code.", CURRENT_FUNC);
   }
-  Isolate::Current()->set_strict_compilation(value);
+  if (!value) {
+    return Api::NewError(
+        "%s expects that the value is set to true only.", CURRENT_FUNC);
+  }
+  Isolate::Current()->set_strict_compilation();
   return Api::Null();
 }
 
@@ -3999,8 +4013,6 @@
   // other operations (gc, compilation) are active.
   TIMERSCOPE(isolate, time_dart_execution);
 
-  isolate->set_has_compiled(true);
-
   const String& function_name = Api::UnwrapStringHandle(isolate, name);
   if (function_name.IsNull()) {
     RETURN_TYPE_ERROR(isolate, name, String);
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index e7717f8..b79780c 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -3711,7 +3711,7 @@
   intptr_t mydata = 12345;
   char* err;
   Dart_Isolate isolate =
-      Dart_CreateIsolate(NULL, NULL, bin::isolate_snapshot_buffer,
+      Dart_CreateIsolate(NULL, NULL, bin::isolate_snapshot_buffer, NULL,
                          reinterpret_cast<void*>(mydata),
                          &err);
   EXPECT(isolate != NULL);
@@ -7311,6 +7311,7 @@
 static Dart_Isolate RunLoopTestCallback(const char* script_name,
                                         const char* main,
                                         const char* package_root,
+                                        Dart_IsolateFlags* flags,
                                         void* data,
                                         char** error) {
   const char* kScriptChars =
@@ -7383,7 +7384,8 @@
   Dart_IsolateCreateCallback saved = Isolate::CreateCallback();
   Isolate::SetCreateCallback(RunLoopTestCallback);
   Isolate::SetUnhandledExceptionCallback(RunLoopUnhandledExceptionCallback);
-  Dart_Isolate isolate = RunLoopTestCallback(NULL, NULL, NULL, NULL, NULL);
+  Dart_Isolate isolate = RunLoopTestCallback(
+      NULL, NULL, NULL, NULL, NULL, NULL);
 
   Dart_EnterIsolate(isolate);
   Dart_EnterScope();
@@ -7485,6 +7487,7 @@
     char* error = NULL;
     shared_isolate = Dart_CreateIsolate(NULL, NULL,
                                         bin::isolate_snapshot_buffer,
+                                        NULL,
                                         NULL, &error);
     EXPECT(shared_isolate != NULL);
     Dart_EnterScope();
@@ -7613,6 +7616,7 @@
   char* err;
   Dart_Isolate isolate = Dart_CreateIsolate(NULL, NULL,
                                             bin::isolate_snapshot_buffer,
+                                            NULL,
                                             my_data, &err);
   if (isolate == NULL) {
     OS::Print("Creation of isolate failed '%s'\n", err);
@@ -7663,6 +7667,7 @@
   char* err;
   Dart_Isolate isolate = Dart_CreateIsolate(NULL, NULL,
                                             bin::isolate_snapshot_buffer,
+                                            NULL,
                                             NULL, &err);
   if (isolate == NULL) {
     OS::Print("Creation of isolate failed '%s'\n", err);
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 57190db..939dafd 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -199,12 +199,7 @@
   Script& script = Script::Handle(isolate);
   intptr_t token_pos;
   bpt_location_->GetCodeLocation(&library, &script, &token_pos);
-  {
-    JSONObject location(&jsobj, "location");
-    location.AddProperty("type", "Location");
-    location.AddProperty("script", script);
-    location.AddProperty("tokenPos", token_pos);
-  }
+  jsobj.AddLocation(script, token_pos);
 }
 
 
@@ -240,7 +235,32 @@
 
 
 bool Debugger::HasEventHandler() {
-  return (event_handler_ != NULL) || Service::NeedsEvents();
+  return ((event_handler_ != NULL) ||
+          Service::NeedsIsolateEvents() ||
+          Service::NeedsDebugEvents());
+}
+
+
+static bool ServiceNeedsDebuggerEvent(DebuggerEvent::EventType type) {
+  switch (type) {
+    case DebuggerEvent::kBreakpointResolved:
+      // kBreakpointResolved events are handled differently in the vm
+      // service, so suppress them here.
+      return false;
+
+    case DebuggerEvent::kBreakpointReached:
+    case DebuggerEvent::kExceptionThrown:
+    case DebuggerEvent::kIsolateInterrupted:
+      return Service::NeedsDebugEvents();
+
+    case DebuggerEvent::kIsolateCreated:
+    case DebuggerEvent::kIsolateShutdown:
+      return Service::NeedsIsolateEvents();
+
+    default:
+      UNREACHABLE();
+      return false;
+  }
 }
 
 
@@ -252,8 +272,7 @@
   //
   // kBreakpointResolved events are handled differently in the vm
   // service, so suppress them here.
-  if (Service::NeedsEvents() &&
-      (event->type() != DebuggerEvent::kBreakpointResolved)) {
+  if (ServiceNeedsDebuggerEvent(event->type())) {
     ServiceEvent service_event(event);
     Service::HandleEvent(&service_event);
   }
@@ -265,7 +284,7 @@
     (*event_handler_)(event);
   }
 
-  if (Service::NeedsEvents() && event->IsPauseEvent()) {
+  if (ServiceNeedsDebuggerEvent(event->type()) && event->IsPauseEvent()) {
     // If we were paused, notify the service that we have resumed.
     ServiceEvent service_event(event->isolate(), ServiceEvent::kResume);
     service_event.set_top_frame(event->top_frame());
@@ -308,7 +327,7 @@
 // than the regular debugger breakpoint notifications.
 static void SendServiceBreakpointEvent(ServiceEvent::EventType type,
                                        Breakpoint* bpt) {
-  if (Service::NeedsEvents()) {
+  if (Service::NeedsDebugEvents()) {
     ServiceEvent service_event(Isolate::Current(), type);
     service_event.set_breakpoint(bpt);
     Service::HandleEvent(&service_event);
@@ -1004,10 +1023,15 @@
                                         bool full) {
   const Script& script = Script::Handle(SourceScript());
   jsobj->AddProperty("type", "Frame");
-  jsobj->AddProperty("script", script, !full);
-  jsobj->AddProperty("tokenPos", TokenPos());
+  jsobj->AddLocation(script, TokenPos());
   jsobj->AddProperty("function", function(), !full);
   jsobj->AddProperty("code", code());
+  if (full) {
+    // TODO(cutch): The old "full" script usage no longer fits
+    // in the world where we pass the script as part of the
+    // location.
+    jsobj->AddProperty("script", script, !full);
+  }
   {
     JSONArray jsvars(jsobj, "vars");
     const int num_vars = NumLocalVariables();
@@ -1020,8 +1044,11 @@
       VariableAt(v, &var_name, &token_pos, &end_token_pos, &var_value);
       jsvar.AddProperty("name", var_name.ToCString());
       jsvar.AddProperty("value", var_value, !full);
-      jsvar.AddProperty("tokenPos", token_pos);
-      jsvar.AddProperty("endTokenPos", end_token_pos);
+      // TODO(turnidge): Do we really want to provide this on every
+      // stack dump?  Should be associated with the function object, I
+      // think, and not the stack frame.
+      jsvar.AddProperty("_tokenPos", token_pos);
+      jsvar.AddProperty("_endTokenPos", end_token_pos);
     }
   }
 }
diff --git a/runtime/vm/debugger_test.cc b/runtime/vm/debugger_test.cc
index 72eff9e..9ccfce1 100644
--- a/runtime/vm/debugger_test.cc
+++ b/runtime/vm/debugger_test.cc
@@ -71,14 +71,14 @@
         js.ToCString(),
         "[{\"type\":\"Breakpoint\",\"fixedId\":true,\"id\":\"breakpoints\\/2\","
         "\"breakpointNumber\":2,\"resolved\":false,"
-        "\"location\":{\"type\":\"Location\","
+        "\"location\":{\"type\":\"SourceLocation\","
         "\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
         "\"id\":\"libraries\\/%" Pd "\\/scripts\\/test-lib\","
         "\"uri\":\"test-lib\","
         "\"_kind\":\"script\"},\"tokenPos\":14}},"
         "{\"type\":\"Breakpoint\",\"fixedId\":true,\"id\":\"breakpoints\\/1\","
         "\"breakpointNumber\":1,\"resolved\":false,"
-        "\"location\":{\"type\":\"Location\","
+        "\"location\":{\"type\":\"SourceLocation\","
         "\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
         "\"id\":\"libraries\\/%" Pd "\\/scripts\\/test-lib\","
         "\"uri\":\"test-lib\","
diff --git a/runtime/vm/flags.cc b/runtime/vm/flags.cc
index b9cda6a..f38639f 100644
--- a/runtime/vm/flags.cc
+++ b/runtime/vm/flags.cc
@@ -427,6 +427,7 @@
   JSONObject jsflag(jsarr);
   jsflag.AddProperty("name", flag->name_);
   jsflag.AddProperty("comment", flag->comment_);
+  jsflag.AddProperty("modified", flag->changed_);
   switch (flag->type_) {
     case Flag::kBoolean: {
       jsflag.AddProperty("_flagType", "Bool");
@@ -463,23 +464,9 @@
 void Flags::PrintJSON(JSONStream* js) {
   JSONObject jsobj(js);
   jsobj.AddProperty("type", "FlagList");
-  {
-    JSONArray jsarr(&jsobj, "unmodifiedFlags");
-    for (intptr_t i = 0; i < num_flags_; ++i) {
-      Flag* flag = flags_[i];
-      if (!flag->changed_) {
-        PrintFlagToJSONArray(&jsarr, flag);
-      }
-    }
-  }
-  {
-    JSONArray jsarr(&jsobj, "modifiedFlags");
-    for (intptr_t i = 0; i < num_flags_; ++i) {
-      Flag* flag = flags_[i];
-      if (flag->changed_) {
-        PrintFlagToJSONArray(&jsarr, flag);
-      }
-    }
+  JSONArray jsarr(&jsobj, "flags");
+  for (intptr_t i = 0; i < num_flags_; ++i) {
+    PrintFlagToJSONArray(&jsarr, flags_[i]);
   }
 }
 
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index aa73c55..a90c9fa 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -113,6 +113,7 @@
   JoinEntryInstr* break_target() const { return break_target_; }
 
   virtual intptr_t ContextLevel() const;
+  virtual void AdjustContextLevel(intptr_t context_level);
 
   virtual JoinEntryInstr* BreakTargetFor(SourceLabel* label);
   virtual JoinEntryInstr* ContinueTargetFor(SourceLabel* label);
@@ -152,6 +153,13 @@
 }
 
 
+void NestedStatement::AdjustContextLevel(intptr_t context_level) {
+  // There must be a NestedContextAdjustment on the nesting stack.
+  ASSERT(outer() != NULL);
+  outer()->AdjustContextLevel(context_level);
+}
+
+
 intptr_t FlowGraphBuilder::context_level() const {
   return (nesting_stack() == NULL) ? 0 : nesting_stack()->ContextLevel();
 }
@@ -162,7 +170,7 @@
   if (break_target_ == NULL) {
     break_target_ =
         new(owner()->zone()) JoinEntryInstr(owner()->AllocateBlockId(),
-                                               owner()->try_index());
+                                            owner()->try_index());
   }
   return break_target_;
 }
@@ -193,6 +201,24 @@
 }
 
 
+// A nested statement reflecting a context level adjustment.
+class NestedContextAdjustment : public NestedStatement {
+ public:
+  NestedContextAdjustment(FlowGraphBuilder* owner, intptr_t context_level)
+      : NestedStatement(owner, NULL), context_level_(context_level) { }
+
+  virtual intptr_t ContextLevel() const { return context_level_; }
+
+  virtual void AdjustContextLevel(intptr_t context_level) {
+    ASSERT(context_level <= context_level_);
+    context_level_ = context_level;
+  }
+
+ private:
+  intptr_t context_level_;
+};
+
+
 // A nested statement that can be the target of a continue as well as a
 // break.
 class NestedLoop : public NestedStatement {
@@ -925,8 +951,9 @@
 
 
 void TestGraphVisitor::ReturnValue(Value* value) {
-  if (Isolate::Current()->TypeChecksEnabled() ||
-      Isolate::Current()->AssertsEnabled()) {
+  Isolate* isolate = Isolate::Current();
+  if (isolate->flags().type_checks() ||
+      isolate->flags().asserts()) {
     value = Bind(new(Z) AssertBooleanInstr(condition_token_pos(), value));
   }
   Value* constant_true = Bind(new(Z) ConstantInstr(Bool::True()));
@@ -961,7 +988,7 @@
         false));  // No number check.
   } else {
     branch = new(Z) BranchInstr(comp);
-    branch->set_is_checked(Isolate::Current()->TypeChecksEnabled());
+    branch->set_is_checked(Isolate::Current()->flags().type_checks());
   }
   AddInstruction(branch);
   CloseFragment();
@@ -971,7 +998,7 @@
 
 
 void TestGraphVisitor::MergeBranchWithNegate(BooleanNegateInstr* neg) {
-  ASSERT(!Isolate::Current()->TypeChecksEnabled());
+  ASSERT(!Isolate::Current()->flags().type_checks());
   Value* constant_true = Bind(new(Z) ConstantInstr(Bool::True()));
   StrictCompareInstr* comp =
       new(Z) StrictCompareInstr(condition_token_pos(),
@@ -993,7 +1020,7 @@
     MergeBranchWithComparison(comp);
     return;
   }
-  if (!Isolate::Current()->TypeChecksEnabled()) {
+  if (!Isolate::Current()->flags().type_checks()) {
     BooleanNegateInstr* neg = definition->AsBooleanNegate();
     if (neg != NULL) {
       MergeBranchWithNegate(neg);
@@ -1055,6 +1082,20 @@
   Append(for_value);
   Value* return_value = for_value.value();
 
+  // Call to stub that checks whether the debugger is in single
+  // step mode. This call must happen before the contexts are
+  // unchained so that captured variables can be inspected.
+  // No debugger check is done in native functions or for return
+  // statements for which there is no associated source position.
+  const Function& function = owner()->function();
+  if (FLAG_support_debugger &&
+      (node->token_pos() != Scanner::kNoSourcePos) && !function.is_native()) {
+    AddInstruction(new(Z) DebugStepCheckInstr(node->token_pos(),
+                                              RawPcDescriptors::kRuntimeCall));
+  }
+
+  NestedContextAdjustment context_adjustment(owner(), owner()->context_level());
+
   if (node->inlined_finally_list_length() > 0) {
     LocalVariable* temp = owner()->parsed_function().finally_return_temp_var();
     ASSERT(temp != NULL);
@@ -1071,19 +1112,7 @@
     return_value = Bind(BuildLoadLocal(*temp));
   }
 
-  // Call to stub that checks whether the debugger is in single
-  // step mode. This call must happen before the contexts are
-  // unchained so that captured variables can be inspected.
-  // No debugger check is done in native functions or for return
-  // statements for which there is no associated source position.
-  const Function& function = owner()->function();
-  if (FLAG_support_debugger &&
-      (node->token_pos() != Scanner::kNoSourcePos) && !function.is_native()) {
-    AddInstruction(new(Z) DebugStepCheckInstr(node->token_pos(),
-                                              RawPcDescriptors::kRuntimeCall));
-  }
-
-  if (Isolate::Current()->TypeChecksEnabled()) {
+  if (Isolate::Current()->flags().type_checks()) {
     const bool is_implicit_dynamic_getter =
         (!function.is_static() &&
         ((function.kind() == RawFunction::kImplicitGetter) ||
@@ -1283,8 +1312,9 @@
     TestGraphVisitor for_left(owner(), node->left()->token_pos());
     node->left()->Visit(&for_left);
     EffectGraphVisitor empty(owner());
-    if (Isolate::Current()->TypeChecksEnabled() ||
-        Isolate::Current()->AssertsEnabled()) {
+    Isolate* isolate = Isolate::Current();
+    if (isolate->flags().type_checks() ||
+        isolate->flags().asserts()) {
       ValueGraphVisitor for_right(owner());
       node->right()->Visit(&for_right);
       Value* right_value = for_right.value();
@@ -1349,8 +1379,9 @@
     ValueGraphVisitor for_right(owner());
     node->right()->Visit(&for_right);
     Value* right_value = for_right.value();
-    if (Isolate::Current()->TypeChecksEnabled() ||
-        Isolate::Current()->AssertsEnabled()) {
+    Isolate* isolate = Isolate::Current();
+    if (isolate->flags().type_checks() ||
+        isolate->flags().asserts()) {
       right_value =
           for_right.Bind(new(Z) AssertBooleanInstr(node->right()->token_pos(),
                                                    right_value));
@@ -1886,8 +1917,9 @@
         kNumArgsChecked,
         owner()->ic_data_array());
     if (node->kind() == Token::kNE) {
-      if (Isolate::Current()->TypeChecksEnabled() ||
-          Isolate::Current()->AssertsEnabled()) {
+      Isolate* isolate = Isolate::Current();
+      if (isolate->flags().type_checks() ||
+          isolate->flags().asserts()) {
         Value* value = Bind(result);
         result = new(Z) AssertBooleanInstr(node->token_pos(), value);
       }
@@ -1933,8 +1965,9 @@
     node->operand()->Visit(&for_value);
     Append(for_value);
     Value* value = for_value.value();
-    if (Isolate::Current()->TypeChecksEnabled() ||
-        Isolate::Current()->AssertsEnabled()) {
+    Isolate* isolate = Isolate::Current();
+    if (isolate->flags().type_checks() ||
+        isolate->flags().asserts()) {
       value =
           Bind(new(Z) AssertBooleanInstr(node->operand()->token_pos(), value));
     }
@@ -2295,6 +2328,8 @@
 
 
 void EffectGraphVisitor::VisitJumpNode(JumpNode* node) {
+  NestedContextAdjustment context_adjustment(owner(), owner()->context_level());
+
   for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) {
     EffectGraphVisitor for_effect(owner());
     node->InlinedFinallyNodeAt(i)->Visit(&for_effect);
@@ -2306,27 +2341,7 @@
   // contains the destination label.
   SourceLabel* label = node->label();
   ASSERT(label->owner() != NULL);
-  int target_context_level = 0;
-  LocalScope* target_scope = label->owner();
-  if (target_scope->num_context_variables() > 0) {
-    // The scope of the target label allocates a context, therefore its outer
-    // scope is at a lower context level.
-    target_context_level = target_scope->context_level() - 1;
-  } else {
-    // The scope of the target label does not allocate a context, so its outer
-    // scope is at the same context level. Find it.
-    while ((target_scope != NULL) &&
-           (target_scope->num_context_variables() == 0)) {
-      target_scope = target_scope->parent();
-    }
-    if (target_scope != NULL) {
-      target_context_level = target_scope->context_level();
-    }
-  }
-  ASSERT(target_context_level >= 0);
-  intptr_t current_context_level = owner()->context_level();
-  ASSERT(current_context_level >= target_context_level);
-  UnchainContexts(current_context_level - target_context_level);
+  AdjustContextLevel(label->owner());
 
   JoinEntryInstr* jump_target = NULL;
   NestedStatement* current = owner()->nesting_stack();
@@ -3450,7 +3465,7 @@
         return ReturnDefinition(BuildNativeGetter(
             node, kind, LinkedHashMap::index_offset(),
             Type::ZoneHandle(Z, Type::DynamicType()),
-            kTypedDataUint32ArrayCid));
+            kDynamicCid));
       }
       case MethodRecognizer::kLinkedHashMap_setIndex: {
         return ReturnDefinition(DoNativeSetterStoreValue(
@@ -3555,7 +3570,7 @@
   node->value()->Visit(&for_value);
   Append(for_value);
   Value* store_value = for_value.value();
-  if (Isolate::Current()->TypeChecksEnabled()) {
+  if (Isolate::Current()->flags().type_checks()) {
     store_value = BuildAssignableValue(node->value()->token_pos(),
                                        store_value,
                                        node->local().type(),
@@ -3596,7 +3611,7 @@
   node->value()->Visit(&for_value);
   Append(for_value);
   Value* store_value = for_value.value();
-  if (Isolate::Current()->TypeChecksEnabled()) {
+  if (Isolate::Current()->flags().type_checks()) {
     const AbstractType& type =
         AbstractType::ZoneHandle(Z, node->field().type());
     const String& dst_name = String::ZoneHandle(Z, node->field().name());
@@ -3867,6 +3882,33 @@
 }
 
 
+void EffectGraphVisitor::AdjustContextLevel(LocalScope* target_scope) {
+  ASSERT(target_scope != NULL);
+  intptr_t target_context_level = 0;
+  if (target_scope->num_context_variables() > 0) {
+    // The scope of the target label allocates a context, therefore its outer
+    // scope is at a lower context level.
+    target_context_level = target_scope->context_level() - 1;
+  } else {
+    // The scope of the target label does not allocate a context, so its outer
+    // scope is at the same context level. Find it.
+    while ((target_scope != NULL) &&
+           (target_scope->num_context_variables() == 0)) {
+      target_scope = target_scope->parent();
+    }
+    if (target_scope != NULL) {
+      target_context_level = target_scope->context_level();
+    }
+  }
+  ASSERT(target_context_level >= 0);
+  intptr_t current_context_level = owner()->context_level();
+  ASSERT(current_context_level >= target_context_level);
+  UnchainContexts(current_context_level - target_context_level);
+  // Record adjusted context level.
+  owner()->nesting_stack()->AdjustContextLevel(target_context_level);
+}
+
+
 // <Statement> ::= Sequence { scope: LocalScope
 //                            nodes: <Statement>*
 //                            label: SourceLabel }
@@ -3960,7 +4002,7 @@
     }
   }
 
-  if (Isolate::Current()->TypeChecksEnabled() && is_top_level_sequence) {
+  if (Isolate::Current()->flags().type_checks() && is_top_level_sequence) {
     const int num_params = function.NumParameters();
     int pos = 0;
     if (function.IsGenerativeConstructor()) {
@@ -4406,12 +4448,15 @@
   }
 
   // Note: do not restore the saved_try_context here since the inlined
-  // code is running at he context level of the return or jump instruction
-  // that follows the inlined code. See issue 22822.
+  // code is not reached via an exception handler, therefore the context is
+  // always properly set on entry. In other words, the inlined finally clause is
+  // never the target of a long jump that would find an uninitialized current
+  // context variable.
 
   JoinEntryInstr* finally_entry =
       new(Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
   EffectGraphVisitor for_finally_block(owner());
+  for_finally_block.AdjustContextLevel(node->finally_block()->scope());
   node->finally_block()->Visit(&for_finally_block);
 
   if (try_index >= 0) {
diff --git a/runtime/vm/flow_graph_builder.h b/runtime/vm/flow_graph_builder.h
index 4c127f1..2115065 100644
--- a/runtime/vm/flow_graph_builder.h
+++ b/runtime/vm/flow_graph_builder.h
@@ -407,6 +407,10 @@
   // Moves the nth parent context into the context register.
   void UnchainContexts(intptr_t n);
 
+  // Unchain the current context until its level matches the context level
+  // expected on entry at the target specified by its scope.
+  void AdjustContextLevel(LocalScope* target_scope);
+
   void CloseFragment() { exit_ = NULL; }
 
   // Returns a local variable index for a temporary local that is
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index ff214ae..169c857 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -980,7 +980,7 @@
 void FlowGraphCompiler::TryIntrinsify() {
   // Intrinsification skips arguments checks, therefore disable if in checked
   // mode.
-  if (FLAG_intrinsify && !isolate()->TypeChecksEnabled()) {
+  if (FLAG_intrinsify && !isolate()->flags().type_checks()) {
     if (parsed_function().function().kind() == RawFunction::kImplicitGetter) {
       // An implicit getter must have a specific AST structure.
       const SequenceNode& sequence_node = *parsed_function().node_sequence();
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index c51d952..2db078f 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -1231,7 +1231,7 @@
                                    call->GetBlock()->try_index());
   (*entry)->InheritDeoptTarget(Z, call);
   Instruction* cursor = *entry;
-  if (I->TypeChecksEnabled()) {
+  if (I->flags().type_checks()) {
     // Only type check for the value. A type check for the index is not
     // needed here because we insert a deoptimizing smi-check for the case
     // the index is not a smi.
@@ -4570,7 +4570,7 @@
                                                  const ICData& unary_ic_data) {
   ASSERT((unary_ic_data.NumberOfChecks() > 0) &&
       (unary_ic_data.NumArgsTested() == 1));
-  if (I->TypeChecksEnabled()) {
+  if (I->flags().type_checks()) {
     // Checked mode setters are inlined like normal methods by conventional
     // inlining.
     return false;
diff --git a/runtime/vm/flow_graph_type_propagator.cc b/runtime/vm/flow_graph_type_propagator.cc
index 64471b7..f1ec8ba 100644
--- a/runtime/vm/flow_graph_type_propagator.cc
+++ b/runtime/vm/flow_graph_type_propagator.cc
@@ -38,7 +38,7 @@
     types_.Add(NULL);
   }
 
-  if (Isolate::Current()->TypeChecksEnabled()) {
+  if (Isolate::Current()->flags().type_checks()) {
     asserts_ = new ZoneGrowableArray<AssertAssignableInstr*>(
         flow_graph->current_ssa_temp_index());
     for (intptr_t i = 0; i < flow_graph->current_ssa_temp_index(); i++) {
@@ -120,7 +120,7 @@
 
   const intptr_t rollback_point = rollback_.length();
 
-  if (Isolate::Current()->TypeChecksEnabled()) {
+  if (Isolate::Current()->flags().type_checks()) {
     StrengthenAsserts(block);
   }
 
@@ -921,7 +921,7 @@
     return CompileType::FromCid(result_cid_);
   }
 
-  if (Isolate::Current()->TypeChecksEnabled()) {
+  if (Isolate::Current()->flags().type_checks()) {
     // Void functions are known to return null, which is checked at the return
     // from the function.
     const AbstractType& result_type =
@@ -936,7 +936,7 @@
 
 
 CompileType LoadLocalInstr::ComputeType() const {
-  if (Isolate::Current()->TypeChecksEnabled()) {
+  if (Isolate::Current()->flags().type_checks()) {
     return CompileType::FromAbstractType(local().type());
   }
   return CompileType::Dynamic();
@@ -980,7 +980,7 @@
   intptr_t cid = kDynamicCid;
   AbstractType* abstract_type = NULL;
   const Field& field = this->StaticField();
-  if (Isolate::Current()->TypeChecksEnabled()) {
+  if (Isolate::Current()->flags().type_checks()) {
     cid = kIllegalCid;
     abstract_type = &AbstractType::ZoneHandle(field.type());
   }
@@ -1038,7 +1038,7 @@
   }
 
   const AbstractType* abstract_type = NULL;
-  if (Isolate::Current()->TypeChecksEnabled()) {
+  if (Isolate::Current()->flags().type_checks()) {
     ASSERT(!type().HasResolvedTypeClass() ||
            !Field::IsExternalizableCid(Class::Handle(
                 type().type_class()).id()));
diff --git a/runtime/vm/heap.cc b/runtime/vm/heap.cc
index 4ff0080..3b92f94 100644
--- a/runtime/vm/heap.cc
+++ b/runtime/vm/heap.cc
@@ -620,7 +620,7 @@
   stats_.after_.old_ = old_space_->GetCurrentUsage();
   ASSERT(gc_in_progress_);
   gc_in_progress_ = false;
-  if (Service::NeedsEvents()) {
+  if (Service::NeedsGCEvents()) {
     ServiceEvent event(Isolate::Current(), ServiceEvent::kGC);
     event.set_gc_stats(&stats_);
     Service::HandleEvent(&event);
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index c5077d0..f78c295 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -2029,7 +2029,7 @@
 
 
 Definition* InstantiateTypeArgumentsInstr::Canonicalize(FlowGraph* flow_graph) {
-  return (Isolate::Current()->TypeChecksEnabled() || HasUses()) ? this : NULL;
+  return (Isolate::Current()->flags().type_checks() || HasUses()) ? this : NULL;
 }
 
 
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index 41921f0..34ab638 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -25,7 +25,6 @@
 namespace dart {
 
 DECLARE_FLAG(bool, emit_edge_counters);
-DECLARE_FLAG(bool, enable_asserts);
 DECLARE_FLAG(int, optimization_counter_threshold);
 DECLARE_FLAG(bool, use_osr);
 
@@ -374,13 +373,13 @@
   ASSERT(locs->always_calls());
   Label done;
 
-  if (Isolate::Current()->TypeChecksEnabled()) {
+  if (Isolate::Current()->flags().type_checks()) {
     __ CompareObject(reg, Bool::True());
     __ b(&done, EQ);
     __ CompareObject(reg, Bool::False());
     __ b(&done, EQ);
   } else {
-    ASSERT(FLAG_enable_asserts);
+    ASSERT(Isolate::Current()->flags().asserts());
     __ CompareObject(reg, Object::null_instance());
     __ b(&done, NE);
   }
diff --git a/runtime/vm/intermediate_language_arm64.cc b/runtime/vm/intermediate_language_arm64.cc
index a260302..38edabd 100644
--- a/runtime/vm/intermediate_language_arm64.cc
+++ b/runtime/vm/intermediate_language_arm64.cc
@@ -24,7 +24,6 @@
 namespace dart {
 
 DECLARE_FLAG(bool, emit_edge_counters);
-DECLARE_FLAG(bool, enable_asserts);
 DECLARE_FLAG(int, optimization_counter_threshold);
 DECLARE_FLAG(bool, use_osr);
 
@@ -362,13 +361,13 @@
   ASSERT(locs->always_calls());
   Label done;
 
-  if (Isolate::Current()->TypeChecksEnabled()) {
+  if (Isolate::Current()->flags().type_checks()) {
     __ CompareObject(reg, Bool::True(), PP);
     __ b(&done, EQ);
     __ CompareObject(reg, Bool::False(), PP);
     __ b(&done, EQ);
   } else {
-    ASSERT(FLAG_enable_asserts);
+    ASSERT(Isolate::Current()->flags().asserts());
     __ CompareObject(reg, Object::null_instance(), PP);
     __ b(&done, NE);
   }
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index a4c8d41..06300e6 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -23,7 +23,6 @@
 namespace dart {
 
 DECLARE_FLAG(bool, emit_edge_counters);
-DECLARE_FLAG(bool, enable_asserts);
 DECLARE_FLAG(int, optimization_counter_threshold);
 DECLARE_FLAG(bool, use_osr);
 DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
@@ -249,13 +248,13 @@
   ASSERT(locs->always_calls());
   Label done;
 
-  if (Isolate::Current()->TypeChecksEnabled()) {
+  if (Isolate::Current()->flags().type_checks()) {
     __ CompareObject(reg, Bool::True());
     __ j(EQUAL, &done, Assembler::kNearJump);
     __ CompareObject(reg, Bool::False());
     __ j(EQUAL, &done, Assembler::kNearJump);
   } else {
-    ASSERT(FLAG_enable_asserts);
+    ASSERT(Isolate::Current()->flags().asserts());
     __ CompareObject(reg, Object::null_instance());
     __ j(NOT_EQUAL, &done, Assembler::kNearJump);
   }
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index 4e279c5..b26ab16 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -24,7 +24,6 @@
 namespace dart {
 
 DECLARE_FLAG(bool, emit_edge_counters);
-DECLARE_FLAG(bool, enable_asserts);
 DECLARE_FLAG(int, optimization_counter_threshold);
 DECLARE_FLAG(bool, use_osr);
 
@@ -427,11 +426,11 @@
   ASSERT(locs->always_calls());
   Label done;
 
-  if (Isolate::Current()->TypeChecksEnabled()) {
+  if (Isolate::Current()->flags().type_checks()) {
     __ BranchEqual(reg, Bool::True(), &done);
     __ BranchEqual(reg, Bool::False(), &done);
   } else {
-    ASSERT(FLAG_enable_asserts);
+    ASSERT(Isolate::Current()->flags().asserts());
     __ BranchNotEqual(reg, Object::null_instance(), &done);
   }
 
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index 830df84..9474ebd 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -23,7 +23,6 @@
 namespace dart {
 
 DECLARE_FLAG(bool, emit_edge_counters);
-DECLARE_FLAG(bool, enable_asserts);
 DECLARE_FLAG(int, optimization_counter_threshold);
 DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
 DECLARE_FLAG(bool, use_osr);
@@ -330,13 +329,13 @@
   ASSERT(locs->always_calls());
   Label done;
 
-  if (Isolate::Current()->TypeChecksEnabled()) {
+  if (Isolate::Current()->flags().type_checks()) {
     __ CompareObject(reg, Bool::True(), PP);
     __ j(EQUAL, &done, Assembler::kNearJump);
     __ CompareObject(reg, Bool::False(), PP);
     __ j(EQUAL, &done, Assembler::kNearJump);
   } else {
-    ASSERT(FLAG_enable_asserts);
+    ASSERT(Isolate::Current()->flags().asserts());
     __ CompareObject(reg, Object::null_instance(), PP);
     __ j(NOT_EQUAL, &done, Assembler::kNearJump);
   }
diff --git a/runtime/vm/intrinsifier.cc b/runtime/vm/intrinsifier.cc
index 71cf333..9bfb434 100644
--- a/runtime/vm/intrinsifier.cc
+++ b/runtime/vm/intrinsifier.cc
@@ -594,7 +594,7 @@
 
 
 bool Intrinsifier::Build_GrowableArraySetIndexed(FlowGraph* flow_graph) {
-  if (Isolate::Current()->TypeChecksEnabled()) {
+  if (Isolate::Current()->flags().type_checks()) {
     return false;
   }
 
diff --git a/runtime/vm/intrinsifier_arm.cc b/runtime/vm/intrinsifier_arm.cc
index f13f452..4ba8fed 100644
--- a/runtime/vm/intrinsifier_arm.cc
+++ b/runtime/vm/intrinsifier_arm.cc
@@ -50,7 +50,7 @@
 void Intrinsifier::ObjectArraySetIndexed(Assembler* assembler) {
   Label fall_through;
 
-  if (Isolate::Current()->TypeChecksEnabled()) {
+  if (Isolate::Current()->flags().type_checks()) {
     const intptr_t type_args_field_offset =
         ComputeObjectArrayTypeArgumentsOffset();
     // Inline simple tests (Smi, null), fallthrough if not positive.
@@ -153,7 +153,7 @@
 // On stack: growable array (+1), value (+0).
 void Intrinsifier::GrowableArray_add(Assembler* assembler) {
   // In checked mode we need to type-check the incoming argument.
-  if (Isolate::Current()->TypeChecksEnabled()) {
+  if (Isolate::Current()->flags().type_checks()) {
     return;
   }
   Label fall_through;
diff --git a/runtime/vm/intrinsifier_arm64.cc b/runtime/vm/intrinsifier_arm64.cc
index 9e44953..fedbe17 100644
--- a/runtime/vm/intrinsifier_arm64.cc
+++ b/runtime/vm/intrinsifier_arm64.cc
@@ -48,7 +48,7 @@
 void Intrinsifier::ObjectArraySetIndexed(Assembler* assembler) {
   Label fall_through;
 
-  if (Isolate::Current()->TypeChecksEnabled()) {
+  if (Isolate::Current()->flags().type_checks()) {
     const intptr_t type_args_field_offset =
         ComputeObjectArrayTypeArgumentsOffset();
     // Inline simple tests (Smi, null), fallthrough if not positive.
@@ -149,7 +149,7 @@
 // On stack: growable array (+1), value (+0).
 void Intrinsifier::GrowableArray_add(Assembler* assembler) {
   // In checked mode we need to type-check the incoming argument.
-  if (Isolate::Current()->TypeChecksEnabled()) {
+  if (Isolate::Current()->flags().type_checks()) {
     return;
   }
   Label fall_through;
diff --git a/runtime/vm/intrinsifier_ia32.cc b/runtime/vm/intrinsifier_ia32.cc
index b8783d0..93290ed 100644
--- a/runtime/vm/intrinsifier_ia32.cc
+++ b/runtime/vm/intrinsifier_ia32.cc
@@ -54,7 +54,7 @@
 // update. Array length is always a Smi.
 void Intrinsifier::ObjectArraySetIndexed(Assembler* assembler) {
   Label fall_through;
-  if (Isolate::Current()->TypeChecksEnabled()) {
+  if (Isolate::Current()->flags().type_checks()) {
     const intptr_t type_args_field_offset =
         ComputeObjectArrayTypeArgumentsOffset();
     // Inline simple tests (Smi, null), fallthrough if not positive.
@@ -155,7 +155,7 @@
 // On stack: growable array (+2), value (+1), return-address (+0).
 void Intrinsifier::GrowableArray_add(Assembler* assembler) {
   // In checked mode we need to type-check the incoming argument.
-  if (Isolate::Current()->TypeChecksEnabled()) return;
+  if (Isolate::Current()->flags().type_checks()) return;
 
   Label fall_through;
   __ movl(EAX, Address(ESP, + 2 * kWordSize));  // Array.
diff --git a/runtime/vm/intrinsifier_mips.cc b/runtime/vm/intrinsifier_mips.cc
index 2163bbe..ecf07e6 100644
--- a/runtime/vm/intrinsifier_mips.cc
+++ b/runtime/vm/intrinsifier_mips.cc
@@ -48,7 +48,7 @@
 void Intrinsifier::ObjectArraySetIndexed(Assembler* assembler) {
   Label fall_through;
 
-  if (Isolate::Current()->TypeChecksEnabled()) {
+  if (Isolate::Current()->flags().type_checks()) {
     const intptr_t type_args_field_offset =
         ComputeObjectArrayTypeArgumentsOffset();
     // Inline simple tests (Smi, null), fallthrough if not positive.
@@ -145,7 +145,7 @@
 // On stack: growable array (+1), value (+0).
 void Intrinsifier::GrowableArray_add(Assembler* assembler) {
   // In checked mode we need to type-check the incoming argument.
-  if (Isolate::Current()->TypeChecksEnabled()) return;
+  if (Isolate::Current()->flags().type_checks()) return;
   Label fall_through;
   __ lw(T0, Address(SP, 1 * kWordSize));  // Array.
   __ lw(T1, FieldAddress(T0, GrowableObjectArray::length_offset()));
diff --git a/runtime/vm/intrinsifier_x64.cc b/runtime/vm/intrinsifier_x64.cc
index 2f0655d..14eb3cf 100644
--- a/runtime/vm/intrinsifier_x64.cc
+++ b/runtime/vm/intrinsifier_x64.cc
@@ -32,7 +32,7 @@
 
 
 void Intrinsifier::ObjectArraySetIndexed(Assembler* assembler) {
-  if (Isolate::Current()->TypeChecksEnabled()) {
+  if (Isolate::Current()->flags().type_checks()) {
     return;
   }
   __ movq(RDX, Address(RSP, + 1 * kWordSize));  // Value.
@@ -101,7 +101,7 @@
 // On stack: growable array (+2), value (+1), return-address (+0).
 void Intrinsifier::GrowableArray_add(Assembler* assembler) {
   // In checked mode we need to check the incoming argument.
-  if (Isolate::Current()->TypeChecksEnabled()) return;
+  if (Isolate::Current()->flags().type_checks()) return;
   Label fall_through;
   __ movq(RAX, Address(RSP, + 2 * kWordSize));  // Array.
   __ movq(RCX, FieldAddress(RAX, GrowableObjectArray::length_offset()));
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index ec9fbd3..2432df9 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -54,6 +54,32 @@
             "Log isolates whose name include the filter. "
             "Default: service isolate log messages are suppressed.");
 
+// TODO(iposva): Make these isolate specific flags inaccessible using the
+// regular FLAG_xyz pattern.
+// These flags are per-isolate and only influence the defaults.
+DEFINE_FLAG(bool, enable_asserts, false, "Enable assert statements.");
+DEFINE_FLAG(bool, enable_type_checks, false, "Enable type checks.");
+DEFINE_FLAG(bool, error_on_bad_override, false,
+            "Report error for bad overrides.");
+DEFINE_FLAG(bool, error_on_bad_type, false,
+            "Report error for malformed types.");
+
+static void CheckedModeHandler(bool value) {
+  FLAG_enable_asserts = value;
+  FLAG_enable_type_checks = value;
+}
+
+// --enable-checked-mode and --checked both enable checked mode which is
+// equivalent to setting --enable-asserts and --enable-type-checks.
+DEFINE_FLAG_HANDLER(CheckedModeHandler,
+                    enable_checked_mode,
+                    "Enable checked mode.");
+
+DEFINE_FLAG_HANDLER(CheckedModeHandler,
+                    checked,
+                    "Enable checked mode.");
+
+
 // Quick access to the locally defined isolate() method.
 #define I (isolate())
 
@@ -450,20 +476,24 @@
 
 
 void IsolateMessageHandler::NotifyPauseOnStart() {
-  StartIsolateScope start_isolate(isolate());
-  StackZone zone(I);
-  HandleScope handle_scope(I);
-  ServiceEvent pause_event(isolate(), ServiceEvent::kPauseStart);
-  Service::HandleEvent(&pause_event);
+  if (Service::NeedsDebugEvents()) {
+    StartIsolateScope start_isolate(isolate());
+    StackZone zone(I);
+    HandleScope handle_scope(I);
+    ServiceEvent pause_event(isolate(), ServiceEvent::kPauseStart);
+    Service::HandleEvent(&pause_event);
+  }
 }
 
 
 void IsolateMessageHandler::NotifyPauseOnExit() {
-  StartIsolateScope start_isolate(isolate());
-  StackZone zone(I);
-  HandleScope handle_scope(I);
-  ServiceEvent pause_event(isolate(), ServiceEvent::kPauseExit);
-  Service::HandleEvent(&pause_event);
+  if (Service::NeedsDebugEvents()) {
+    StartIsolateScope start_isolate(isolate());
+    StackZone zone(I);
+    HandleScope handle_scope(I);
+    ServiceEvent pause_event(isolate(), ServiceEvent::kPauseExit);
+    Service::HandleEvent(&pause_event);
+  }
 }
 
 
@@ -532,6 +562,35 @@
 }
 
 
+Isolate::Flags::Flags()
+  : type_checks_(FLAG_enable_type_checks),
+    asserts_(FLAG_enable_asserts),
+    error_on_bad_type_(FLAG_error_on_bad_type),
+    error_on_bad_override_(FLAG_error_on_bad_override) {}
+
+
+void Isolate::Flags::CopyFrom(const Flags& orig) {
+  type_checks_ = orig.type_checks();
+  asserts_ = orig.asserts();
+  error_on_bad_type_ = orig.error_on_bad_type();
+  error_on_bad_override_ = orig.error_on_bad_override();
+}
+
+
+void Isolate::Flags::CopyFrom(const Dart_IsolateFlags& api_flags) {
+  type_checks_ = api_flags.enable_type_checks;
+  asserts_ = api_flags.enable_asserts;
+  // Leave others at defaults.
+}
+
+
+void Isolate::Flags::CopyTo(Dart_IsolateFlags* api_flags) const {
+  api_flags->version = DART_FLAGS_CURRENT_VERSION;
+  api_flags->enable_type_checks = type_checks();
+  api_flags->enable_asserts = asserts();
+}
+
+
 #if defined(DEBUG)
 // static
 void BaseIsolate::AssertCurrent(BaseIsolate* isolate) {
@@ -549,7 +608,7 @@
 #define REUSABLE_HANDLE_INITIALIZERS(object)                                   \
   object##_handle_(NULL),
 
-Isolate::Isolate()
+Isolate::Isolate(const Dart_IsolateFlags& api_flags)
   :   mutator_thread_(NULL),
       vm_tag_(0),
       store_buffer_(),
@@ -574,7 +633,7 @@
       single_step_(false),
       resume_request_(false),
       has_compiled_(false),
-      strict_compilation_(false),
+      flags_(),
       random_(),
       simulator_(NULL),
       long_jump_base_(NULL),
@@ -616,6 +675,7 @@
       REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS)
       REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_INIT)
       reusable_handles_() {
+  flags_.CopyFrom(api_flags);
   set_vm_tag(VMTag::kEmbedderTagId);
   set_user_tag(UserTags::kDefaultUserTag);
 }
@@ -667,8 +727,10 @@
 }
 
 
-Isolate* Isolate::Init(const char* name_prefix, bool is_vm_isolate) {
-  Isolate* result = new Isolate();
+Isolate* Isolate::Init(const char* name_prefix,
+                       const Dart_IsolateFlags& api_flags,
+                       bool is_vm_isolate) {
+  Isolate* result = new Isolate(api_flags);
   ASSERT(result != NULL);
 
   // Initialize metrics.
@@ -1811,6 +1873,7 @@
       serialized_args_len_(0),
       serialized_message_(NULL),
       serialized_message_len_(0),
+      isolate_flags_(),
       paused_(paused) {
   script_url_ = NULL;
   const Class& cls = Class::Handle(func.Owner());
@@ -1829,6 +1892,8 @@
                   &serialized_message_,
                   &serialized_message_len_,
                   can_send_any_object);
+  // Inherit flags from spawning isolate.
+  isolate_flags()->CopyFrom(Isolate::Current()->flags());
 }
 
 
@@ -1848,6 +1913,7 @@
       serialized_args_len_(0),
       serialized_message_(NULL),
       serialized_message_len_(0),
+      isolate_flags_(),
       paused_(paused) {
   script_url_ = strdup(script_url);
   if (package_root != NULL) {
@@ -1864,6 +1930,9 @@
                   &serialized_message_,
                   &serialized_message_len_,
                   can_send_any_object);
+  // By default inherit flags from spawning isolate. These can be overridden
+  // from the calling code.
+  isolate_flags()->CopyFrom(Isolate::Current()->flags());
 }
 
 
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 57b23e9..a3758a2 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -23,11 +23,6 @@
 
 namespace dart {
 
-DECLARE_FLAG(bool, enable_type_checks);
-DECLARE_FLAG(bool, enable_asserts);
-DECLARE_FLAG(bool, error_on_bad_type);
-DECLARE_FLAG(bool, error_on_bad_override);
-
 // Forward declarations.
 class AbstractType;
 class ApiState;
@@ -126,7 +121,9 @@
   }
 
   static void InitOnce();
-  static Isolate* Init(const char* name_prefix, bool is_vm_isolate = false);
+  static Isolate* Init(const char* name_prefix,
+                       const Dart_IsolateFlags& api_flags,
+                       bool is_vm_isolate = false);
   void Shutdown();
 
   // Register a newly introduced class.
@@ -383,19 +380,51 @@
   void set_has_compiled(bool value) { has_compiled_ = value; }
   bool has_compiled() const { return has_compiled_; }
 
-  void set_strict_compilation(bool value) { strict_compilation_ = value; }
-  bool strict_compilation() const { return strict_compilation_; }
-  bool TypeChecksEnabled() {
-    return FLAG_enable_type_checks || strict_compilation_;
-  }
-  bool AssertsEnabled() {
-    return FLAG_enable_asserts || strict_compilation_;
-  }
-  bool ErrorOnBadTypeEnabled() {
-    return FLAG_error_on_bad_type || strict_compilation_;
-  }
-  bool ErrorOnBadOverrideEnabled() {
-    return FLAG_error_on_bad_override || strict_compilation_;
+  // TODO(iposva): Evaluate whether two different isolate flag structures are
+  // needed. Currently it serves as a separation between publicly visible flags
+  // and VM internal flags.
+  class Flags : public ValueObject {
+   public:
+    // Construct default flags as specified by the options.
+    Flags();
+
+    bool type_checks() const { return type_checks_; }
+    bool asserts() const { return asserts_; }
+    bool error_on_bad_type() const { return error_on_bad_type_; }
+    bool error_on_bad_override() const { return error_on_bad_override_; }
+
+    void set_checked(bool val) {
+      type_checks_ = val;
+      asserts_ = val;
+    }
+
+    void CopyFrom(const Flags& orig);
+    void CopyFrom(const Dart_IsolateFlags& api_flags);
+    void CopyTo(Dart_IsolateFlags* api_flags) const;
+
+   private:
+    bool type_checks_;
+    bool asserts_;
+    bool error_on_bad_type_;
+    bool error_on_bad_override_;
+
+    friend class Isolate;
+
+    DISALLOW_ALLOCATION();
+    DISALLOW_COPY_AND_ASSIGN(Flags);
+  };
+
+  const Flags& flags() const { return flags_; }
+
+  // Set the checks in the compiler to the highest level. Statically and when
+  // executing generated code. Needs to be called before any code has been
+  // compiled.
+  void set_strict_compilation() {
+    ASSERT(!has_compiled());
+    flags_.type_checks_ = true;
+    flags_.asserts_ = true;
+    flags_.error_on_bad_type_ = true;
+    flags_.error_on_bad_override_ = true;
   }
 
   // Requests that the debugger resume execution.
@@ -677,7 +706,7 @@
   void PauseEventHandler();
 
  private:
-  Isolate();
+  explicit Isolate(const Dart_IsolateFlags& api_flags);
 
   void BuildName(const char* name_prefix);
   void PrintInvokedFunctions();
@@ -720,7 +749,7 @@
   bool single_step_;
   bool resume_request_;
   bool has_compiled_;
-  bool strict_compilation_;
+  Flags flags_;
   Random random_;
   Simulator* simulator_;
   LongJumpScope* long_jump_base_;
@@ -946,6 +975,7 @@
   char* function_name() const { return function_name_; }
   bool is_spawn_uri() const { return library_url_ == NULL; }
   bool paused() const { return paused_; }
+  Isolate::Flags* isolate_flags() { return &isolate_flags_; }
 
   RawObject* ResolveFunction();
   RawInstance* BuildArgs(Zone* zone);
@@ -964,6 +994,7 @@
   intptr_t serialized_args_len_;
   uint8_t* serialized_message_;
   intptr_t serialized_message_len_;
+  Isolate::Flags isolate_flags_;
   bool paused_;
 };
 
diff --git a/runtime/vm/isolate_test.cc b/runtime/vm/isolate_test.cc
index 2bb21c7..99c8354 100644
--- a/runtime/vm/isolate_test.cc
+++ b/runtime/vm/isolate_test.cc
@@ -10,7 +10,10 @@
 namespace dart {
 
 UNIT_TEST_CASE(IsolateCurrent) {
-  Isolate* isolate = Isolate::Init(NULL);
+  Isolate::Flags vm_flags;
+  Dart_IsolateFlags api_flags;
+  vm_flags.CopyTo(&api_flags);
+  Isolate* isolate = Isolate::Init(NULL, api_flags);
   EXPECT_EQ(isolate, Isolate::Current());
   isolate->Shutdown();
   EXPECT_EQ(reinterpret_cast<Isolate*>(NULL), Isolate::Current());
diff --git a/runtime/vm/json_stream.cc b/runtime/vm/json_stream.cc
index 2470d19..71d30a9 100644
--- a/runtime/vm/json_stream.cc
+++ b/runtime/vm/json_stream.cc
@@ -577,6 +577,20 @@
 }
 
 
+void JSONObject::AddLocation(const Script& script,
+                             intptr_t token_pos,
+                             intptr_t end_token_pos) {
+  JSONObject location(this, "location");
+  location.AddProperty("type", "SourceLocation");
+  location.AddProperty("script", script);
+  location.AddProperty("tokenPos", token_pos);
+  if (end_token_pos >= 0) {
+    location.AddProperty("endTokenPos", end_token_pos);
+  }
+}
+
+
+
 void JSONObject::AddPropertyF(const char* name,
                               const char* format, ...) const {
   stream_->PrintPropertyName(name);
diff --git a/runtime/vm/json_stream.h b/runtime/vm/json_stream.h
index 39bb0ac..4a06178 100644
--- a/runtime/vm/json_stream.h
+++ b/runtime/vm/json_stream.h
@@ -21,13 +21,18 @@
 class MessageQueue;
 class Metric;
 class Object;
+class Script;
 class ServiceEvent;
 class Breakpoint;
 class String;
 class Zone;
 
 
-// Keep this in sync with runtime/observatory/lib/src/service/object.dart.
+// Keep this enum in sync with:
+//
+//  - runtime/vm/service/vmservice.dart
+//  - runtime/observatory/lib/src/service/object.dart
+//
 enum JSONRpcErrorCode {
   kParseError     = -32700,
   kInvalidRequest = -32600,
@@ -35,9 +40,11 @@
   kInvalidParams  = -32602,
   kInternalError  = -32603,
 
-  kFeatureDisabled     = 100,
-  kVMMustBePaused      = 101,
-  kCannotAddBreakpoint = 102,
+  kFeatureDisabled         = 100,
+  kVMMustBePaused          = 101,
+  kCannotAddBreakpoint     = 102,
+  kStreamAlreadySubscribed = 103,
+  kStreamNotSubscribed     = 104,
 };
 
 
@@ -186,6 +193,10 @@
 
   void AddFixedServiceId(const char* format, ...) const PRINTF_ATTRIBUTE(2, 3);
 
+  void AddLocation(const Script& script,
+                   intptr_t token_pos,
+                   intptr_t end_token_pos = -1);
+
   void AddProperty(const char* name, bool b) const {
     stream_->PrintPropertyBool(name, b);
   }
diff --git a/runtime/vm/message.cc b/runtime/vm/message.cc
index 906a16c..810a348 100644
--- a/runtime/vm/message.cc
+++ b/runtime/vm/message.cc
@@ -191,6 +191,7 @@
   while (it.HasNext()) {
     Message* current = it.Next();
     JSONObject message(&messages);
+    message.AddProperty("type", "Message");
     message.AddPropertyF("name", "Isolate Message (%" Px ")", current->Id());
     message.AddPropertyF("messageObjectId", "messages/%" Px "",
                          current->Id());
@@ -207,15 +208,16 @@
       // Grab function from closure.
       msg_handler = Closure::function(Instance::Cast(msg_handler));
     }
-    if (!msg_handler.IsFunction()) {
-      // No handler function.
-      continue;
+    if (msg_handler.IsFunction()) {
+      const Function& function = Function::Cast(msg_handler);
+      message.AddProperty("handler", function);
+
+      const Script& script = Script::Handle(function.script());
+      if (!script.IsNull()) {
+        message.AddLocation(script, function.token_pos(),
+                            function.end_token_pos());
+      }
     }
-    const Function& function = Function::Cast(msg_handler);
-    const Script& script = Script::Handle(function.script());
-    message.AddProperty("handlerFunction", function);
-    message.AddProperty("handlerScript", script);
-    message.AddProperty("handlerTokenPos", function.token_pos());
   }
 }
 
diff --git a/runtime/vm/metrics_test.cc b/runtime/vm/metrics_test.cc
index 6750a41..364c946 100644
--- a/runtime/vm/metrics_test.cc
+++ b/runtime/vm/metrics_test.cc
@@ -14,7 +14,10 @@
 namespace dart {
 
 UNIT_TEST_CASE(Metric_Simple) {
-  Isolate* isolate = Isolate::Init(NULL);
+  Isolate::Flags vm_flags;
+  Dart_IsolateFlags api_flags;
+  vm_flags.CopyTo(&api_flags);
+  Isolate* isolate = Isolate::Init(NULL, api_flags);
   EXPECT_EQ(isolate, Isolate::Current());
   Metric metric;
 
@@ -40,7 +43,10 @@
 };
 
 UNIT_TEST_CASE(Metric_OnDemand) {
-  Isolate* isolate = Isolate::Init(NULL);
+  Isolate::Flags vm_flags;
+  Dart_IsolateFlags api_flags;
+  vm_flags.CopyTo(&api_flags);
+  Isolate* isolate = Isolate::Init(NULL, api_flags);
   EXPECT_EQ(isolate, Isolate::Current());
   MyMetric metric;
 
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 2896d72..d95d307 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -65,7 +65,6 @@
 DEFINE_FLAG(bool, use_lib_cache, true, "Use library name cache");
 DEFINE_FLAG(bool, trace_field_guards, false, "Trace changes in field's cids.");
 
-DECLARE_FLAG(bool, error_on_bad_override);
 DECLARE_FLAG(bool, trace_compiler);
 DECLARE_FLAG(bool, trace_deoptimization);
 DECLARE_FLAG(bool, trace_deoptimization_verbose);
@@ -1586,34 +1585,41 @@
 }
 
 
-static void AddTypeProperties(JSONObject* jsobj,
-                              const char* user_type,
-                              const char* vm_type,
-                              bool ref) {
-  bool same_type = (strcmp(user_type, vm_type) == 0);
+void Object::AddCommonObjectProperties(JSONObject* jsobj,
+                                       const char* protocol_type,
+                                       bool ref) const {
+  const char* vm_type = JSONType();
+  bool same_type = (strcmp(protocol_type, vm_type) == 0);
   if (ref) {
-    jsobj->AddPropertyF("type", "@%s", user_type);
+    jsobj->AddPropertyF("type", "@%s", protocol_type);
   } else {
-    jsobj->AddProperty("type", user_type);
+    jsobj->AddProperty("type", protocol_type);
   }
   if (!same_type) {
     jsobj->AddProperty("_vmType", vm_type);
   }
+  if (!ref || IsInstance()) {
+    // TODO(turnidge): Provide the type arguments here too?
+    const Class& cls = Class::Handle(this->clazz());
+    jsobj->AddProperty("class", cls);
+  }
+  if (!ref) {
+    if (raw()->IsHeapObject()) {
+      jsobj->AddProperty("size", raw()->Size());
+    } else {
+      jsobj->AddProperty("size", (intptr_t)0);
+    }
+  }
 }
 
 
 void Object::PrintJSON(JSONStream* stream, bool ref) const {
   if (IsNull()) {
     JSONObject jsobj(stream);
-    AddTypeProperties(&jsobj, "Instance", JSONType(), ref);
+    AddCommonObjectProperties(&jsobj, "Instance", ref);
     jsobj.AddProperty("kind", "Null");
     jsobj.AddFixedServiceId("objects/null");
     jsobj.AddProperty("valueAsString", "null");
-    if (!ref) {
-      const Class& cls = Class::Handle(this->clazz());
-      jsobj.AddProperty("class", cls);
-      jsobj.AddProperty("size", raw()->Size());
-    }
   } else {
     PrintJSONImpl(stream, ref);
   }
@@ -1622,14 +1628,11 @@
 
 void Object::PrintJSONImpl(JSONStream* stream, bool ref) const {
   JSONObject jsobj(stream);
-  AddTypeProperties(&jsobj, "Object", JSONType(), ref);
+  AddCommonObjectProperties(&jsobj, "Object", ref);
   jsobj.AddServiceId(*this);
   if (ref) {
     return;
   }
-  Class& cls = Class::Handle(this->clazz());
-  jsobj.AddProperty("class", cls);
-  jsobj.AddProperty("size", raw()->Size());
 }
 
 
@@ -4111,12 +4114,11 @@
 void Class::PrintJSONImpl(JSONStream* stream, bool ref) const {
   JSONObject jsobj(stream);
   if ((raw() == Class::null()) || (id() == kFreeListElement)) {
-    // TODO(turnidge): This is weird.  See if there is another way to
-    // handle this.
+    // TODO(turnidge): This is weird and needs to be changed.
     jsobj.AddProperty("type", "null");
     return;
   }
-  AddTypeProperties(&jsobj, "Class", JSONType(), ref);
+  AddCommonObjectProperties(&jsobj, "Class", ref);
   jsobj.AddFixedServiceId("classes/%" Pd "", id());
   const String& user_name = String::Handle(PrettyName());
   const String& vm_name = String::Handle(Name());
@@ -4141,9 +4143,7 @@
   jsobj.AddProperty("library", Object::Handle(library()));
   const Script& script = Script::Handle(this->script());
   if (!script.IsNull()) {
-    jsobj.AddProperty("script", script);
-    jsobj.AddProperty("tokenPos", token_pos());
-    jsobj.AddProperty("endTokenPos", ComputeEndTokenPos());
+    jsobj.AddLocation(script, token_pos(), ComputeEndTokenPos());
   }
   {
     JSONArray interfaces_array(&jsobj, "interfaces");
@@ -4446,7 +4446,7 @@
   ObjectStore* object_store = isolate->object_store();
   const Array& table = Array::Handle(object_store->canonical_type_arguments());
   ASSERT(table.Length() > 0);
-  AddTypeProperties(&jsobj, "TypeArguments", JSONType(), ref);
+  AddCommonObjectProperties(&jsobj, "TypeArguments", ref);
   jsobj.AddServiceId(*this);
   const String& user_name = String::Handle(PrettyName());
   const String& vm_name = String::Handle(Name());
@@ -5114,6 +5114,7 @@
 
 
 void Function::ClearCode() const {
+  ASSERT(ic_data_array() == Array::null());
   StorePointer(&raw_ptr()->unoptimized_code_, Code::null());
   StubCode* stub_code = Isolate::Current()->stub_code();
   StorePointer(&raw_ptr()->instructions_,
@@ -5140,8 +5141,9 @@
   if (!error.IsNull()) {
     Exceptions::PropagateError(error);
   }
-  AttachCode(Code::Handle(zone, unoptimized_code()));
-  CodePatcher::RestoreEntry(Code::Handle(zone, unoptimized_code()));
+  const Code& unopt_code = Code::Handle(zone, unoptimized_code());
+  AttachCode(unopt_code);
+  CodePatcher::RestoreEntry(unopt_code);
   isolate->TrackDeoptimizedCode(current_code);
 }
 
@@ -5905,7 +5907,7 @@
 
 bool Function::HasCompatibleParametersWith(const Function& other,
                                            Error* bound_error) const {
-  ASSERT(Isolate::Current()->ErrorOnBadOverrideEnabled());
+  ASSERT(Isolate::Current()->flags().error_on_bad_override());
   ASSERT((bound_error != NULL) && bound_error->IsNull());
   // Check that this function's signature type is a subtype of the other
   // function's signature type.
@@ -6197,13 +6199,13 @@
   const PatchClass& clone_owner =
       PatchClass::Handle(PatchClass::New(new_owner, origin));
   clone.set_owner(clone_owner);
+  clone.ClearICDataArray();
   clone.ClearCode();
   clone.set_usage_counter(0);
   clone.set_deoptimization_counter(0);
   clone.set_regexp_cid(kIllegalCid);
   clone.set_optimized_instruction_count(0);
   clone.set_optimized_call_site_count(0);
-  clone.set_ic_data_array(Array::Handle());
   if (new_owner.NumTypeParameters() > 0) {
     // Adjust uninstantiated types to refer to type parameters of the new owner.
     AbstractType& type = AbstractType::Handle(clone.result_type());
@@ -6754,7 +6756,7 @@
 }
 
 void Function::ClearICDataArray() const {
-  set_ic_data_array(Array::Handle());
+  set_ic_data_array(Array::null_array());
 }
 
 
@@ -6891,7 +6893,7 @@
   err ^= cls.EnsureIsFinalized(Isolate::Current());
   ASSERT(err.IsNull());
   JSONObject jsobj(stream);
-  AddTypeProperties(&jsobj, "Function", JSONType(), ref);
+  AddCommonObjectProperties(&jsobj, "Function", ref);
   AddFunctionServiceId(jsobj, *this, cls);
   const String& user_name = String::Handle(PrettyName());
   const String& vm_name = String::Handle(name());
@@ -6930,9 +6932,7 @@
 
   const Script& script = Script::Handle(this->script());
   if (!script.IsNull()) {
-    jsobj.AddProperty("script", script);
-    jsobj.AddProperty("tokenPos", token_pos());
-    jsobj.AddProperty("endTokenPos", end_token_pos());
+    jsobj.AddLocation(script, token_pos(), end_token_pos());
   }
 }
 
@@ -7241,7 +7241,7 @@
   intptr_t id = cls.FindFieldIndex(*this);
   ASSERT(id >= 0);
   intptr_t cid = cls.id();
-  AddTypeProperties(&jsobj, "Field", JSONType(), ref);
+  AddCommonObjectProperties(&jsobj, "Field", ref);
   jsobj.AddFixedServiceId("classes/%" Pd "/fields/%" Pd "", cid, id);
   const String& user_name = String::Handle(PrettyName());
   const String& vm_name = String::Handle(name());
@@ -7287,8 +7287,7 @@
   const Class& origin_cls = Class::Handle(origin());
   const Script& script = Script::Handle(origin_cls.script());
   if (!script.IsNull()) {
-    jsobj.AddProperty("script", script);
-    jsobj.AddProperty("tokenPos", token_pos());
+    jsobj.AddLocation(script, token_pos());
   }
 }
 
@@ -8026,16 +8025,13 @@
 
 void TokenStream::PrintJSONImpl(JSONStream* stream, bool ref) const {
   JSONObject jsobj(stream);
-  AddTypeProperties(&jsobj, "Object", JSONType(), ref);
+  AddCommonObjectProperties(&jsobj, "Object", ref);
   // TODO(johnmccutchan): Generate a stable id. TokenStreams hang off
   // a Script object but do not have a back reference to generate a stable id.
   jsobj.AddServiceId(*this);
   if (ref) {
     return;
   }
-  Class& cls = Class::Handle(this->clazz());
-  jsobj.AddProperty("class", cls);
-  jsobj.AddProperty("size", raw()->Size());
   const String& private_key = String::Handle(PrivateKey());
   jsobj.AddProperty("privateKey", private_key);
   // TODO(johnmccutchan): Add support for printing LiteralTokens and add
@@ -8560,7 +8556,7 @@
 // See also Dart_ScriptGetTokenInfo.
 void Script::PrintJSONImpl(JSONStream* stream, bool ref) const {
   JSONObject jsobj(stream);
-  AddTypeProperties(&jsobj, "Script", JSONType(), ref);
+  AddCommonObjectProperties(&jsobj, "Script", ref);
   const String& uri = String::Handle(url());
   ASSERT(!uri.IsNull());
   const String& encoded_uri = String::Handle(String::EncodeIRI(uri));
@@ -9911,7 +9907,7 @@
   intptr_t id = index();
   ASSERT(id >= 0);
   JSONObject jsobj(stream);
-  AddTypeProperties(&jsobj, "Library", JSONType(), ref);
+  AddCommonObjectProperties(&jsobj, "Library", ref);
   jsobj.AddFixedServiceId("libraries/%" Pd "", id);
   jsobj.AddProperty("name", library_name);
   const String& library_url = String::Handle(url());
@@ -10771,16 +10767,13 @@
 
 
 void PcDescriptors::PrintToJSONObject(JSONObject* jsobj, bool ref) const {
-  AddTypeProperties(jsobj, "Object", JSONType(), ref);
+  AddCommonObjectProperties(jsobj, "Object", ref);
   // TODO(johnmccutchan): Generate a stable id. PcDescriptors hang off a Code
   // object but do not have a back reference to generate an ID.
   jsobj->AddServiceId(*this);
   if (ref) {
     return;
   }
-  Class& cls = Class::Handle(this->clazz());
-  jsobj->AddProperty("class", cls);
-  jsobj->AddProperty("size", raw()->Size());
   JSONArray members(jsobj, "members");
   Iterator iter(*this, RawPcDescriptors::kAnyKind);
   while (iter.MoveNext()) {
@@ -10788,6 +10781,7 @@
     descriptor.AddPropertyF("pcOffset", "%" Px "", iter.PcOffset());
     descriptor.AddProperty("kind", KindAsStr(iter.Kind()));
     descriptor.AddProperty("deoptId", iter.DeoptId());
+    // TODO(turnidge): Use AddLocation instead.
     descriptor.AddProperty("tokenPos", iter.TokenPos());
     descriptor.AddProperty("tryIndex", iter.TryIndex());
   }
@@ -11052,16 +11046,13 @@
 void LocalVarDescriptors::PrintJSONImpl(JSONStream* stream,
                                         bool ref) const {
   JSONObject jsobj(stream);
-  AddTypeProperties(&jsobj, "Object", JSONType(), ref);
+  AddCommonObjectProperties(&jsobj, "Object", ref);
   // TODO(johnmccutchan): Generate a stable id. LocalVarDescriptors hang off
   // a Code object but do not have a back reference to generate an ID.
   jsobj.AddServiceId(*this);
   if (ref) {
     return;
   }
-  Class& cls = Class::Handle(this->clazz());
-  jsobj.AddProperty("class", cls);
-  jsobj.AddProperty("size", raw()->Size());
   JSONArray members(&jsobj, "members");
   String& var_name = String::Handle();
   for (intptr_t i = 0; i < Length(); i++) {
@@ -12001,6 +11992,7 @@
 
   JSONObject jsobj(&jsarray);
   jsobj.AddProperty("name", String::Handle(target_name()).ToCString());
+  // TODO(turnidge): Use AddLocation instead.
   jsobj.AddProperty("tokenPos", token_pos);
   // TODO(rmacnak): Figure out how to stringify DeoptReasons().
   // jsobj.AddProperty("deoptReasons", ...);
@@ -12731,7 +12723,7 @@
 
 void Code::PrintJSONImpl(JSONStream* stream, bool ref) const {
   JSONObject jsobj(stream);
-  AddTypeProperties(&jsobj, "Code", JSONType(), ref);
+  AddCommonObjectProperties(&jsobj, "Code", ref);
   jsobj.AddFixedServiceId("code/%" Px64"-%" Px "",
                           compile_timestamp(),
                           EntryPoint());
@@ -13030,7 +13022,7 @@
   JSONObject jsobj(stream);
   // TODO(turnidge): Should the user level type for Context be Context
   // or Object?
-  AddTypeProperties(&jsobj, "Context", JSONType(), ref);
+  AddCommonObjectProperties(&jsobj, "Context", ref);
   jsobj.AddServiceId(*this);
 
   jsobj.AddProperty("length", num_variables());
@@ -13039,19 +13031,16 @@
     return;
   }
 
-  Class& cls = Class::Handle(this->clazz());
-  jsobj.AddProperty("class", cls);
-
-  jsobj.AddProperty("size", raw()->Size());
-
   const Context& parent_context = Context::Handle(parent());
-  jsobj.AddProperty("parent", parent_context);
+  if (!parent_context.IsNull()) {
+    jsobj.AddProperty("parent", parent_context);
+  }
 
   JSONArray jsarr(&jsobj, "variables");
-  for (intptr_t i = 0; i < num_variables(); i++) {
-    const Object& var = Object::Handle(At(i));
+  Object& var = Object::Handle();
+  for (intptr_t index = 0; index < num_variables(); index++) {
+    var = At(index);
     JSONObject jselement(&jsarr);
-    jselement.AddProperty("index", i);
     jselement.AddProperty("value", var);
   }
 }
@@ -13449,7 +13438,9 @@
 
 void ApiError::PrintJSONImpl(JSONStream* stream, bool ref) const {
   JSONObject jsobj(stream);
-  AddTypeProperties(&jsobj, "Error", JSONType(), ref);
+  AddCommonObjectProperties(&jsobj, "Error", ref);
+  jsobj.AddProperty("kind", "InternalError");
+  jsobj.AddServiceId(*this);
   jsobj.AddProperty("message", ToErrorCString());
 }
 
@@ -13586,7 +13577,9 @@
 
 void LanguageError::PrintJSONImpl(JSONStream* stream, bool ref) const {
   JSONObject jsobj(stream);
-  AddTypeProperties(&jsobj, "Error", JSONType(), ref);
+  AddCommonObjectProperties(&jsobj, "Error", ref);
+  jsobj.AddProperty("kind", "LanguageError");
+  jsobj.AddServiceId(*this);
   jsobj.AddProperty("message", ToErrorCString());
 }
 
@@ -13677,9 +13670,13 @@
 void UnhandledException::PrintJSONImpl(JSONStream* stream,
                                        bool ref) const {
   JSONObject jsobj(stream);
-  AddTypeProperties(&jsobj, "Error", JSONType(), ref);
+  AddCommonObjectProperties(&jsobj, "Error", ref);
+  jsobj.AddProperty("kind", "UnhandledException");
+  jsobj.AddServiceId(*this);
   jsobj.AddProperty("message", ToErrorCString());
-
+  if (ref) {
+    return;
+  }
   Instance& instance = Instance::Handle();
   instance = exception();
   jsobj.AddProperty("exception", instance);
@@ -13721,7 +13718,9 @@
 
 void UnwindError::PrintJSONImpl(JSONStream* stream, bool ref) const {
   JSONObject jsobj(stream);
-  AddTypeProperties(&jsobj, "Error", JSONType(), ref);
+  AddCommonObjectProperties(&jsobj, "Error", ref);
+  jsobj.AddProperty("kind", "TerminationError");
+  jsobj.AddServiceId(*this);
   jsobj.AddProperty("message", ToErrorCString());
 }
 
@@ -13862,6 +13861,7 @@
       break;
     }
     if (this->CanonicalizeEquals(result)) {
+      ASSERT(result.IsCanonical());
       return result.raw();
     }
     index++;
@@ -13953,7 +13953,7 @@
     const AbstractType& instantiated_other = AbstractType::Handle(
         isolate, other.InstantiateFrom(other_instantiator, bound_error));
     if ((bound_error != NULL) && !bound_error->IsNull()) {
-      ASSERT(Isolate::Current()->TypeChecksEnabled());
+      ASSERT(Isolate::Current()->flags().type_checks());
       return false;
     }
     other_class = instantiated_other.type_class();
@@ -14164,21 +14164,13 @@
 
 void Instance::PrintSharedInstanceJSON(JSONObject* jsobj,
                                        bool ref) const {
-  AddTypeProperties(jsobj, "Instance", JSONType(), ref);
-  Class& cls = Class::Handle(this->clazz());
-  jsobj->AddProperty("class", cls);
-  // TODO(turnidge): Provide the type arguments here too.
+  AddCommonObjectProperties(jsobj, "Instance", ref);
   if (ref) {
     return;
   }
 
-  if (raw()->IsHeapObject()) {
-    jsobj->AddProperty("size", raw()->Size());
-  } else {
-    jsobj->AddProperty("size", (intptr_t)0);
-  }
-
   // Walk the superclass chain, adding all instance fields.
+  Class& cls = Class::Handle(this->clazz());
   {
     Instance& fieldValue = Instance::Handle();
     JSONArray jsarr(jsobj, "fields");
@@ -14628,14 +14620,14 @@
   // type and/or malbounded parameter types, which will then be encountered here
   // at run time.
   if (IsMalbounded()) {
-    ASSERT(Isolate::Current()->TypeChecksEnabled());
+    ASSERT(Isolate::Current()->flags().type_checks());
     if ((bound_error != NULL) && bound_error->IsNull()) {
       *bound_error = error();
     }
     return false;
   }
   if (other.IsMalbounded()) {
-    ASSERT(Isolate::Current()->TypeChecksEnabled());
+    ASSERT(Isolate::Current()->flags().type_checks());
     if ((bound_error != NULL) && bound_error->IsNull()) {
       *bound_error = other.error();
     }
@@ -14842,7 +14834,7 @@
 
 
 bool Type::IsMalbounded() const {
-  if (!Isolate::Current()->TypeChecksEnabled()) {
+  if (!Isolate::Current()->flags().type_checks()) {
     return false;
   }
   if (raw_ptr()->error_ == LanguageError::null()) {
@@ -14862,7 +14854,7 @@
     return true;
   }
   ASSERT(type_error.kind() == Report::kMalboundedType);
-  return Isolate::Current()->TypeChecksEnabled();
+  return Isolate::Current()->flags().type_checks();
 }
 
 
@@ -15532,7 +15524,7 @@
   if (ref) {
     return;
   }
-  jsobj.AddProperty("type", AbstractType::Handle(type()));
+  jsobj.AddProperty("targetType", AbstractType::Handle(type()));
 }
 
 
@@ -15866,7 +15858,7 @@
                                                 bound_error,
                                                 trail);
   }
-  if ((Isolate::Current()->TypeChecksEnabled()) &&
+  if ((Isolate::Current()->flags().type_checks()) &&
       (bound_error != NULL) && bound_error->IsNull()) {
     AbstractType& upper_bound = AbstractType::Handle(bound());
     ASSERT(!upper_bound.IsObjectType() && !upper_bound.IsDynamicType());
@@ -15982,7 +15974,7 @@
   if (ref) {
     return;
   }
-  jsobj.AddProperty("type", AbstractType::Handle(type()));
+  jsobj.AddProperty("targetType", AbstractType::Handle(type()));
   jsobj.AddProperty("bound", AbstractType::Handle(bound()));
 }
 
@@ -16556,6 +16548,7 @@
       break;
     }
     if (canonical_value.value() == value) {
+      ASSERT(canonical_value.IsCanonical());
       return canonical_value.raw();
     }
     index++;
@@ -19357,12 +19350,10 @@
   if (IsNull()) {
     return IsImmutable() ? "_ImmutableList NULL" : "_List NULL";
   }
-  const char* format = IsImmutable() ?
-      "_ImmutableList len:%" Pd : "_List len:%" Pd;
-  intptr_t len = OS::SNPrint(NULL, 0, format, Length()) + 1;
-  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
-  OS::SNPrint(chars, len, format, Length());
-  return chars;
+  Zone* zone = Isolate::Current()->current_zone();
+  const char* format = IsImmutable() ? "_ImmutableList len:%" Pd
+                                     : "_List len:%" Pd;
+  return zone->PrintToString(format, Length());
 }
 
 
@@ -19377,12 +19368,10 @@
   }
   {
     JSONArray jsarr(&jsobj, "elements");
+    Object& element = Object::Handle();
     for (intptr_t index = 0; index < Length(); index++) {
-      JSONObject jselement(&jsarr);
-      jselement.AddProperty("index", index);
-
-      Object& element = Object::Handle(At(index));
-      jselement.AddProperty("value", element);
+      element = At(index);
+      jsarr.AddValue(element);
     }
   }
 }
@@ -19623,12 +19612,10 @@
   }
   {
     JSONArray jsarr(&jsobj, "elements");
+    Object& element = Object::Handle();
     for (intptr_t index = 0; index < Length(); index++) {
-      JSONObject jselement(&jsarr);
-      jselement.AddProperty("index", index);
-
-      Object& element = Object::Handle(At(index));
-      jselement.AddProperty("value", element);
+      element = At(index);
+      jsarr.AddValue(element);
     }
   }
 }
@@ -19669,18 +19656,13 @@
 
 
 RawLinkedHashMap* LinkedHashMap::NewDefault(Heap::Space space) {
-  // Keep this in sync with Dart implementation (lib/compact_hash.dart).
-  static const intptr_t kInitialIndexBits = 3;
-  static const intptr_t kInitialIndexSize = 1 << (kInitialIndexBits + 1);
   const Array& data = Array::Handle(Array::New(kInitialIndexSize, space));
   const TypedData& index = TypedData::Handle(TypedData::New(
       kTypedDataUint32ArrayCid, kInitialIndexSize, space));
+  // On 32-bit, the top bits are wasted to avoid Mint allocation.
+  static const intptr_t kAvailableBits = (kSmiBits >= 32) ? 32 : kSmiBits;
   static const intptr_t kInitialHashMask =
-#if defined(ARCH_IS_64_BIT)
-      (1 << (32 - kInitialIndexBits)) - 1;
-#else
-      (1 << (30 - kInitialIndexBits)) - 1;
-#endif
+      (1 << (kAvailableBits - kInitialIndexBits)) - 1;
   return LinkedHashMap::New(data, index, kInitialHashMask, 0, 0, space);
 }
 
@@ -19720,8 +19702,8 @@
 
 
 const char* LinkedHashMap::ToCString() const {
-  // TODO(koda): Print key/value pairs.
-  return "_LinkedHashMap";
+  Zone* zone = Isolate::Current()->current_zone();
+  return zone->PrintToString("_LinkedHashMap len:%" Pd, Length());
 }
 
 
@@ -19730,11 +19712,22 @@
   PrintSharedInstanceJSON(&jsobj, ref);
   jsobj.AddProperty("kind", "Map");
   jsobj.AddServiceId(*this);
-  // TODO(koda): Print length.
+  jsobj.AddProperty("length", Length());
   if (ref) {
     return;
   }
-  // TODO(koda): Print key/value pairs.
+  {
+    JSONArray jsarr(&jsobj, "associations");
+    Object& object = Object::Handle();
+    LinkedHashMap::Iterator iterator(*this);
+    while (iterator.MoveNext()) {
+      JSONObject jsassoc(&jsarr);
+      object = iterator.CurrentKey();
+      jsassoc.AddProperty("key", object);
+      object = iterator.CurrentValue();
+      jsassoc.AddProperty("value", object);
+    }
+  }
 }
 
 
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 39a57ba..612a80b 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -206,7 +206,7 @@
   friend class StackFrame;                                                     \
 
 // This macro is used to denote types that do not have a sub-type.
-#define FINAL_HEAP_OBJECT_IMPLEMENTATION(object, super)                        \
+#define FINAL_HEAP_OBJECT_IMPLEMENTATION_HELPER(object, rettype, super)        \
  public:  /* NOLINT */                                                         \
   void operator=(Raw##object* value) {                                         \
     raw_ = value;                                                              \
@@ -226,10 +226,16 @@
   static intptr_t NextFieldOffset() {                                          \
     return -kWordSize;                                                         \
   }                                                                            \
-  SNAPSHOT_READER_SUPPORT(object)                                              \
+  SNAPSHOT_READER_SUPPORT(rettype)                                             \
   friend class Isolate;                                                        \
   friend class StackFrame;                                                     \
 
+#define FINAL_HEAP_OBJECT_IMPLEMENTATION(object, super)                        \
+  FINAL_HEAP_OBJECT_IMPLEMENTATION_HELPER(object, object, super)               \
+
+#define MINT_OBJECT_IMPLEMENTATION(object, rettype, super)                     \
+  FINAL_HEAP_OBJECT_IMPLEMENTATION_HELPER(object, rettype, super)              \
+
 class Object {
  public:
   virtual ~Object() { }
@@ -699,6 +705,10 @@
   RawObject* raw_;  // The raw object reference.
 
  protected:
+  void AddCommonObjectProperties(JSONObject* jsobj,
+                                 const char* protocol_type,
+                                 bool ref) const;
+
   virtual void PrintJSONImpl(JSONStream* stream, bool ref) const;
 
  private:
@@ -5548,7 +5558,7 @@
  private:
   void set_value(int64_t value) const;
 
-  FINAL_HEAP_OBJECT_IMPLEMENTATION(Mint, Integer);
+  MINT_OBJECT_IMPLEMENTATION(Mint, Integer, Integer);
   friend class Class;
 };
 
@@ -7233,9 +7243,61 @@
     return OFFSET_OF(RawLinkedHashMap, deleted_keys_);
   }
 
+  intptr_t Length() const {
+    intptr_t used = Smi::Value(raw_ptr()->used_data_);
+    intptr_t deleted = Smi::Value(raw_ptr()->deleted_keys_);
+    return (used >> 1) - deleted;
+  }
+
+  // This iterator differs somewhat from its Dart counterpart (_CompactIterator
+  // in runtime/lib/compact_hash.dart):
+  //  - There are no checks for concurrent modifications.
+  //  - Accessing a key or value before the first call to MoveNext and after
+  //    MoveNext returns false will result in crashes.
+  class Iterator : ValueObject {
+   public:
+    explicit Iterator(const LinkedHashMap& map)
+      : data_(Array::Handle(map.data())),
+        scratch_(Object::Handle()),
+        offset_(-2),
+        length_(Smi::Value(map.used_data())) {}
+
+    bool MoveNext() {
+      while (true) {
+        offset_ += 2;
+        if (offset_ >= length_) {
+          return false;
+        }
+        scratch_ = data_.At(offset_);
+        if (scratch_.raw() != data_.raw()) {
+          // Slot is not deleted (self-reference indicates deletion).
+          return true;
+        }
+      }
+    }
+
+    RawObject* CurrentKey() const {
+      return data_.At(offset_);
+    }
+
+    RawObject* CurrentValue() const {
+      return data_.At(offset_ + 1);
+    }
+
+   private:
+    const Array& data_;
+    Object& scratch_;
+    intptr_t offset_;
+    const intptr_t length_;
+  };
+
  private:
   FINAL_HEAP_OBJECT_IMPLEMENTATION(LinkedHashMap, Instance);
 
+  // Keep this in sync with Dart implementation (lib/compact_hash.dart).
+  static const intptr_t kInitialIndexBits = 3;
+  static const intptr_t kInitialIndexSize = 1 << (kInitialIndexBits + 1);
+
   // Allocate a map, but leave all fields set to null.
   // Used during deserialization (since map might contain itself as key/value).
   static RawLinkedHashMap* NewUninitialized(Heap::Space space = Heap::kNew);
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index ebe0ba0..028455d 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -4500,7 +4500,8 @@
         "\"class\":{\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\","
         "\"name\":\"_InternalLinkedHashMap\",\"_vmName\":\"\"},"
         "\"kind\":\"Map\","
-        "\"id\":\"\"}",
+        "\"id\":\"\","
+        "\"length\":0}",
         buffer);
   }
   // UserTag reference
@@ -4706,4 +4707,46 @@
   CheckIdenticalHashStructure(dart_map, cc_map);
 }
 
+
+TEST_CASE(LinkedHashMap_iteration) {
+  const char* kScript =
+      "makeMap() {\n"
+      "  var map = {'x': 3, 'y': 4, 'z': 5, 'w': 6};\n"
+      "  map.remove('y');\n"
+      "  map.remove('w');\n"
+      "  return map;\n"
+      "}";
+  Dart_Handle h_lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(h_lib);
+  Library& lib = Library::Handle();
+  lib ^= Api::UnwrapHandle(h_lib);
+  EXPECT(!lib.IsNull());
+  Dart_Handle h_result = Dart_Invoke(h_lib, NewString("makeMap"), 0, NULL);
+  EXPECT_VALID(h_result);
+
+  Instance& dart_map = Instance::Handle();
+  dart_map ^= Api::UnwrapHandle(h_result);
+  ASSERT(dart_map.IsLinkedHashMap());
+  const LinkedHashMap& cc_map = LinkedHashMap::Cast(dart_map);
+
+  EXPECT_EQ(2, cc_map.Length());
+
+  LinkedHashMap::Iterator iterator(cc_map);
+  Object& object = Object::Handle();
+
+  EXPECT(iterator.MoveNext());
+  object = iterator.CurrentKey();
+  EXPECT_STREQ("x", object.ToCString());
+  object = iterator.CurrentValue();
+  EXPECT_STREQ("3", object.ToCString());
+
+  EXPECT(iterator.MoveNext());
+  object = iterator.CurrentKey();
+  EXPECT_STREQ("z", object.ToCString());
+  object = iterator.CurrentValue();
+  EXPECT_STREQ("5", object.ToCString());
+
+  EXPECT(!iterator.MoveNext());
+}
+
 }  // namespace dart
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 7479a09..0307c90 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -37,32 +37,14 @@
 
 namespace dart {
 
-DEFINE_FLAG(bool, enable_asserts, false, "Enable assert statements.");
 DEFINE_FLAG(bool, enable_debug_break, false, "Allow use of break \"message\".");
-DEFINE_FLAG(bool, enable_type_checks, false, "Enable type checks.");
 DEFINE_FLAG(bool, load_deferred_eagerly, false,
     "Load deferred libraries eagerly.");
 DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations.");
 DEFINE_FLAG(bool, warn_mixin_typedef, true, "Warning on legacy mixin typedef.");
-DECLARE_FLAG(bool, error_on_bad_type);
 DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
 DECLARE_FLAG(bool, warn_on_javascript_compatibility);
 
-static void CheckedModeHandler(bool value) {
-  FLAG_enable_asserts = value;
-  FLAG_enable_type_checks = value;
-}
-
-// --enable-checked-mode and --checked both enable checked mode which is
-// equivalent to setting --enable-asserts and --enable-type-checks.
-DEFINE_FLAG_HANDLER(CheckedModeHandler,
-                    enable_checked_mode,
-                    "Enable checked mode.");
-
-DEFINE_FLAG_HANDLER(CheckedModeHandler,
-                    checked,
-                    "Enable checked mode.");
-
 
 // Quick access to the current isolate and zone.
 #define I (isolate())
@@ -3230,7 +3212,7 @@
     // Populate function scope with the formal parameters.
     AddFormalParamsToScope(&params, current_block_->scope);
 
-    if (I->TypeChecksEnabled() &&
+    if (I->flags().type_checks() &&
         (current_block_->scope->function_level() > 0)) {
       // We are parsing, but not compiling, a local function.
       // The instantiator may be required at run time for generic type checks.
@@ -7282,7 +7264,7 @@
   bool is_final = (CurrentToken() == Token::kFINAL);
   bool is_const = (CurrentToken() == Token::kCONST);
   const AbstractType& type = AbstractType::ZoneHandle(Z,
-      ParseConstFinalVarOrType(I->TypeChecksEnabled() ?
+      ParseConstFinalVarOrType(I->flags().type_checks() ?
           ClassFinalizer::kCanonicalize : ClassFinalizer::kIgnore));
   if (!IsIdentifier()) {
     ReportError("identifier expected");
@@ -8391,8 +8373,8 @@
     // position, which is inside the loop body.
     new_loop_var = true;
     loop_var_type = ParseConstFinalVarOrType(
-       I->TypeChecksEnabled() ? ClassFinalizer::kCanonicalize :
-                                ClassFinalizer::kIgnore);
+       I->flags().type_checks() ? ClassFinalizer::kCanonicalize :
+                                  ClassFinalizer::kIgnore);
   }
   intptr_t loop_var_pos = TokenPos();
   const String* loop_var_name = ExpectIdentifier("variable name expected");
@@ -8671,8 +8653,8 @@
     // position, which is inside the loop body.
     new_loop_var = true;
     loop_var_type = ParseConstFinalVarOrType(
-        I->TypeChecksEnabled() ? ClassFinalizer::kCanonicalize :
-                                 ClassFinalizer::kIgnore);
+        I->flags().type_checks() ? ClassFinalizer::kCanonicalize :
+                                   ClassFinalizer::kIgnore);
     loop_var_name = ExpectIdentifier("variable name expected");
   }
   ExpectToken(Token::kIN);
@@ -8890,7 +8872,7 @@
   ConsumeToken();  // Consume assert keyword.
   ExpectToken(Token::kLPAREN);
   const intptr_t condition_pos = TokenPos();
-  if (!I->AssertsEnabled() && !I->TypeChecksEnabled()) {
+  if (!I->flags().asserts() && !I->flags().type_checks()) {
     SkipExpr();
     ExpectToken(Token::kRPAREN);
     return NULL;
@@ -12083,7 +12065,7 @@
                     "include a type variable");
       }
     } else {
-      if (I->ErrorOnBadTypeEnabled()) {
+      if (I->flags().error_on_bad_type()) {
         ReportError(type_pos,
                     "a list literal takes one type argument specifying "
                     "the element type");
@@ -12106,7 +12088,7 @@
     while (CurrentToken() != Token::kRBRACK) {
       const intptr_t element_pos = TokenPos();
       AstNode* element = ParseExpr(is_const, kConsumeCascades);
-      if (I->TypeChecksEnabled() &&
+      if (I->flags().type_checks() &&
           !is_const &&
           !element_type.IsDynamicType()) {
         element = new(Z) AssignableNode(element_pos,
@@ -12137,7 +12119,7 @@
       // Arguments have been evaluated to a literal value already.
       ASSERT(elem->IsLiteralNode());
       ASSERT(!is_top_level_);  // We cannot check unresolved types.
-      if (I->TypeChecksEnabled() &&
+      if (I->flags().type_checks() &&
           !element_type.IsDynamicType() &&
           (!elem->AsLiteralNode()->literal().IsNull() &&
            !elem->AsLiteralNode()->literal().IsInstanceOf(
@@ -12280,7 +12262,7 @@
                     "include a type variable");
       }
     } else {
-      if (I->ErrorOnBadTypeEnabled()) {
+      if (I->flags().error_on_bad_type()) {
         ReportError(type_pos,
                     "a map literal takes two type arguments specifying "
                     "the key type and the value type");
@@ -12299,7 +12281,7 @@
     const bool saved_mode = SetAllowFunctionLiterals(true);
     const intptr_t key_pos = TokenPos();
     AstNode* key = ParseExpr(is_const, kConsumeCascades);
-    if (I->TypeChecksEnabled() &&
+    if (I->flags().type_checks() &&
         !is_const &&
         !key_type.IsDynamicType()) {
       key = new(Z) AssignableNode(
@@ -12322,7 +12304,7 @@
     const intptr_t value_pos = TokenPos();
     AstNode* value = ParseExpr(is_const, kConsumeCascades);
     SetAllowFunctionLiterals(saved_mode);
-    if (I->TypeChecksEnabled() &&
+    if (I->flags().type_checks() &&
         !is_const &&
         !value_type.IsDynamicType()) {
       value = new(Z) AssignableNode(
@@ -12354,7 +12336,7 @@
       // Arguments have been evaluated to a literal value already.
       ASSERT(arg->IsLiteralNode());
       ASSERT(!is_top_level_);  // We cannot check unresolved types.
-      if (I->TypeChecksEnabled()) {
+      if (I->flags().type_checks()) {
         if ((i % 2) == 0) {
           // Check key type.
           arg_type = key_type.raw();
@@ -12679,7 +12661,7 @@
         }
         return ThrowTypeError(redirect_type.token_pos(), redirect_type);
       }
-      if (I->TypeChecksEnabled() && !redirect_type.IsSubtypeOf(type, NULL)) {
+      if (I->flags().type_checks() && !redirect_type.IsSubtypeOf(type, NULL)) {
         // Additional type checking of the result is necessary.
         type_bound = type.raw();
       }
diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc
index 29be014..9fd95f2 100644
--- a/runtime/vm/profiler_service.cc
+++ b/runtime/vm/profiler_service.cc
@@ -200,7 +200,7 @@
   void PrintToJSONObject(JSONObject* func) {
     func->AddProperty("type", "@Function");
     func->AddProperty("name", name());
-    func->AddProperty("kind", KindToCString(kind()));
+    func->AddProperty("_kind", KindToCString(kind()));
   }
 
   void PrintToJSONArray(JSONArray* functions) {
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index f571979..349ad59 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -1661,6 +1661,7 @@
   friend class SnapshotReader;
   friend class GrowableObjectArray;
   friend class LinkedHashMap;
+  friend class RawLinkedHashMap;
   friend class Object;
   friend class ICData;  // For high performance access.
   friend class SubtypeTestCache;  // For high performance access.
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 27ec70d..152c4b0 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -722,8 +722,8 @@
   }
 
   // Initialize all fields that are not part of the snapshot.
+  func.ClearICDataArray();
   func.ClearCode();
-  func.set_ic_data_array(Object::null_array());
   return func.raw();
 }
 
@@ -1681,15 +1681,21 @@
 }
 
 
-RawMint* Mint::ReadFrom(SnapshotReader* reader,
-                        intptr_t object_id,
-                        intptr_t tags,
-                        Snapshot::Kind kind) {
+RawInteger* Mint::ReadFrom(SnapshotReader* reader,
+                           intptr_t object_id,
+                           intptr_t tags,
+                           Snapshot::Kind kind) {
   ASSERT(reader != NULL);
 
   // Read the 64 bit value for the object.
   int64_t value = reader->Read<int64_t>();
 
+  // Check if the value could potentially fit in a Smi in our current
+  // architecture, if so return the object as a Smi.
+  if (Smi::IsValid(value)) {
+    return Smi::New(static_cast<intptr_t>(value));
+  }
+
   // Create a Mint object or get canonical one if it is a canonical constant.
   Mint& mint = Mint::ZoneHandle(reader->zone(), Mint::null());
   if (kind == Snapshot::kFull) {
@@ -2204,9 +2210,9 @@
 
 
 RawLinkedHashMap* LinkedHashMap::ReadFrom(SnapshotReader* reader,
-                                              intptr_t object_id,
-                                              intptr_t tags,
-                                              Snapshot::Kind kind) {
+                                          intptr_t object_id,
+                                          intptr_t tags,
+                                          Snapshot::Kind kind) {
   ASSERT(reader != NULL);
 
   LinkedHashMap& map = LinkedHashMap::ZoneHandle(
@@ -2222,20 +2228,46 @@
   reader->AddBackRef(object_id, &map, kIsDeserialized);
   // Set the object tags.
   map.set_tags(tags);
-  // Read and set the fields.
-  intptr_t num_flds = (map.raw()->to() - map.raw()->from());
-  for (intptr_t i = 0; i <= num_flds; i++) {
-    (*reader->PassiveObjectHandle()) = reader->ReadObjectRef();
-    map.StorePointer((map.raw()->from() + i),
-                     reader->PassiveObjectHandle()->raw());
+
+  // Read the type arguments.
+  *reader->TypeArgumentsHandle() ^= reader->ReadObjectImpl();
+  map.SetTypeArguments(*reader->TypeArgumentsHandle());
+
+  // Read the number of key/value pairs.
+  intptr_t len = reader->ReadSmiValue();
+  intptr_t used_data = (len << 1);
+  map.SetUsedData(used_data);
+
+  // Allocate the data array.
+  intptr_t data_size = Utils::Maximum(
+      Utils::RoundUpToPowerOfTwo(used_data),
+      static_cast<uintptr_t>(LinkedHashMap::kInitialIndexSize));
+  Array& data = Array::ZoneHandle(reader->zone(),
+                                  Array::New(data_size, HEAP_SPACE(kind)));
+  map.SetData(data);
+  map.SetDeletedKeys(0);
+
+  // The index and hashMask is regenerated by the maps themselves on demand.
+  // Thus, the index will probably be allocated in new space (unless it's huge).
+  // TODO(koda): Eagerly rehash here when no keys have user-defined '==', and
+  // in particular, if/when (const) maps are needed in the VM isolate snapshot.
+  ASSERT(reader->isolate() != Dart::vm_isolate());
+  map.SetHashMask(0);  // Prefer sentinel 0 over null for better type feedback.
+
+  // Read the keys and values.
+  bool is_canonical = RawObject::IsCanonical(tags);
+  for (intptr_t i = 0; i < used_data; i++) {
+    *reader->PassiveObjectHandle() =
+        is_canonical ? reader->ReadObjectImpl() : reader->ReadObjectRef();
+    data.SetAt(i, *reader->PassiveObjectHandle());
   }
   return map.raw();
 }
 
 
 void RawLinkedHashMap::WriteTo(SnapshotWriter* writer,
-                                 intptr_t object_id,
-                                 Snapshot::Kind kind) {
+                               intptr_t object_id,
+                               Snapshot::Kind kind) {
   if (kind == Snapshot::kFull || kind == Snapshot::kScript) {
     // The immutable maps that seed map literals are not yet VM-internal, so
     // we don't reach this.
@@ -2248,14 +2280,45 @@
 
   // Write out the class and tags information.
   writer->WriteIndexedObject(kLinkedHashMapCid);
-  writer->WriteTags(writer->GetObjectTags(this));
+  const uword tags = writer->GetObjectTags(this);
+  writer->WriteTags(tags);
 
-  // Write out all the object pointer fields.
-  // TODO(koda): Serialize only used parts of data_ (after compaction), to
-  // reduce space and support per-isolate salted hash codes. All allowed keys
-  // have types for which we can rehash without running Dart code.
-  SnapshotWriterVisitor visitor(writer);
-  visitor.VisitPointers(from(), to());
+  // Write out the type arguments.
+  writer->WriteObjectImpl(ptr()->type_arguments_);
+
+  const intptr_t used_data = Smi::Value(ptr()->used_data_);
+  ASSERT((used_data & 1) == 0);  // Keys + values, so must be even.
+  const intptr_t deleted_keys = Smi::Value(ptr()->deleted_keys_);
+
+  // Write out the number of (not deleted) key/value pairs that will follow.
+  writer->Write<RawObject*>(Smi::New((used_data >> 1) - deleted_keys));
+
+  // Write out the keys and values.
+  const bool is_canonical = RawObject::IsCanonical(tags);
+  RawArray* data_array = ptr()->data_;
+  RawObject** data_elements = data_array->ptr()->data();
+  ASSERT(used_data <= Smi::Value(data_array->ptr()->length_));
+#if defined(DEBUG)
+  intptr_t deleted_keys_found = 0;
+#endif  // DEBUG
+  for (intptr_t i = 0; i < used_data; i += 2) {
+    RawObject* key = data_elements[i];
+    if (key == data_array) {
+#if defined(DEBUG)
+      ++deleted_keys_found;
+#endif  // DEBUG
+      continue;
+    }
+    RawObject* value = data_elements[i + 1];
+    if (is_canonical) {
+      writer->WriteObjectImpl(key);
+      writer->WriteObjectImpl(value);
+    } else {
+      writer->WriteObjectRef(key);
+      writer->WriteObjectRef(value);
+    }
+  }
+  DEBUG_ASSERT(deleted_keys_found == deleted_keys);
 }
 
 
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index ef3d12e..0593f7f 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -74,6 +74,54 @@
 struct ServiceMethodDescriptor;
 ServiceMethodDescriptor* FindMethod(const char* method_name);
 
+// TODO(turnidge): Build a general framework later.  For now, we have
+// a small set of well-known streams.
+bool Service::needs_isolate_events_ = false;
+bool Service::needs_debug_events_ = false;
+bool Service::needs_gc_events_ = false;
+bool Service::needs_echo_events_ = false;
+bool Service::needs_graph_events_ = false;
+
+void Service::ListenStream(const char* stream_id) {
+  if (FLAG_trace_service) {
+    OS::Print("vm-service: starting stream '%s'\n",
+              stream_id);
+  }
+  if (strcmp(stream_id, "Isolate") == 0) {
+    needs_isolate_events_ = true;
+  } else if (strcmp(stream_id, "Debug") == 0) {
+    needs_debug_events_ = true;
+  } else if (strcmp(stream_id, "GC") == 0) {
+    needs_gc_events_ = true;
+  } else if (strcmp(stream_id, "_Echo") == 0) {
+    needs_echo_events_ = true;
+  } else if (strcmp(stream_id, "_Graph") == 0) {
+    needs_graph_events_ = true;
+  } else {
+    UNREACHABLE();
+  }
+}
+
+void Service::CancelStream(const char* stream_id) {
+  if (FLAG_trace_service) {
+    OS::Print("vm-service: stopping stream '%s'\n",
+              stream_id);
+  }
+  if (strcmp(stream_id, "Isolate") == 0) {
+    needs_isolate_events_ = false;
+  } else if (strcmp(stream_id, "Debug") == 0) {
+    needs_debug_events_ = false;
+  } else if (strcmp(stream_id, "GC") == 0) {
+    needs_gc_events_ = false;
+  } else if (strcmp(stream_id, "_Echo") == 0) {
+    needs_echo_events_ = false;
+  } else if (strcmp(stream_id, "_Graph") == 0) {
+    needs_graph_events_ = false;
+  } else {
+    UNREACHABLE();
+  }
+}
+
 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) {
   void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size);
   return reinterpret_cast<uint8_t*>(new_ptr);
@@ -497,13 +545,9 @@
 }
 
 
-bool Service::NeedsEvents() {
-  return ServiceIsolate::IsRunning();
-}
-
-
-void Service::SendEvent(intptr_t eventType,
-                        const Object& eventMessage) {
+void Service::SendEvent(const char* stream_id,
+                        const char* event_type,
+                        const Object& event_message) {
   ASSERT(!ServiceIsolate::IsServiceIsolateDescendant(Isolate::Current()));
   if (!ServiceIsolate::IsRunning()) {
     return;
@@ -512,14 +556,21 @@
   ASSERT(isolate != NULL);
   HANDLESCOPE(isolate);
 
+  const Array& list = Array::Handle(Array::New(2));
+  ASSERT(!list.IsNull());
+  const String& stream_id_str = String::Handle(String::New(stream_id));
+  list.SetAt(0, stream_id_str);
+  list.SetAt(1, event_message);
+
   // Push the event to port_.
   uint8_t* data = NULL;
   MessageWriter writer(&data, &allocator, false);
-  writer.WriteMessage(eventMessage);
+  writer.WriteMessage(list);
   intptr_t len = writer.BytesWritten();
   if (FLAG_trace_service) {
-    OS::Print("vm-service: Pushing event of type %" Pd ", len %" Pd "\n",
-              eventType, len);
+    OS::Print(
+        "vm-service: Pushing event of type %s to stream %s, len %" Pd "\n",
+        event_type, stream_id, len);
   }
   // TODO(turnidge): For now we ignore failure to send an event.  Revisit?
   PortMap::PostMessage(
@@ -527,9 +578,11 @@
 }
 
 
-void Service::SendEvent(const String& meta,
-                        const uint8_t* data,
-                        intptr_t size) {
+void Service::SendEventWithData(const char* stream_id,
+                                const char* event_type,
+                                const String& meta,
+                                const uint8_t* data,
+                                intptr_t size) {
   // Bitstream: [meta data size (big-endian 64 bit)] [meta data (UTF-8)] [data]
   const intptr_t meta_bytes = Utf8::Length(meta);
   const intptr_t total_bytes = sizeof(uint64_t) + meta_bytes + size;
@@ -552,8 +605,7 @@
     offset += size;
   }
   ASSERT(offset == total_bytes);
-  // TODO(turnidge): Pass the real eventType here.
-  SendEvent(0, message);
+  SendEvent(stream_id, event_type, message);
 }
 
 
@@ -562,12 +614,16 @@
     return;
   }
   JSONStream js;
+  const char* stream_id = event->stream_id();
+  ASSERT(stream_id != NULL);
   {
     JSONObject jsobj(&js);
     jsobj.AddProperty("event", event);
+    jsobj.AddProperty("streamId", stream_id);
   }
   const String& message = String::Handle(String::New(js.ToCString()));
-  SendEvent(event->type(), message);
+  SendEvent(stream_id, ServiceEvent::EventTypeToCString(event->type()),
+            message);
 }
 
 
@@ -616,10 +672,10 @@
   Dart_ServiceRequestCallback callback = handler->callback();
   ASSERT(callback != NULL);
   const char* r = NULL;
-  const char* name = js->method();
+  const char* method = js->method();
   const char** keys = js->param_keys();
   const char** values = js->param_values();
-  r = callback(name, keys, values, js->num_params(), handler->user_data());
+  r = callback(method, keys, values, js->num_params(), handler->user_data());
   ASSERT(r != NULL);
   // TODO(johnmccutchan): Allow for NULL returns?
   TextBuffer* buffer = js->buffer();
@@ -774,15 +830,18 @@
         event.AddProperty("text", text);
       }
     }
+    jsobj.AddProperty("streamId", "_Echo");
   }
   const String& message = String::Handle(String::New(js.ToCString()));
   uint8_t data[] = {0, 128, 255};
-  SendEvent(message, data, sizeof(data));
+  SendEventWithData("_Echo", "_Echo", message, data, sizeof(data));
 }
 
 
 static bool TriggerEchoEvent(Isolate* isolate, JSONStream* js) {
-  Service::SendEchoEvent(isolate, js->LookupParam("text"));
+  if (Service::NeedsEchoEvents()) {
+    Service::SendEchoEvent(isolate, js->LookupParam("text"));
+  }
   JSONObject jsobj(js);
   return HandleCommonEcho(&jsobj, js);
 }
@@ -2091,7 +2150,7 @@
   const char* step_param = js->LookupParam("step");
   if (isolate->message_handler()->paused_on_start()) {
     isolate->message_handler()->set_pause_on_start(false);
-    {
+    if (Service::NeedsDebugEvents()) {
       ServiceEvent event(isolate, ServiceEvent::kResume);
       Service::HandleEvent(&event);
     }
@@ -2260,7 +2319,9 @@
 
 
 static bool RequestHeapSnapshot(Isolate* isolate, JSONStream* js) {
-  Service::SendGraphEvent(isolate);
+  if (Service::NeedsGraphEvents()) {
+    Service::SendGraphEvent(isolate);
+  }
   // TODO(koda): Provide some id that ties this request to async response(s).
   JSONObject jsobj(js);
   jsobj.AddProperty("type", "OK");
@@ -2303,12 +2364,15 @@
         ? stream.bytes_written() - (i * kChunkSize)
         : kChunkSize;
 
-    SendEvent(message, chunk_start, chunk_size);
+    SendEventWithData("_Graph", "_Graph", message, chunk_start, chunk_size);
   }
 }
 
 
 void Service::SendInspectEvent(Isolate* isolate, const Object& inspectee) {
+  if (!Service::NeedsDebugEvents()) {
+    return;
+  }
   ServiceEvent event(isolate, ServiceEvent::kInspect);
   event.set_inspectee(&inspectee);
   Service::HandleEvent(&event);
@@ -2541,8 +2605,8 @@
   // pids > 53-bits (when consumed by JavaScript).
   // TODO(johnmccutchan): Codify how integers are sent across the service.
   jsobj.AddPropertyF("pid", "%" Pd "", OS::ProcessId());
-  jsobj.AddProperty("_assertsEnabled", isolate->AssertsEnabled());
-  jsobj.AddProperty("_typeChecksEnabled", isolate->TypeChecksEnabled());
+  jsobj.AddProperty("_assertsEnabled", isolate->flags().asserts());
+  jsobj.AddProperty("_typeChecksEnabled", isolate->flags().type_checks());
   int64_t start_time_millis = (Dart::vm_isolate()->start_time() /
                                kMicrosecondsPerMillisecond);
   jsobj.AddProperty64("startTime", start_time_millis);
@@ -2633,7 +2697,7 @@
 
 static bool SetName(Isolate* isolate, JSONStream* js) {
   isolate->set_debugger_name(js->LookupParam("name"));
-  {
+  if (Service::NeedsIsolateEvents()) {
     ServiceEvent event(isolate, ServiceEvent::kIsolateUpdate);
     Service::HandleEvent(&event);
   }
diff --git a/runtime/vm/service.h b/runtime/vm/service.h
index 4ca3eb0..a7a7569 100644
--- a/runtime/vm/service.h
+++ b/runtime/vm/service.h
@@ -67,7 +67,14 @@
   // Handles a message which is directed to a particular isolate.
   static void HandleIsolateMessage(Isolate* isolate, const Array& message);
 
-  static bool NeedsEvents();
+  static bool NeedsIsolateEvents() { return needs_isolate_events_; }
+  static bool NeedsDebugEvents() { return needs_debug_events_; }
+  static bool NeedsGCEvents() { return needs_gc_events_; }
+  static bool NeedsEchoEvents() { return needs_echo_events_; }
+  static bool NeedsGraphEvents() { return needs_graph_events_; }
+
+  static void ListenStream(const char* stream_id);
+  static void CancelStream(const char* stream_id);
 
   static void HandleEvent(ServiceEvent* event);
 
@@ -94,15 +101,24 @@
   static EmbedderServiceHandler* FindIsolateEmbedderHandler(const char* name);
   static EmbedderServiceHandler* FindRootEmbedderHandler(const char* name);
 
-  static void SendEvent(intptr_t eventType,
+  static void SendEvent(const char* stream_id,
+                        const char* event_type,
                         const Object& eventMessage);
   // Does not take ownership of 'data'.
-  static void SendEvent(const String& meta,
-                        const uint8_t* data,
-                        intptr_t size);
+  static void SendEventWithData(const char* stream_id,
+                                const char* event_type,
+                                const String& meta,
+                                const uint8_t* data,
+                                intptr_t size);
 
   static EmbedderServiceHandler* isolate_service_handler_head_;
   static EmbedderServiceHandler* root_service_handler_head_;
+
+  static bool needs_isolate_events_;
+  static bool needs_debug_events_;
+  static bool needs_gc_events_;
+  static bool needs_echo_events_;
+  static bool needs_graph_events_;
 };
 
 }  // namespace dart
diff --git a/runtime/vm/service/client.dart b/runtime/vm/service/client.dart
index 56051f8..c8a374a 100644
--- a/runtime/vm/service/client.dart
+++ b/runtime/vm/service/client.dart
@@ -8,6 +8,7 @@
 abstract class Client {
   final VMService service;
   final bool sendEvents;
+  final Set<String> streams = new Set<String>();
 
   Client(this.service, { bool sendEvents: true })
       : this.sendEvents = sendEvents {
diff --git a/runtime/vm/service/message.dart b/runtime/vm/service/message.dart
index 3afbd0d..7b07baa 100644
--- a/runtime/vm/service/message.dart
+++ b/runtime/vm/service/message.dart
@@ -9,6 +9,7 @@
   bool get completed => _completer.isCompleted;
   /// Future of response.
   Future<String> get response => _completer.future;
+  Client client;
 
   // Client-side identifier for this message.
   final serial;
@@ -33,7 +34,7 @@
     });
   }
 
-  Message.fromJsonRpc(Map map)
+  Message.fromJsonRpc(this.client, Map map)
       : serial = map['id'], method = map['method'] {
     params.addAll(map['params']);
   }
@@ -48,12 +49,12 @@
     return uri.pathSegments[0];
   }
 
-  Message.fromUri(Uri uri)
+  Message.fromUri(this.client, Uri uri)
       : method = _methodNameFromUri(uri) {
     params.addAll(uri.queryParameters);
   }
 
-  Message.forIsolate(Uri uri, RunningIsolate isolate)
+  Message.forIsolate(this.client, Uri uri, RunningIsolate isolate)
       : method = _methodNameFromUri(uri) {
     params.addAll(uri.queryParameters);
     params['isolateId'] = isolate.serviceId;
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index 005a771..a42486596 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -1,8 +1,10 @@
-# Dart VM Service Protocol 0.0
+# Dart VM Service Protocol 1.0 (Draft 1)
 
-This document describes _version 0.0_ of the Dart VM Service Protocol.
-This protocol is used to communicate with a running Dart Virtual
-Machine.
+> Please post feedback to the [observatory-discuss group][discuss-list]
+
+This document describes _draft 1_ of _version 1.0_ of the Dart VM
+Service Protocol.  This protocol is used to communicate with a running
+Dart Virtual Machine.
 
 To use the Service Protocol, start the VM with the *--observe* flag.
 The VM will start a webserver which services protocol requests via WebSocket.
@@ -11,7 +13,7 @@
 here.
 
 The Service Protocol is based on JSON-RPC 2.0
-(http://www.jsonrpc.org/specification).  The Service Protocol has been
+(http://www.jsonrpc.org/specification). The Service Protocol has been
 extended to support pushing _events_ to the client, which is
 apparently outside the scope of the JSON-RPC specification.
 
@@ -49,7 +51,10 @@
 	- [ClassList](#classlist)
 	- [Code](#code)
 	- [CodeKind](#codekind)
+	- [Context](#context)
+	- [ContextElement](#contextelement)
 	- [Error](#error)
+	- [ErrorKind](#errorkind)
 	- [Event](#event)
 	- [EventKind](#eventkind)
 	- [Field](#field)
@@ -61,13 +66,14 @@
 	- [Isolate](#isolate)
 	- [Library](#library)
 	- [LibraryDependency](#librarydependency)
-	- [ListElement](#listelement)
+	- [MapAssociation](#mapassociation)
 	- [Message](#message)
 	- [Null](#null)
 	- [Object](#object)
 	- [Sentinel](#sentinel)
 	- [SentinelKind](#sentinelkind)
 	- [Script](#script)
+	- [SourceLocation](#sourcelocation)
 	- [Stack](#stack)
 	- [StepOption](#stepoption)
 	- [Success](#success)
@@ -79,7 +85,7 @@
 
 ## RPCs, Requests, and Responses
 
-An RPC request is a JSON object sent to the server.  Here is an
+An RPC request is a JSON object sent to the server. Here is an
 example [getVersion](#getversion) request:
 
 ```
@@ -91,11 +97,11 @@
 }
 ```
 
-Currently the _id_ property must be a string.  The Service Protocol
+Currently the _id_ property must be a string. The Service Protocol
 optionally accepts requests without the _jsonprc_ property.
 
-An RPC response is a JSON object (http://json.org/).  The response always specifies an
-_id_ property to pair it with the corresponding request.  If the RPC
+An RPC response is a JSON object (http://json.org/). The response always specifies an
+_id_ property to pair it with the corresponding request. If the RPC
 was successful, the _result_ property provides the result.
 
 Here is an example response for our [getVersion](#getversion) request above:
@@ -105,7 +111,7 @@
   "json-rpc": "2.0",
   "result": {
     "type": "Version",
-    "major": 0,
+    "major": 1,
     "minor": 0
   }
   "id": "1"
@@ -118,7 +124,7 @@
 
 By convention, every response returned by the Service Protocol is a subtype
 of [Response](#response) and provides a _type_ paramters which can be used
-to distinguish the exact return type.  In the example above, the
+to distinguish the exact return type. In the example above, the
 [Version](#version) type is returned.
 
 Here is an example [streamListen](#streamlisten) request which provides
@@ -137,11 +143,11 @@
 
 <a name="rpc-error"></a>
 When an RPC encounters an error, it is provided in the _error_
-property of the response object.  JSON-RPC errors always provide
+property of the response object. JSON-RPC errors always provide
 _code_, _message_, and _data_ properties.
 
 Here is an example error response for our [streamListen](#streamlisten)
-request above.  This error would be generated if we were attempting to
+request above. This error would be generated if we were attempting to
 subscribe to the _GC_ stream multiple times from the same client.
 
 ```
@@ -176,11 +182,11 @@
 
 By using the [streamListen](#streamlisten) and [streamCancel](#streamcancel) RPCs, a client may
 request to be notified when an _event_ is posted to a specific
-_stream_ in the VM.  Every stream has an associated _stream id_ which
+_stream_ in the VM. Every stream has an associated _stream id_ which
 is used to name that stream.
 
-Each stream provides access to certain kinds of events.  For example the _Isolate_ stream provides
-access to events pertaining to isolate births, deaths, and name changes.  See [streamListen](#streamlisten)
+Each stream provides access to certain kinds of events. For example the _Isolate_ stream provides
+access to events pertaining to isolate births, deaths, and name changes. See [streamListen](#streamlisten)
 for a list of the well-known stream ids and their associated events.
 
 Events arrive asynchronously over the WebSocket and always have the
@@ -210,12 +216,12 @@
 
 By convention, every result and event provided by the Service Protocol
 is a subtype of [Response](#response) and has the _type_ property.
-This allows the client to distinguish different kinds of responses.  For example,
+This allows the client to distinguish different kinds of responses. For example,
 information about a Dart function is returned using the [Function](#function) type.
 
 If the type of a response begins with the _@_ character, then that
-response is a _reference_.  If the type name of a response does not
-begin with the _@_ character, it is the an _object_.  A reference is
+response is a _reference_. If the type name of a response does not
+begin with the _@_ character, it is the an _object_. A reference is
 intended to be a subset of an object which provides enough information
 to generate a reasonable looking reference to the object.
 
@@ -250,8 +256,8 @@
 
 Many responses returned by the Service Protocol have an _id_ property.
 This is an identifier used to request an object from an isolate using
-the [getObject](#getobject) RPC.  If two responses have the same _id_ then they
-refer to the same object.  The converse is not true: the same object
+the [getObject](#getobject) RPC. If two responses have the same _id_ then they
+refer to the same object. The converse is not true: the same object
 may sometimes be returned with two different values for _id_.
 
 The _id_ property should be treated as an opaque string by the client:
@@ -259,65 +265,65 @@
 
 An id can be either _temporary_ or _fixed_:
 
-* A _temporary_ id can expire over time.  The VM allocates certain ids
+* A _temporary_ id can expire over time. The VM allocates certain ids
   in a ring which evicts old ids over time.
 
 * A _fixed_ id will never expire, but the object it refers to may
-  be collected.  The VM uses fixed ids for objects like scripts,
+  be collected. The VM uses fixed ids for objects like scripts,
   libraries, and classes.
 
 If an id is fixed, the _fixedId_ property will be true. If an id is temporary
 the _fixedId_ property will be omitted.
 
-Sometimes a temporary id may expire.  In this case, some RPCs may return
+Sometimes a temporary id may expire. In this case, some RPCs may return
 an _Expired_ [Sentinel](#sentinel) to indicate this.
 
 The object referred to by an id may be collected by the VM's garbage
-collector.  In this case, some RPCs may return a _Collected_ [Sentinel](#sentinel)
+collector. In this case, some RPCs may return a _Collected_ [Sentinel](#sentinel)
 to indicate this.
 
-Many objects also have a _name_ property.  This is provided so that
+Many objects also have a _name_ property. This is provided so that
 objects can be displayed in a way that a Dart language programmer
-would find familiar.  Names are not unique.
+would find familiar. Names are not unique.
 
 ## Versioning
 
 The [getVersion](#getversion) RPC can be used to find the version of the protocol
-returned by a VM.  The _Version_ response has a major and a minor
+returned by a VM. The _Version_ response has a major and a minor
 version number:
 
 ```
   "result": {
     "type": "Version",
-    "major": 0,
+    "major": 1,
     "minor": 0
   }
 ```
 
 The major version number is incremented when the protocol is changed
-in a potentially _incompatible_ way.  An example of an incompatible
+in a potentially _incompatible_ way. An example of an incompatible
 change is removing a non-optional property from a result.
 
 The minor version number is incremented when the protocol is changed
-in a _backwards compatible_ way.  An example of a backwards compatible
+in a _backwards compatible_ way. An example of a backwards compatible
 change is adding a property to a result.
 
 Certain changes that would normally not be backwards compatible are
 considered backwards compatible for the purposes of versioning.
 Specifically, additions can be made to the [EventKind](#eventkind) and
 [InstanceKind](#instancekind) enumerated types and the client must
-handle this gracefully.  See the notes on these enumerated types for more
+handle this gracefully. See the notes on these enumerated types for more
 information.
 
 ## Private RPCs, Types, and Properties
 
 Any RPC, type, or property which begins with an underscore is said to
-be _private_.  These RPCs, types, and fields can be changed at any
+be _private_. These RPCs, types, and fields can be changed at any
 time without changing major or minor version numbers.
 
 The intention is that the Service Protocol will evolve by adding
 private RPCs which may, over time, migrate to the public api as they
-become stable.  Some private types and properties expose VM specific
+become stable. Some private types and properties expose VM specific
 implementation state and will never be appropriate to add to
 the public api.
 
@@ -334,9 +340,9 @@
 ```
 
 If an RPC says it returns type _T_ it may actually return _T_ or any
-[subtype](#public-types) of _T_.  For example, an
-RPC which is declared to return [@Instance](#instance) may actually
-return [@Int](#int).
+[subtype](#public-types) of _T_. For example, an
+RPC which is declared to return [@Object](#object) may actually
+return [@Instance](#instance).
 
 If an RPC can return one or more independent types, this is indicated
 with the vertical bar:
@@ -347,7 +353,7 @@
 
 Any RPC may return an _error_ response as [described above](#rpc-error).
 
-Some parameters are optional.  This is indicated by the text
+Some parameters are optional. This is indicated by the text
 _[optional]_ following the parameter name:
 
 ```
@@ -427,7 +433,7 @@
 ```
 
 The _evaluateInFrame_ RPC is used to evaluate an expression in the
-context of a particular stack frame.  _frameIndex_ is the index of the
+context of a particular stack frame. _frameIndex_ is the index of the
 desired [Frame](#frame), with an index of _0_ indicating the top (most
 recent) frame.
 
@@ -485,7 +491,7 @@
 ```
 
 The _getStack_ RPC is used to retrieve the current execution stack and
-message queue for an isolate.  The isolate does not need to be paused.
+message queue for an isolate. The isolate does not need to be paused.
 
 See [Stack](#stack).
 
@@ -515,7 +521,7 @@
 Success pause(string isolateId)
 ```
 
-The _pause_ RPC is used to interrupt a running isolate.  The RPC enqueues the interrupt request and potentially returns before the isolate is paused.
+The _pause_ RPC is used to interrupt a running isolate. The RPC enqueues the interrupt request and potentially returns before the isolate is paused.
 
 When the isolate is paused an event will be sent on the _Debug_ stream.
 
@@ -600,7 +606,7 @@
 Success streamListen(string streamId)
 ```
 
-The _streamListen_ RPC subscribes to a stream in the VM.  Once
+The _streamListen_ RPC subscribes to a stream in the VM. Once
 subscribed, the client will begin receiving events from the stream.
 
 If the client is not subscribed to the stream, the _103_ (Stream already
@@ -646,7 +652,7 @@
 
 This describes a JSON object type _T_ with some set of expected properties.
 
-Types are organized into an inheritance hierarchy.  If type _T_
+Types are organized into an inheritance hierarchy. If type _T_
 extends type _S_...
 
 ```
@@ -660,7 +666,7 @@
 ```
 
 ...then that means that all properties of _S_ are also present in type
-_T_.  In the example above, type _T_ would have the expected
+_T_. In the example above, type _T_ would have the expected
 properties _a_ and _b_.
 
 If a property has an _Array_ type, it is written with brackets:
@@ -740,8 +746,7 @@
 class Breakpoint extends Response {
   int breakpointNumber;
   bool resolved;
-  @Script script;
-  int tokenPos;
+  SourceLocation location;
 }
 ```
 
@@ -784,9 +789,8 @@
   // The library which contains this class.
   @Library library;
 
-  // The script which defines this class.  May be missing for some
-  // classes.
-  @Script script;
+  // The location of this class in the source code.
+  SourceLocation location [optional];
 
   // The superclass of this class, if any.
   @Class super [optional];
@@ -794,11 +798,11 @@
   // A list of interface types for this class.
   @Type[] interfaces;
 
-  // A list of fields in this class.  Does not include fields from
+  // A list of fields in this class. Does not include fields from
   // superclasses.
   @Field[] fields;
 
-  // A list of functions in this class.  Does not include functions
+  // A list of functions in this class. Does not include functions
   // from superclasses.
   @Function[] functions;
 
@@ -869,8 +873,19 @@
   // The number of variables in this context.
   int length;
 
+  // The enclosing context for this context.
+  Context parent [optional];
+
   // The variables in this context object.
-  ListElement[] variables;
+  ContextElement[] variables;
+}
+```
+
+### ContextElement
+
+```
+class ContextElement {
+  @Instance|Sentinel value;
 }
 ```
 
@@ -878,6 +893,9 @@
 
 ```
 class @Error extends @Object {
+  // What kind of error is this?
+  ErrorKind kind;
+
   // A description of the error.
   string message;
 }
@@ -887,6 +905,9 @@
 
 ```
 class Error extends Object {
+  // What kind of error is this?
+  ErrorKind kind;
+
   // A description of the error.
   string message;
 
@@ -900,15 +921,27 @@
 }
 ```
 
-An _Error_ represents a Dart language level error.  This is distinct from an
+An _Error_ represents a Dart language level error. This is distinct from an
 [rpc error](#rpc-error).
 
-An error may occur when:
+### ErrorKind
 
-- The program has encountered an unhandled exception
-- The program has encountered a syntax error (or another Dart language error)
-- The program has encountered an unhandled erroneous condition in native code
-- The program has been terminated
+```
+enum ErrorKind {
+  // The isolate has encountered an unhandled Dart exception.
+  UnhandledException,
+
+  // The isolate has encountered a Dart language error in the program.
+  LanguageError,
+
+  // The isolate has encounted an internal error. These errors should be
+  // reported as bugs.
+  InternalError,
+
+  // The isolate has been terminated by an external source.
+  TerminationError
+}
+```
 
 ### Event
 
@@ -920,7 +953,7 @@
   // The isolate with which this event is associated.
   @Isolate isolate;
 
-  // The breakpoint associated with this event, if applicable.
+  // The breakpoint which was added, removed, or resolved.
   //
   // This is provided for the event kinds:
   //   PauseBreakpoint
@@ -929,6 +962,19 @@
   //   BreakpointResolved
   Breakpoint breakpoint [optional];
 
+  // The list of breakpoints at which we are currently paused
+  // for a PauseBreakpoint event.
+  //
+  // This list may be empty. For example, while single-stepping, the
+  // VM sends a PauseBreakpoint event with no breakpoints.
+  //
+  // If there is more than one breakpoint set at the program position,
+  // then all of them will be provided.
+  //
+  // This is provided for the event kinds:
+  //   PauseBreakpoint
+  Breakpoint[] pauseBreakpoints [optional];
+
   // The top stack frame associated with this event, if applicable.
   //
   // This is provided for the event kinds:
@@ -947,7 +993,7 @@
 }
 ```
 
-An _Event_ is an asynchronous notification from the VM.  It is delivered
+An _Event_ is an asynchronous notification from the VM. It is delivered
 only when the client has subscribed to an event stream using the
 [streamListen](#streamListen) RPC.
 
@@ -1001,7 +1047,7 @@
 ```
 
 Adding new values to _EventKind_ is considered a backwards compatible
-change.  Clients should ignore unrecognized events.
+change. Clients should ignore unrecognized events.
 
 ### Field
 
@@ -1054,11 +1100,8 @@
   // The value of this field, if the field is static.
   @Instance staticValue [optional];
 
-  // The script containing this feild.
-  @Script script [optional];
-
-  // The token position of this field.
-  int tokenPos [optional];
+  // The location of this field in the source code.
+  SourceLocation location [optional];
 }
 ```
 
@@ -1076,6 +1119,9 @@
   // A description of the flag.
   string comment;
 
+  // Has this flag been modified from its default setting?
+  bool modified;
+
   // The value of this flag as a string.
   //
   // If this property is absent, then the value of the flag was NULL.
@@ -1102,7 +1148,7 @@
 ### Frame
 
 ```
-class Frame {
+class Frame extends Response {
   int index;
   @Function function;
   @Code code;
@@ -1145,14 +1191,8 @@
   // Function.
   @Library|@Class|@Function owner;
 
-  // The script containing this function.
-  @Script script [optional];
-
-  // The first token position of this function.
-  int tokenPos [optional];
-
-  // The last token position of this function.
-  int endTokenPos [optional];
+  // The location of this function in the source code.
+  SourceLocation location [optional];
 
   // The compiled code associated with this function.
   @Code code [optional];
@@ -1168,7 +1208,7 @@
   // What kind of instance is this?
   InstanceKind kind;
 
-  // Instance references include their class.
+  // Instance references always include their class.
   @Class class;
 
   // The value of this instance as a string.
@@ -1181,7 +1221,7 @@
   //   String (value may be truncated)
   string valueAsString [optional];
 
-  // The valueAsString for String references may be truncated.  If so,
+  // The valueAsString for String references may be truncated. If so,
   // this property is added with the value 'true'.
   bool valueAsStringIsTruncated [optional];
 
@@ -1218,7 +1258,7 @@
   // What kind of instance is this?
   InstanceKind kind;
 
-  // Instance references include their class.
+  // Instance references always include their class.
   @Class class;
 
   // The value of this instance as a string.
@@ -1230,7 +1270,7 @@
   //   String (value may be truncated)
   string valueAsString [optional];
 
-  // The valueAsString for String references may be truncated.  If so,
+  // The valueAsString for String references may be truncated. If so,
   // this property is added with the value 'true'.
   bool valueAsStringIsTruncated [optional];
 
@@ -1265,7 +1305,13 @@
   //
   // Provided for instance kinds:
   //   List
-  ListElement[] elements [optional];
+  @Instance|Sentinel[] elements [optional];
+
+  // The elements of a List instance.
+  //
+  // Provided for instance kinds:
+  //   Map
+  MapAssociation[] associations [optional];
 
   // The function associated with a Closure instance.
   //
@@ -1310,8 +1356,8 @@
   int parameterIndex [optional];
 
   // The type bounded by a BoundedType instance
-  // or
-  // The referent of a TypeRef instance.
+  // - or -
+  // the referent of a TypeRef instance.
   //
   // The value will always be one of:
   // Type, TypeRef, TypeParameter, BoundedType.
@@ -1319,7 +1365,7 @@
   // Provided for instance kinds:
   //   BoundedType
   //   TypeRef
-  @Instance type [optional];
+  @Instance targetType [optional];
 
   // The bound of a TypeParameter or BoundedType.
   //
@@ -1357,15 +1403,15 @@
   // An instance of the Dart class String.
   String,
 
-  // An instance of the built-in VM List implementation.  User-defined
+  // An instance of the built-in VM List implementation. User-defined
   // Lists will be PlainInstance.
   List,
 
-  // An instance of the built-in VM Map implementation.  User-defined
+  // An instance of the built-in VM Map implementation. User-defined
   // Maps will be PlainInstance.
   Map,
 
-  // An instance of the built-in VM Closure implementation.  User-defined
+  // An instance of the built-in VM Closure implementation. User-defined
   // Closures will be PlainInstance.
   Closure,
 
@@ -1390,7 +1436,7 @@
 ```
 
 Adding new values to _InstanceKind_ is considered a backwards
-compatible change.  Clients should treat unrecognized instance kinds
+compatible change. Clients should treat unrecognized instance kinds
 as _PlainInstance_.
 
 ### Isolate
@@ -1400,10 +1446,10 @@
   // The id which is passed to the getIsolate RPC to load this isolate.
   string id;
 
-  // A numeric id for this isolate, represented as a string.  Unique.
+  // A numeric id for this isolate, represented as a string. Unique.
   string number;
 
-  // A name identifying this isolate.  Not guaranteed to be unique.
+  // A name identifying this isolate. Not guaranteed to be unique.
   string name;
 }
 ```
@@ -1416,10 +1462,10 @@
   // isolate.
   string id;
 
-  // A numeric id for this isolate, represented as a string.  Unique.
+  // A numeric id for this isolate, represented as a string. Unique.
   string number;
 
-  // A name identifying this isolate.  Not guaranteed to be unique.
+  // A name identifying this isolate. Not guaranteed to be unique.
   string name;
 
   // The time that the VM started in milliseconds since the epoch.
@@ -1436,7 +1482,7 @@
   // Will this isolate pause when exiting?
   bool pauseOnExit;
 
-  // The last pause event delivered to the isolate.  If the isolate is
+  // The last pause event delivered to the isolate. If the isolate is
   // running, this will be a resume event.
   Event pauseEvent;
 
@@ -1522,11 +1568,11 @@
 
 A _LibraryDependency_ provides information about an import or export.
 
-### ListElement
+### MapAssociation
 
 ```
-class ListElement {
-  int index;
+class MapAssociation {
+  @Instance|Sentinel key;
   @Instance|Sentinel value;
 }
 ```
@@ -1534,14 +1580,13 @@
 ### Message
 
 ```
-class Message {
+class Message extends Response {
   int index;
   string name;
   string messageObjectId;
   int size;
-  @Function handlerFunction [optional];
-  @Script handleScript [optional];
-  int handlerTokenPos [optional];
+  @Function handler [optional];
+  SourceLocation location [optional];
 }
 ```
 
@@ -1569,7 +1614,7 @@
 
 ```
 class @Object extends Response {
-  // A unique identifier for an Object.  Passed to the
+  // A unique identifier for an Object. Passed to the
   // getObject RPC to load this Object.
   string id
 }
@@ -1579,19 +1624,30 @@
 
 ```
 class Object extends Response {
-  // A unique identifier for an Object.  Passed to the
+  // A unique identifier for an Object. Passed to the
   // getObject RPC to reload this Object.
   //
   // Some objects may get a new id when they are reloaded.
   string id;
 
-  // Every object has a corresponding Class in the VM.
-  @Class class;
+  // If an object is allocated in the Dart heap, it will have
+  // a corresponding class object.
+  //
+  // The class of a non-instance is not a Dart class, but is instead
+  // an internal vm object.
+  //
+  // Moving an Object into or out of the heap is considered a
+  // backwards compatible change for types other than Instance.
+  @Class class [optional];
 
   // The size of this object in the heap.
   //
-  // Note that the size can be zero for some objects.
-  int size;
+  // If an object is not heap-allocated, then this field is omitted.
+  //
+  // Note that the size can be zero for some objects. In the current
+  // VM implementation, this occurs for small integers, which are
+  // stored entirely within their object pointers.
+  int size [optional];
 }
 ```
 
@@ -1612,7 +1668,7 @@
 A _Sentinel_ is used to indicate that the normal response is not available.
 
 We use a _Sentinel_ instead of an [error](#errors) for these cases because
-they do not represent a problematic condition.  They are normal.
+they do not represent a problematic condition. They are normal.
 
 ### SentinelKind
 
@@ -1641,7 +1697,7 @@
 A _SentinelKind_ is used to distinguish different kinds of _Sentinel_ objects.
 
 Adding new values to _SentinelKind_ is considered a backwards
-compatible change.  Clients must handle this gracefully.
+compatible change. Clients must handle this gracefully.
 
 ### Script
 
@@ -1662,7 +1718,7 @@
   // The library which owns this script.
   @Library library;
 
-  // The source code for this script.  For certain built-in scripts,
+  // The source code for this script. For certain built-in scripts,
   // this may be reconstructed without source comments.
   string source;
 
@@ -1673,7 +1729,7 @@
 
 A _Script_ provides information about a Dart language script.
 
-The _tokenPosTable_ is an array of int arrays.  Each subarray
+The _tokenPosTable_ is an array of int arrays. Each subarray
 consists of a line number followed by _(tokenPos, columnNumber)_ pairs:
 
 > [lineNumber, (tokenPos, columnNumber)*]
@@ -1690,6 +1746,24 @@
 101 | 1 | 8
 102 | 2 | 7
 
+### SourceLocation
+
+```
+class SourceLocation extends Response {
+  // The script contaiinging the source location.
+  @Script script;
+
+  // The first token of the location.
+  int tokenPos;
+
+  // The last token of the location if this is a range.
+  int endTokenPos [optional];
+}
+```
+
+The _SourceLocation_ class is used to designate a position or range in
+some script.
+
 ### Stack
 
 ```
@@ -1749,7 +1823,7 @@
 ```
 class Response {
   // Every response returned by the VM Service has the
-  // type property.  This allows the client distinguish
+  // type property. This allows the client distinguish
   // between different kinds of responses.
   string type;
 }
@@ -1808,4 +1882,7 @@
 
 version | comments
 ------- | --------
-0.0 | draft
+1.0 draft 1 | initial revision
+
+
+[discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss
diff --git a/runtime/vm/service/vmservice.dart b/runtime/vm/service/vmservice.dart
index 4566e49..1959cec 100644
--- a/runtime/vm/service/vmservice.dart
+++ b/runtime/vm/service/vmservice.dart
@@ -36,17 +36,25 @@
   ShutdownCallback onShutdown;
 
   void _addClient(Client client) {
+    assert(client.streams.isEmpty);
     clients.add(client);
   }
 
   void _removeClient(Client client) {
     clients.remove(client);
+    for (var streamId in client.streams) {
+      if (!_isAnyClientSubscribed(streamId)) {
+        _vmCancelStream(streamId);
+      }
+    }
   }
 
-  void _eventMessageHandler(dynamic eventMessage) {
+  void _eventMessageHandler(List eventMessage) {
+    var streamId = eventMessage[0];
+    var event = eventMessage[1];
     for (var client in clients) {
-      if (client.sendEvents) {
-        client.post(eventMessage);
+      if (client.sendEvents && client.streams.contains(streamId)) {
+        client.post(event);
       }
     }
   }
@@ -81,20 +89,14 @@
   }
 
   void messageHandler(message) {
-    if (message is String) {
-      // This is an event intended for all clients.
-      _eventMessageHandler(message);
-      return;
-    }
-    if (message is Uint8List) {
-      // This is "raw" data intended for a specific client.
-      //
-      // TODO(turnidge): Do not broadcast this data to all clients.
-      _eventMessageHandler(message);
-      return;
-    }
     if (message is List) {
-      // This is an internal vm service event.
+      if (message.length == 2) {
+        // This is an event.
+        assert(message[0] is String);
+        assert(message[1] is String || message[1] is Uint8List);
+        _eventMessageHandler(message);
+        return;
+      }
       if (message.length == 1) {
         // This is a control message directing the vm service to exit.
         assert(message[0] == Constants.SERVICE_EXIT_MESSAGE_ID);
@@ -108,7 +110,6 @@
         return;
       }
     }
-
     Logger.root.severe(
         'Internal vm-service error: ignoring illegal message: $message');
   }
@@ -142,9 +143,101 @@
     message.setResponse(JSON.encode(result));
   }
 
+  // These must be kept in sync with the declarations in vm/json_stream.h.
+  static const _kInvalidParams = -32602;
+  static const _kStreamAlreadySubscribed = 103;
+  static const _kStreamNotSubscribed = 104;
+
+  var _errorMessages = {
+    _kInvalidParams: 'Invalid params"',
+    _kStreamAlreadySubscribed: 'Stream already subscribed',
+    _kStreamNotSubscribed: 'Stream not subscribed',
+  };
+
+  String _encodeError(Message message, int code, {String details}) {
+    var response = {
+      'id' : message.serial,
+      'error' : {
+        'code': code,
+        'message': _errorMessages[code],
+      },
+    };
+    if (details != null) {
+      response['error']['data'] = {
+        'details': details,
+      };
+    }
+    return JSON.encode(response);
+  }
+
+  String _encodeResult(Message message, Map result) {
+    var response = {
+      'id' : message.serial,
+      'result' : result,
+    };
+    return JSON.encode(response);
+  }
+
+  bool _isValidStream(String streamId) {
+    final validStreams = [ 'Isolate', 'Debug', 'GC', '_Echo', '_Graph' ];
+    return validStreams.contains(streamId);
+  }
+
+  bool _isAnyClientSubscribed(String streamId) {
+    for (var client in clients) {
+      if (client.streams.contains(streamId)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  Future<String> _streamListen(Message message) async {
+    var client = message.client;
+    var streamId = message.params['streamId'];
+
+    if (!_isValidStream(streamId)) {
+      return _encodeError(
+          message, _kInvalidParams,
+          details:"streamListen: invalid 'streamId' parameter: ${streamId}");
+    }
+    if (client.streams.contains(streamId)) {
+      return _encodeError(message, _kStreamAlreadySubscribed);
+    }
+    if (!_isAnyClientSubscribed(streamId)) {
+      _vmListenStream(streamId);
+    }
+    client.streams.add(streamId);
+
+    var result = { 'type' : 'Success' };
+    return _encodeResult(message, result);
+  }
+
+  Future<String> _streamCancel(Message message) async {
+    var client = message.client;
+    var streamId = message.params['streamId'];
+
+    if (!_isValidStream(streamId)) {
+      return _encodeError(
+          message, _kInvalidParams,
+          details:"streamCancel: invalid 'streamId' parameter: ${streamId}");
+    }
+    if (!client.streams.contains(streamId)) {
+      return _encodeError(message, _kStreamNotSubscribed);
+    }
+    client.streams.remove(streamId);
+    if (!_isAnyClientSubscribed(streamId)) {
+      _vmCancelStream(streamId);
+    }
+
+    var result = { 'type' : 'Success' };
+    return _encodeResult(message, result);
+  }
+
   // TODO(johnmccutchan): Turn this into a command line tool that uses the
   // service library.
-  Future<String> _getCrashDump() async {
+  Future<String> _getCrashDump(Message message) async {
+    var client = message.client;
     final perIsolateRequests = [
         // ?isolateId=<isolate id> will be appended to each of these requests.
         // Isolate information.
@@ -165,13 +258,13 @@
     // Request VM.
     var getVM = Uri.parse('getVM');
     var getVmResponse = JSON.decode(
-        await new Message.fromUri(getVM).sendToVM());
+        await new Message.fromUri(client, getVM).sendToVM());
     responses[getVM.toString()] = getVmResponse['result'];
 
     // Request command line flags.
     var getFlagList = Uri.parse('getFlagList');
     var getFlagListResponse = JSON.decode(
-        await new Message.fromUri(getFlagList).sendToVM());
+        await new Message.fromUri(client, getFlagList).sendToVM());
     responses[getFlagList.toString()] = getFlagListResponse['result'];
 
     // Make requests to each isolate.
@@ -185,7 +278,7 @@
       }
       // Dump the object id ring requests.
       var message =
-          new Message.forIsolate(Uri.parse('_dumpIdZone'), isolate);
+          new Message.forIsolate(client, Uri.parse('_dumpIdZone'), isolate);
       var response = JSON.decode(await isolate.route(message));
       // Insert getObject requests into responses map.
       for (var object in response['result']['objects']) {
@@ -196,10 +289,7 @@
     }
 
     // Encode the entire crash dump.
-    return JSON.encode({
-      'id' : null,
-      'result' : responses,
-    });
+    return _encodeResult(message, responses);
   }
 
   Future<String> route(Message message) {
@@ -212,7 +302,13 @@
       return message.response;
     }
     if (message.method == '_getCrashDump') {
-      return _getCrashDump();
+      return _getCrashDump(message);
+    }
+    if (message.method == 'streamListen') {
+      return _streamListen(message);
+    }
+    if (message.method == 'streamCancel') {
+      return _streamCancel(message);
     }
     if (message.params['isolateId'] != null) {
       return runningIsolates.route(message);
@@ -234,3 +330,7 @@
 void _onStart() native "VMService_OnStart";
 
 void _onExit() native "VMService_OnExit";
+
+void _vmListenStream(String streamId) native "VMService_ListenStream";
+
+void _vmCancelStream(String streamId) native "VMService_CancelStream";
diff --git a/runtime/vm/service_event.cc b/runtime/vm/service_event.cc
index a60ca8b..2c6680d 100644
--- a/runtime/vm/service_event.cc
+++ b/runtime/vm/service_event.cc
@@ -84,6 +84,8 @@
       return "GC";  // TODO(koda): Change to GarbageCollected.
     case kInspect:
       return "Inspect";
+    case kIllegal:
+      return "Illegal";
     default:
       UNREACHABLE();
       return "Unknown";
@@ -91,13 +93,51 @@
 }
 
 
+const char* ServiceEvent::stream_id() const {
+  switch (type()) {
+    case kIsolateStart:
+    case kIsolateExit:
+    case kIsolateUpdate:
+      return "Isolate";
+
+    case kPauseStart:
+    case kPauseExit:
+    case kPauseBreakpoint:
+    case kPauseInterrupted:
+    case kPauseException:
+    case kResume:
+    case kBreakpointAdded:
+    case kBreakpointResolved:
+    case kBreakpointRemoved:
+    case kInspect:
+      return "Debug";
+
+    case kGC:
+      return "GC";
+
+    default:
+      UNREACHABLE();
+      return NULL;
+  }
+}
+
+
 void ServiceEvent::PrintJSON(JSONStream* js) const {
   JSONObject jsobj(js);
   jsobj.AddProperty("type", "Event");
   jsobj.AddProperty("kind", EventTypeToCString(type()));
   jsobj.AddProperty("isolate", isolate());
-  if (breakpoint() != NULL) {
-    jsobj.AddProperty("breakpoint", breakpoint());
+  if (type() == kPauseBreakpoint) {
+    JSONArray jsarr(&jsobj, "pauseBreakpoints");
+    // TODO(rmacnak): If we are paused at more than one breakpoint,
+    // provide it here.
+    if (breakpoint() != NULL) {
+      jsarr.AddValue(breakpoint());
+    }
+  } else {
+    if (breakpoint() != NULL) {
+      jsobj.AddProperty("breakpoint", breakpoint());
+    }
   }
   if (top_frame() != NULL) {
     JSONObject jsFrame(&jsobj, "topFrame");
diff --git a/runtime/vm/service_event.h b/runtime/vm/service_event.h
index 0c90d00..f835498 100644
--- a/runtime/vm/service_event.h
+++ b/runtime/vm/service_event.h
@@ -24,13 +24,12 @@
     kPauseInterrupted,
     kPauseException,
     kResume,
-
     kBreakpointAdded,
     kBreakpointResolved,
     kBreakpointRemoved,
+    kInspect,
 
     kGC,
-    kInspect,
 
     kIllegal,
   };
@@ -50,6 +49,8 @@
 
   EventType type() const { return type_; }
 
+  const char* stream_id() const;
+
   Breakpoint* breakpoint() const {
     return breakpoint_;
   }
diff --git a/runtime/vm/service_isolate.cc b/runtime/vm/service_isolate.cc
index faffd66..89d93b6 100644
--- a/runtime/vm/service_isolate.cc
+++ b/runtime/vm/service_isolate.cc
@@ -296,6 +296,26 @@
       }
     }
   }
+
+  static void ListenStream(Dart_NativeArguments args) {
+    NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
+    Isolate* isolate = arguments->thread()->isolate();
+    StackZone stack_zone(isolate);
+    Zone* zone = stack_zone.GetZone();  // Used by GET_NON_NULL_NATIVE_ARGUMENT.
+    HANDLESCOPE(isolate);
+    GET_NON_NULL_NATIVE_ARGUMENT(String, stream_id, arguments->NativeArgAt(0));
+    Service::ListenStream(stream_id.ToCString());
+  }
+
+  static void CancelStream(Dart_NativeArguments args) {
+    NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
+    Isolate* isolate = arguments->thread()->isolate();
+    StackZone stack_zone(isolate);
+    Zone* zone = stack_zone.GetZone();  // Used by GET_NON_NULL_NATIVE_ARGUMENT.
+    HANDLESCOPE(isolate);
+    GET_NON_NULL_NATIVE_ARGUMENT(String, stream_id, arguments->NativeArgAt(0));
+    Service::CancelStream(stream_id.ToCString());
+  }
 };
 
 
@@ -315,6 +335,10 @@
     ServiceIsolateNatives::OnStart },
   {"VMService_OnExit", 0,
     ServiceIsolateNatives::OnExit },
+  {"VMService_ListenStream", 1,
+    ServiceIsolateNatives::ListenStream },
+  {"VMService_CancelStream", 1,
+    ServiceIsolateNatives::CancelStream },
 };
 
 
@@ -601,10 +625,15 @@
       return;
     }
 
+    Isolate::Flags default_flags;
+    Dart_IsolateFlags api_flags;
+    default_flags.CopyTo(&api_flags);
+
     isolate =
         reinterpret_cast<Isolate*>(create_callback(ServiceIsolate::kName,
                                                    NULL,
                                                    NULL,
+                                                   &api_flags,
                                                    NULL,
                                                    &error));
     if (isolate == NULL) {
diff --git a/runtime/vm/service_test.cc b/runtime/vm/service_test.cc
index 5356581..5b119b8 100644
--- a/runtime/vm/service_test.cc
+++ b/runtime/vm/service_test.cc
@@ -204,13 +204,13 @@
                       entry);
   Service::HandleIsolateMessage(isolate, service_msg);
   handler.HandleNextMessage();
+  EXPECT_SUBSTRING("\"type\":\"Code\"", handler.msg());
   {
     // Only perform a partial match.
     const intptr_t kBufferSize = 512;
     char buffer[kBufferSize];
     OS::SNPrint(buffer, kBufferSize-1,
-                "{\"type\":\"Code\",\"fixedId\":true,"
-                "\"id\":\"code\\/%" Px64 "-%" Px "\",",
+                "\"fixedId\":true,\"id\":\"code\\/%" Px64 "-%" Px "\",",
                 compile_timestamp,
                 entry);
     EXPECT_SUBSTRING(buffer, handler.msg());
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index 6bce497..28cf4b5 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -1129,11 +1129,9 @@
   result.SetTypeArguments(*TypeArgumentsHandle());
 
   bool is_canonical = RawObject::IsCanonical(tags);
-  Object& obj = Object::Handle(isolate());
 
   for (intptr_t i = 0; i < len; i++) {
     *PassiveObjectHandle() = is_canonical ? ReadObjectImpl() : ReadObjectRef();
-    obj = (*PassiveObjectHandle()).raw();
     result.SetAt(i, *PassiveObjectHandle());
   }
 }
@@ -1751,19 +1749,6 @@
     return true;
   }
 
-  // Check if the object is a Mint and could potentially be a Smi
-  // on other architectures (64 bit), if so write it out as int64_t value.
-  if (cid == kMintCid) {
-    int64_t value = reinterpret_cast<RawMint*>(rawobj)->ptr()->value_;
-    const intptr_t kSmi64Bits = 62;
-    const int64_t kSmi64Max = (static_cast<int64_t>(1) << kSmi64Bits) - 1;
-    const int64_t kSmi64Min = -(static_cast<int64_t>(1) << kSmi64Bits);
-    if (value <= kSmi64Max && value >= kSmi64Min) {
-      Write<int64_t>((value << kSmiTagShift) | kSmiTag);
-      return true;
-    }
-  }
-
   // Check if it is a code object in that case just write a Null object
   // as we do not want code objects in the snapshot.
   if (cid == kCodeCid) {
diff --git a/runtime/vm/thread_test.cc b/runtime/vm/thread_test.cc
index 63dd249..5cb270b6b 100644
--- a/runtime/vm/thread_test.cc
+++ b/runtime/vm/thread_test.cc
@@ -12,7 +12,10 @@
 
 UNIT_TEST_CASE(Mutex) {
   // This unit test case needs a running isolate.
-  Isolate* isolate = Isolate::Init(NULL);
+  Isolate::Flags vm_flags;
+  Dart_IsolateFlags api_flags;
+  vm_flags.CopyTo(&api_flags);
+  Isolate* isolate = Isolate::Init(NULL, api_flags);
 
   Mutex* mutex = new Mutex();
   mutex->Lock();
@@ -34,7 +37,10 @@
 
 UNIT_TEST_CASE(Monitor) {
   // This unit test case needs a running isolate.
-  Isolate* isolate = Isolate::Init(NULL);
+  Isolate::Flags vm_flags;
+  Dart_IsolateFlags api_flags;
+  vm_flags.CopyTo(&api_flags);
+  Isolate* isolate = Isolate::Init(NULL, api_flags);
   // Thread interrupter interferes with this test, disable interrupts.
   isolate->set_thread_state(NULL);
   Profiler::EndExecution(isolate);
diff --git a/runtime/vm/unit_test.h b/runtime/vm/unit_test.h
index e554b5a..01ba009 100644
--- a/runtime/vm/unit_test.h
+++ b/runtime/vm/unit_test.h
@@ -286,7 +286,8 @@
   static Dart_Isolate CreateIsolate(const uint8_t* buffer,
                                     const char* name) {
     char* err;
-    Dart_Isolate isolate = Dart_CreateIsolate(name, NULL, buffer, NULL, &err);
+    Dart_Isolate isolate = Dart_CreateIsolate(
+        name, NULL, buffer, NULL, NULL, &err);
     if (isolate == NULL) {
       OS::Print("Creation of isolate failed '%s'\n", err);
       free(err);
diff --git a/runtime/vm/zone_test.cc b/runtime/vm/zone_test.cc
index 31ec786..580f968 100644
--- a/runtime/vm/zone_test.cc
+++ b/runtime/vm/zone_test.cc
@@ -16,7 +16,10 @@
 #if defined(DEBUG)
   FLAG_trace_zones = true;
 #endif
-  Isolate* isolate = Isolate::Init(NULL);
+  Isolate::Flags vm_flags;
+  Dart_IsolateFlags api_flags;
+  vm_flags.CopyTo(&api_flags);
+  Isolate* isolate = Isolate::Init(NULL, api_flags);
   EXPECT(Isolate::Current() == isolate);
   EXPECT(isolate->current_zone() == NULL);
   {
@@ -78,7 +81,10 @@
 #if defined(DEBUG)
   FLAG_trace_zones = true;
 #endif
-  Isolate* isolate = Isolate::Init(NULL);
+  Isolate::Flags vm_flags;
+  Dart_IsolateFlags api_flags;
+  vm_flags.CopyTo(&api_flags);
+  Isolate* isolate = Isolate::Init(NULL, api_flags);
   EXPECT(Isolate::Current() == isolate);
   EXPECT(isolate->current_zone() == NULL);
   {
@@ -102,7 +108,10 @@
 #if defined(DEBUG)
   FLAG_trace_zones = true;
 #endif
-  Isolate* isolate = Isolate::Init(NULL);
+  Isolate::Flags vm_flags;
+  Dart_IsolateFlags api_flags;
+  vm_flags.CopyTo(&api_flags);
+  Isolate* isolate = Isolate::Init(NULL, api_flags);
   EXPECT(Isolate::Current() == isolate);
   EXPECT(isolate->current_zone() == NULL);
   {
@@ -121,7 +130,10 @@
 #if defined(DEBUG)
   FLAG_trace_zones = true;
 #endif
-  Isolate* isolate = Isolate::Init(NULL);
+  Isolate::Flags vm_flags;
+  Dart_IsolateFlags api_flags;
+  vm_flags.CopyTo(&api_flags);
+  Isolate* isolate = Isolate::Init(NULL, api_flags);
   EXPECT(Isolate::Current() == isolate);
   EXPECT(isolate->current_zone() == NULL);
   static int marker;
diff --git a/sdk/api_readme.md b/sdk/api_readme.md
index e11030d..4df6470 100644
--- a/sdk/api_readme.md
+++ b/sdk/api_readme.md
@@ -11,16 +11,13 @@
     I/O for command-line apps.
   
 Except for dart:core, you must import a library before you can use it.
-Here's an example of importing dart:html, dart:math, and a
-third popular library called [polymer.dart](https://www.dartlang.org/polymer-dart/):
+Here's an example of importing dart:html and dart:math:
   
     import 'dart:html';
     import 'dart:math';
-    import 'package:polymer/polymer.dart';
   
-Polymer.dart is an example of a library that isn't
-included in the Dart download,
-but is easy to get and update using the _pub package manager_.
+You can install more libraries
+using the _pub package manager_.
 For information on finding, using, and publishing libraries (and more)
 with pub, see [pub.dartlang.org](https://pub.dartlang.org).
   
@@ -35,8 +32,6 @@
   * [A Tour of the Dart Libraries](https://www.dartlang.org/docs/dart-up-and-running/contents/ch03.html)
   
 This API reference is automatically generated from the source code in the
-[Dart project](https://code.google.com/p/dart/).
+[Dart project](https://github.com/dart-lang/sdk).
 If you'd like to contribute to this documentation, see
-[Contributing](https://code.google.com/p/dart/wiki/Contributing)
-and
-[Writing API Documentation](https://code.google.com/p/dart/wiki/WritingApiDocumentation).
\ No newline at end of file
+[Contributing](https://github.com/dart-lang/sdk/wiki/Contributing).
diff --git a/sdk/bin/dartanalyzer b/sdk/bin/dartanalyzer
index fec7d1c..ea69738 100755
--- a/sdk/bin/dartanalyzer
+++ b/sdk/bin/dartanalyzer
@@ -43,7 +43,7 @@
 
 DART_ROOT="$(cd "${SDK_DIR}/.." ; pwd -P)"
 
-ANALYZER="$DART_ROOT/third_party/pkg_tested/analyzer_cli/bin/analyzer.dart"
+ANALYZER="$DART_ROOT/third_party/pkg/analyzer_cli/bin/analyzer.dart"
 
 if [ -z "$DART_CONFIGURATION" ];
 then
diff --git a/sdk/bin/dartanalyzer.bat b/sdk/bin/dartanalyzer.bat
index a296b32..ef041b0 100644
--- a/sdk/bin/dartanalyzer.bat
+++ b/sdk/bin/dartanalyzer.bat
@@ -38,7 +38,7 @@
 rem Remove trailing backslash if there is one
 if %DART_ROOT:~-1%==\ set DART_ROOT=%DART_ROOT:~0,-1%
 
-set ANALYZER=%DART_ROOT%\third_party\pkg_tested\analyzer_cli\bin\analyzer.dart
+set ANALYZER=%DART_ROOT%\third_party\pkg\analyzer_cli\bin\analyzer.dart
 
 rem DART_CONFIGURATION defaults to ReleaseIA32
 if "%DART_CONFIGURATION%"=="" set DART_CONFIGURATION=ReleaseIA32
diff --git a/sdk/lib/_internal/compiler/js_lib/isolate_patch.dart b/sdk/lib/_internal/compiler/js_lib/isolate_patch.dart
index b01318c..4915374 100644
--- a/sdk/lib/_internal/compiler/js_lib/isolate_patch.dart
+++ b/sdk/lib/_internal/compiler/js_lib/isolate_patch.dart
@@ -37,6 +37,7 @@
   @patch
   static Future<Isolate> spawnUri(
       Uri uri, List<String> args, var message, { bool paused: false,
+                                                 bool checked,
                                                  Uri packageRoot }) {
     if (packageRoot != null) throw new UnimplementedError("packageRoot");
     try {
diff --git a/sdk/lib/_internal/compiler/js_lib/js_helper.dart b/sdk/lib/_internal/compiler/js_lib/js_helper.dart
index 02ef267..3fa9543 100644
--- a/sdk/lib/_internal/compiler/js_lib/js_helper.dart
+++ b/sdk/lib/_internal/compiler/js_lib/js_helper.dart
@@ -2318,7 +2318,8 @@
       throw 'Error in reflectionInfo.';
     }
 
-    JS('', '#[#] = #', prototype, JS_SIGNATURE_NAME(), signatureFunction);
+    JS('', '#[#] = #', prototype, JS_GET_NAME(JsGetName.SIGNATURE_NAME),
+        signatureFunction);
 
     JS('', '#[#] = #', prototype, callName, trampoline);
     for (int i = 1; i < functions.length; i++) {
@@ -3221,28 +3222,33 @@
 
   _extractFunctionTypeObjectFrom(o) {
     var interceptor = getInterceptor(o);
-    return JS('bool', '# in #', JS_SIGNATURE_NAME(), interceptor)
-        ? JS('', '#[#]()', interceptor, JS_SIGNATURE_NAME())
+    var signatureName = JS_GET_NAME(JsGetName.SIGNATURE_NAME);
+    return JS('bool', '# in #', signatureName, interceptor)
+        ? JS('', '#[#]()', interceptor, JS_GET_NAME(JsGetName.SIGNATURE_NAME))
         : null;
   }
 
   toRti() {
     var result = createDartFunctionTypeRti();
     if (isVoid) {
-      JS('', '#[#] = true', result, JS_FUNCTION_TYPE_VOID_RETURN_TAG());
+      JS('', '#[#] = true', result,
+          JS_GET_NAME(JsGetName.FUNCTION_TYPE_VOID_RETURN_TAG));
     } else {
       if (returnType is! DynamicRuntimeType) {
-        JS('', '#[#] = #', result, JS_FUNCTION_TYPE_RETURN_TYPE_TAG(),
+        JS('', '#[#] = #', result,
+           JS_GET_NAME(JsGetName.FUNCTION_TYPE_RETURN_TYPE_TAG),
            returnType.toRti());
       }
     }
     if (parameterTypes != null && !parameterTypes.isEmpty) {
-      JS('', '#[#] = #', result, JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG(),
+      JS('', '#[#] = #', result,
+         JS_GET_NAME(JsGetName.FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG),
          listToRti(parameterTypes));
     }
 
     if (optionalParameterTypes != null && !optionalParameterTypes.isEmpty) {
-      JS('', '#[#] = #', result, JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG(),
+      JS('', '#[#] = #', result,
+         JS_GET_NAME(JsGetName.FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG),
          listToRti(optionalParameterTypes));
     }
 
@@ -3254,7 +3260,8 @@
         var rti = JS('', '#[#]', namedParameters, name).toRti();
         JS('', '#[#] = #', namedRti, name, rti);
       }
-      JS('', '#[#] = #', result, JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG(),
+      JS('', '#[#] = #', result,
+         JS_GET_NAME(JsGetName.FUNCTION_TYPE_NAMED_PARAMETERS_TAG),
          namedRti);
     }
 
diff --git a/sdk/lib/_internal/compiler/js_lib/js_mirrors.dart b/sdk/lib/_internal/compiler/js_lib/js_mirrors.dart
index ff7e9c5..1ab1cfc 100644
--- a/sdk/lib/_internal/compiler/js_lib/js_mirrors.dart
+++ b/sdk/lib/_internal/compiler/js_lib/js_mirrors.dart
@@ -2631,41 +2631,51 @@
   JsFunctionTypeMirror(this._typeData, this.owner);
 
   bool get _hasReturnType {
-    return JS('bool', '# in #', JS_FUNCTION_TYPE_RETURN_TYPE_TAG(), _typeData);
+    return JS('bool', '# in #',
+        JS_GET_NAME(JsGetName.FUNCTION_TYPE_RETURN_TYPE_TAG), _typeData);
   }
+
   get _returnType {
-    return JS('', '#[#]', _typeData, JS_FUNCTION_TYPE_RETURN_TYPE_TAG());
+    return JS('', '#[#]', _typeData,
+        JS_GET_NAME(JsGetName.FUNCTION_TYPE_RETURN_TYPE_TAG));
   }
 
   bool get _isVoid {
-    return JS('bool', '!!#[#]', _typeData, JS_FUNCTION_TYPE_VOID_RETURN_TAG());
+    return JS('bool', '!!#[#]', _typeData,
+        JS_GET_NAME(JsGetName.FUNCTION_TYPE_VOID_RETURN_TAG));
   }
 
   bool get _hasArguments {
     return JS('bool', '# in #',
-              JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG(), _typeData);
+              JS_GET_NAME(JsGetName.FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG),
+               _typeData);
   }
   List get _arguments {
     return JS('JSExtendableArray', '#[#]',
-              _typeData, JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG());
+              _typeData,
+              JS_GET_NAME(JsGetName.FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG));
   }
 
   bool get _hasOptionalArguments {
     return JS('bool', '# in #',
-              JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG(), _typeData);
+              JS_GET_NAME(JsGetName.FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG),
+              _typeData);
   }
   List get _optionalArguments {
     return JS('JSExtendableArray', '#[#]',
-              _typeData, JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG());
+              _typeData,
+              JS_GET_NAME(JsGetName.FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG));
   }
 
   bool get _hasNamedArguments {
     return JS('bool', '# in #',
-              JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG(), _typeData);
+              JS_GET_NAME(JsGetName.FUNCTION_TYPE_NAMED_PARAMETERS_TAG),
+              _typeData);
   }
   get _namedArguments {
     return JS('=Object', '#[#]',
-              _typeData, JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG());
+              _typeData,
+              JS_GET_NAME(JsGetName.FUNCTION_TYPE_NAMED_PARAMETERS_TAG));
   }
 
   bool get isOriginalDeclaration => true;
@@ -2854,7 +2864,7 @@
     return reflectClassByMangledName(
         getMangledTypeName(createRuntimeType(representation)));
   }
-  String typedefPropertyName = JS_TYPEDEF_TAG();
+  String typedefPropertyName = JS_GET_NAME(JsGetName.TYPEDEF_TAG);
   if (type != null && JS('', '#[#]', type, typedefPropertyName) != null) {
     return typeMirrorFromRuntimeTypeRepresentation(
         owner, JS('', '#[#]', type, typedefPropertyName));
diff --git a/sdk/lib/_internal/compiler/js_lib/js_rti.dart b/sdk/lib/_internal/compiler/js_lib/js_rti.dart
index 7b9db7c..f153150 100644
--- a/sdk/lib/_internal/compiler/js_lib/js_rti.dart
+++ b/sdk/lib/_internal/compiler/js_lib/js_rti.dart
@@ -105,8 +105,8 @@
  * Returns the type arguments of [target] as an instance of [substitutionName].
  */
 getRuntimeTypeArguments(target, substitutionName) {
-  var substitution =
-      getField(target, '${JS_OPERATOR_AS_PREFIX()}$substitutionName');
+  var substitution = getField(target,
+      '${JS_GET_NAME(JsGetName.OPERATOR_AS_PREFIX)}$substitutionName');
   return substitute(substitution, getRuntimeTypeInfo(target));
 }
 
@@ -392,7 +392,8 @@
   } else if (isDartFunctionType(t)) {
     // Functions are treated specially and have their type information stored
     // directly in the instance.
-    var targetSignatureFunction = getField(o, '${JS_SIGNATURE_NAME()}');
+    var targetSignatureFunction =
+        getField(o, '${JS_GET_NAME(JsGetName.SIGNATURE_NAME)}');
     if (targetSignatureFunction == null) return false;
     type = invokeOn(targetSignatureFunction, o, null);
     return isFunctionSubtype(type, t);
@@ -459,7 +460,8 @@
       return false;
     }
     var typeOfSPrototype = JS('', '#.prototype', typeOfS);
-    var field = '${JS_OPERATOR_AS_PREFIX()}${runtimeTypeToString(typeOfT)}';
+    var field = '${JS_GET_NAME(JsGetName.OPERATOR_AS_PREFIX)}'
+        '${runtimeTypeToString(typeOfT)}';
     substitution = getField(typeOfSPrototype, field);
   }
   // The class of [s] is a subclass of the class of [t].  If [s] has no type
@@ -531,25 +533,26 @@
 bool isFunctionSubtype(var s, var t) {
   assert(isDartFunctionType(t));
   if (!isDartFunctionType(s)) return false;
-  if (hasField(s, '${JS_FUNCTION_TYPE_VOID_RETURN_TAG()}')) {
-    if (hasNoField(t, '${JS_FUNCTION_TYPE_VOID_RETURN_TAG()}') &&
-        hasField(t, '${JS_FUNCTION_TYPE_RETURN_TYPE_TAG()}')) {
+  var voidReturnTag = JS_GET_NAME(JsGetName.FUNCTION_TYPE_VOID_RETURN_TAG);
+  var returnTypeTag = JS_GET_NAME(JsGetName.FUNCTION_TYPE_RETURN_TYPE_TAG);
+  if (hasField(s, voidReturnTag)) {
+    if (hasNoField(t, voidReturnTag) && hasField(t, returnTypeTag)) {
       return false;
     }
-  } else if (hasNoField(t, '${JS_FUNCTION_TYPE_VOID_RETURN_TAG()}')) {
-    var sReturnType = getField(s, '${JS_FUNCTION_TYPE_RETURN_TYPE_TAG()}');
-    var tReturnType = getField(t, '${JS_FUNCTION_TYPE_RETURN_TYPE_TAG()}');
+  } else if (hasNoField(t, voidReturnTag)) {
+    var sReturnType = getField(s, returnTypeTag);
+    var tReturnType = getField(t, returnTypeTag);
     if (!isAssignable(sReturnType, tReturnType)) return false;
   }
-  var sParameterTypes =
-      getField(s, '${JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG()}');
-  var tParameterTypes =
-      getField(t, '${JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG()}');
+  var requiredParametersTag =
+      JS_GET_NAME(JsGetName.FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG);
+  var sParameterTypes = getField(s, requiredParametersTag);
+  var tParameterTypes = getField(t, requiredParametersTag);
 
-  var sOptionalParameterTypes =
-      getField(s, '${JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG()}');
-  var tOptionalParameterTypes =
-      getField(t, '${JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG()}');
+  var optionalParametersTag =
+      JS_GET_NAME(JsGetName.FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG);
+  var sOptionalParameterTypes = getField(s, optionalParametersTag);
+  var tOptionalParameterTypes = getField(t, optionalParametersTag);
 
   int sParametersLen = sParameterTypes != null ? getLength(sParameterTypes) : 0;
   int tParametersLen = tParameterTypes != null ? getLength(tParameterTypes) : 0;
@@ -606,10 +609,10 @@
     }
   }
 
-  var sNamedParameters =
-      getField(s, '${JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG()}');
-  var tNamedParameters =
-      getField(t, '${JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG()}');
+  var namedParametersTag =
+      JS_GET_NAME(JsGetName.FUNCTION_TYPE_NAMED_PARAMETERS_TAG);
+  var sNamedParameters = getField(s, namedParametersTag);
+  var tNamedParameters = getField(t, namedParametersTag);
   return areAssignableMaps(sNamedParameters, tNamedParameters);
 }
 
diff --git a/sdk/lib/_internal/compiler/js_lib/shared/embedded_names.dart b/sdk/lib/_internal/compiler/js_lib/shared/embedded_names.dart
index 03fcf72..9118548 100644
--- a/sdk/lib/_internal/compiler/js_lib/shared/embedded_names.dart
+++ b/sdk/lib/_internal/compiler/js_lib/shared/embedded_names.dart
@@ -92,7 +92,15 @@
   REQUIRED_PARAMETER_PROPERTY,
   DEFAULT_VALUES_PROPERTY,
   CALL_NAME_PROPERTY,
-  DEFERRED_ACTION_PROPERTY
+  DEFERRED_ACTION_PROPERTY,
+  OPERATOR_AS_PREFIX,
+  SIGNATURE_NAME,
+  TYPEDEF_TAG,
+  FUNCTION_TYPE_VOID_RETURN_TAG,
+  FUNCTION_TYPE_RETURN_TYPE_TAG,
+  FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG,
+  FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG,
+  FUNCTION_TYPE_NAMED_PARAMETERS_TAG,
 }
 
 enum JsBuiltin {
diff --git a/sdk/lib/collection/list.dart b/sdk/lib/collection/list.dart
index e7d902e..9b6b753 100644
--- a/sdk/lib/collection/list.dart
+++ b/sdk/lib/collection/list.dart
@@ -476,7 +476,7 @@
 
   void insertAll(int index, Iterable<E> iterable) {
     RangeError.checkValueInInterval(index, 0, length, "index");
-    if (iterable is EfficientLength) {
+    if (iterable is! EfficientLength || identical(iterable, this)) {
       iterable = iterable.toList();
     }
     int insertionLength = iterable.length;
@@ -484,6 +484,12 @@
     // will end up being modified but the operation not complete. Unless we
     // always go through a "toList" we can't really avoid that.
     this.length += insertionLength;
+    if (iterable.length != insertionLength) {
+      // If the iterable's length is linked to this list's length somehow,
+      // we can't insert one in the other.
+      this.length -= insertionLength;
+      throw new ConcurrentModificationError(iterable);
+    }
     setRange(index + insertionLength, this.length, this, index);
     setAll(index, iterable);
   }
diff --git a/sdk/lib/internal/list.dart b/sdk/lib/internal/list.dart
index e642fb7..ed5c987 100644
--- a/sdk/lib/internal/list.dart
+++ b/sdk/lib/internal/list.dart
@@ -123,7 +123,7 @@
   }
 
   /** This operation is not supported by an unmodifiable list. */
-  E insert(int index, E value) {
+  void insert(int index, E element) {
     throw new UnsupportedError(
         "Cannot add to an unmodifiable list");
   }
diff --git a/sdk/lib/isolate/isolate.dart b/sdk/lib/isolate/isolate.dart
index 8c46d60..8372eaf 100644
--- a/sdk/lib/isolate/isolate.dart
+++ b/sdk/lib/isolate/isolate.dart
@@ -148,8 +148,6 @@
    * before it starts running.
    * To resume the isolate, call `isolate.resume(isolate.pauseCapability)`.
    *
-   * WARNING: The `pause` parameter is not implemented on all platforms yet.
-   *
    * Returns a future that will complete with an [Isolate] instance if the
    * spawning succeeded. It will complete with an error otherwise.
    */
@@ -172,6 +170,26 @@
    * When present, the parameter `args` is set to the provided [args] list.
    * When present, the parameter `message` is set to the initial [message].
    *
+   * If the [paused] parameter is set to `true`,
+   * the isolate will start up in a paused state,
+   * as if by an initial call of `isolate.pause(isolate.pauseCapability)`.
+   * This allows setting up error or exit listeners on the isolate
+   * before it starts running.
+   * To resume the isolate, call `isolate.resume(isolate.pauseCapability)`.
+   *
+   * If the [checked] parameter is set to `true` or `false`,
+   * the new isolate will run code in checked mode,
+   * respectively in production mode, if possible.
+   * If the parameter is omitted, the new isolate will inherit the
+   * value from the current isolate.
+   *
+   * It may not always be possible to honor the `checked` parameter.
+   * If the isolate code was pre-compiled, it may not be possible to change
+   * the checked mode setting dynamically.
+   * In that case, the `checked` parameter is ignored.
+   *
+   * WARNING: The [checked] parameter is not implemented on all platforms yet.
+   *
    * If the [packageRoot] parameter is provided, it is used to find the location
    * of packages imports in the spawned isolate.
    * The `packageRoot` URI must be a "file" or "http"/"https" URI that specifies
@@ -187,15 +205,6 @@
    * WARNING: The [packageRoot] parameter is not implemented on all
    * platforms yet.
    *
-   * If the [paused] parameter is set to `true`,
-   * the isolate will start up in a paused state,
-   * as if by an initial call of `isolate.pause(isolate.pauseCapability)`.
-   * This allows setting up error or exit listeners on the isolate
-   * before it starts running.
-   * To resume the isolate, call `isolate.resume(isolate.pauseCapability)`.
-   *
-   * WARNING: The `pause` parameter is not implemented on all platforms yet.
-   *
    * Returns a future that will complete with an [Isolate] instance if the
    * spawning succeeded. It will complete with an error otherwise.
    */
@@ -204,6 +213,7 @@
       List<String> args,
       var message,
       {bool paused: false,
+       bool checked,
        Uri packageRoot});
 
   /**
diff --git a/sdk/lib/svg/dartium/svg_dartium.dart b/sdk/lib/svg/dartium/svg_dartium.dart
index 63a74c6..0090a4d 100644
--- a/sdk/lib/svg/dartium/svg_dartium.dart
+++ b/sdk/lib/svg/dartium/svg_dartium.dart
@@ -1,3 +1,11 @@
+/**
+ * Scalable Vector Graphics:
+ * Two-dimensional vector graphics with support for events and animation.
+ *
+ * For details about the features and syntax of SVG, a W3C standard,
+ * refer to the
+ * [Scalable Vector Graphics Specification](http://www.w3.org/TR/SVG/).
+ */
 library dart.dom.svg;
 
 import 'dart:async';
diff --git a/sdk/lib/web_audio/dartium/web_audio_dartium.dart b/sdk/lib/web_audio/dartium/web_audio_dartium.dart
index 40547d5..0d2124c 100644
--- a/sdk/lib/web_audio/dartium/web_audio_dartium.dart
+++ b/sdk/lib/web_audio/dartium/web_audio_dartium.dart
@@ -1,3 +1,6 @@
+/**
+ * High-fidelity audio programming in the browser.
+ */
 library dart.dom.web_audio;
 
 import 'dart:async';
diff --git a/sdk/lib/web_gl/dartium/web_gl_dartium.dart b/sdk/lib/web_gl/dartium/web_gl_dartium.dart
index 7b9d549..cf2f5f7 100644
--- a/sdk/lib/web_gl/dartium/web_gl_dartium.dart
+++ b/sdk/lib/web_gl/dartium/web_gl_dartium.dart
@@ -1,3 +1,6 @@
+/**
+ * 3D programming in the browser.
+ */
 library dart.dom.web_gl;
 
 import 'dart:async';
diff --git a/tests/co19/co19-analyzer2.status b/tests/co19/co19-analyzer2.status
index 423ab88..8d35bf6 100644
--- a/tests/co19/co19-analyzer2.status
+++ b/tests/co19/co19-analyzer2.status
@@ -7,6 +7,7 @@
 WebPlatformTest/html/semantics/forms/the-textarea-element/textarea-type_t01: fail
 LayoutTests/fast/forms/checkValidity-001_t01: fail
 Language/12_Expressions/29_Assignable_Expressions_A01_t08: StaticWarning
+Language/14_Libraries_and_Scripts/3_Parts_A03_t11: fail, pass # Issue 23595
 
 # TBF: Static members should not be accessible via subclasses.
 Language/07_Classes/9_Superclasses/1_Inheritance_and_Overriding_A01_t05: MissingStaticWarning
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 2f271ba..dfe9a16 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -9633,17 +9633,11 @@
 Language/07_Classes/6_Constructors/2_Factories_A09_t03: Crash # Please triage this failure.
 Language/07_Classes/6_Constructors/2_Factories_A09_t04: Crash # Please triage this failure.
 Language/10_Generics/09_Generics_A04_t03: Crash # Please triage this failure.
-Language/12_Expressions/12_Instance_Creation/1_New_A06_t07: RuntimeError # Please triage this failure.
-Language/12_Expressions/12_Instance_Creation/1_New_A06_t08: Crash # Please triage this failure.
-Language/12_Expressions/12_Instance_Creation/1_New_A06_t09: RuntimeError # Please triage this failure.
 Language/12_Expressions/12_Instance_Creation/1_New_A06_t12: RuntimeError # Please triage this failure.
-Language/12_Expressions/12_Instance_Creation/1_New_A06_t13: RuntimeError # Please triage this failure.
-Language/12_Expressions/12_Instance_Creation/1_New_A06_t14: Crash # Please triage this failure.
 Language/12_Expressions/13_Property_Extraction_A03_t01: RuntimeError # Please triage this failure.
 Language/12_Expressions/13_Property_Extraction_A03_t02: RuntimeError # Please triage this failure.
 Language/12_Expressions/13_Property_Extraction_A03_t03: RuntimeError # Please triage this failure.
 Language/12_Expressions/15_Method_Invocation/4_Super_Invocation_A01_t01: RuntimeError # Please triage this failure.
-Language/12_Expressions/15_Method_Invocation/4_Super_Invocation_A02_t04: RuntimeError # Please triage this failure.
 Language/12_Expressions/22_Equality_A03_t01: RuntimeError # Please triage this failure.
 Language/12_Expressions/30_Identifier_Reference_A09_t03: Crash # (i=0): For-loop variable captured in loop header
 Language/12_Expressions/33_Type_Cast_A01_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
@@ -9794,12 +9788,10 @@
 LayoutTests/fast/css/pseudo-valid-dynamic_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
 LayoutTests/fast/css/readonly-pseudoclass-opera-005_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
 LayoutTests/fast/css/visited-link-hang_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/dom/TreeWalker/TreeWalker-basic_t01: Crash # Please triage this failure.
 LayoutTests/fast/dom/location-hash_t01: Crash #  Unhandled node
 LayoutTests/fast/dynamic/inline-to-block-crash_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
 LayoutTests/fast/encoding/css-charset-dom_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
 LayoutTests/fast/events/event-attributes-after-exception_t01: Crash #  try/finally
-LayoutTests/fast/eventsource/eventsource-constructor_t01: Crash # Please triage this failure.
 LayoutTests/fast/files/file-reader-methods-illegal-arguments_t01: Crash #  Unhandled node
 LayoutTests/fast/forms/autofocus-focus-only-once_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
 LayoutTests/fast/forms/datalist/datalist-child-validation_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
@@ -9859,7 +9851,7 @@
 LayoutTests/fast/xpath/name-null-namespace_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
 LayoutTests/fast/xsl/default-html_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
 LayoutTests/fast/xsl/extra-lf-at-end_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LibTest/async/DeferredLibrary/DeferredLibrary_A01_t01: Crash # (lazy.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
+LibTest/async/DeferredLibrary/DeferredLibrary_A01_t01: RuntimeError # Please triage this failure.
 LibTest/async/Stream/Stream.periodic_A01_t01: Crash # Please triage this failure.
 LibTest/async/Stream/drain_A01_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
 LibTest/async/Stream/drain_A02_t01: Crash # Please triage this failure.
diff --git a/tests/compiler/dart2js/const_exp_test.dart b/tests/compiler/dart2js/const_exp_test.dart
index 50b63af..3117c2d 100644
--- a/tests/compiler/dart2js/const_exp_test.dart
+++ b/tests/compiler/dart2js/const_exp_test.dart
@@ -31,12 +31,13 @@
      var element = env.getElement('constant');
      Expect.isNotNull(element, "Element 'constant' not found.");
      var constant = env.compiler.constants.getConstantForVariable(element);
+     var value = env.compiler.constants.getConstantValue(constant);
      Expect.isNotNull(constant,
                       "No constant computed for '$element'.");
      Expect.equals(expectedOutput, constant.getText(),
          "Unexpected to string '${constant.getText()}' for constant "
          "'$constantInitializer' of value "
-         "${constant.value.toStructuredString()}");
+         "${value.toStructuredString()}");
    });
 }
 
diff --git a/tests/compiler/dart2js/constant_expression_evaluate_test.dart b/tests/compiler/dart2js/constant_expression_evaluate_test.dart
index 2a2c41e..2e82412 100644
--- a/tests/compiler/dart2js/constant_expression_evaluate_test.dart
+++ b/tests/compiler/dart2js/constant_expression_evaluate_test.dart
@@ -38,7 +38,8 @@
   final Compiler compiler;

   final Map<String, String> env;

 

-  MemoryEnvironment(this.compiler, [this.env = const <String, String>{}]);

+  MemoryEnvironment(this.compiler,

+                    [this.env = const <String, String>{}]);

 

   @override

   String readFromEnvironment(String name) => env[name];

@@ -54,6 +55,7 @@
     const ConstantData('"foo"', const { const {} : 'StringConstant("foo")' }),

     const ConstantData('1 + 2', const { const {} : 'IntConstant(3)' }),

     const ConstantData('-(1)', const { const {} : 'IntConstant(-1)' }),

+    const ConstantData('"foo".length', const { const {} : 'IntConstant(3)' }),

     const ConstantData('identical(0, 1)',

                        const { const {} : 'BoolConstant(false)' }),

     const ConstantData('"a" "b"', const { const {} : 'StringConstant("ab")' }),

@@ -144,9 +146,7 @@
 }

 class B<S> implements C {

   const factory B({field1}) = A<B<S>>;

-  // TODO(johnniwinther): Enable this when the constructor evaluator doesn't

-  // crash:

-  /*const factory B.named() = A<S>;*/

+  const factory B.named() = A<S>;

 }

 class C<U> {

   const factory C({field1}) = A<B<double>>;

@@ -170,11 +170,9 @@
     const ConstantData('const C<int>(field1: 87)',

         const { const {} :

           'ConstructedConstant(A<B<double>>(field1=IntConstant(87)))' }),

-    // TODO(johnniwinther): Enable this when the constructor evaluator doesn't

-    // crash:

-    /*const ConstantData('const B<int>.named()',

+    const ConstantData('const B<int>.named()',

         const { const {} :

-          'ConstructedConstant(A<int>(field1=IntConstant(42)))' }),*/

+          'ConstructedConstant(A<int>(field1=IntConstant(42)))' }),

   ]),

   const TestData('''

 const c = const int.fromEnvironment("foo", defaultValue: 5);

diff --git a/tests/compiler/dart2js/constant_expression_test.dart b/tests/compiler/dart2js/constant_expression_test.dart
index c7fdaaf..d4e9df0 100644
--- a/tests/compiler/dart2js/constant_expression_test.dart
+++ b/tests/compiler/dart2js/constant_expression_test.dart
@@ -52,6 +52,7 @@
     const ConstantData('"foo"', ConstantExpressionKind.STRING),
     const ConstantData('1 + 2', ConstantExpressionKind.BINARY),
     const ConstantData('-(1)', ConstantExpressionKind.UNARY, text: '-1'),
+    const ConstantData('"foo".length', ConstantExpressionKind.STRING_LENGTH),
     const ConstantData('identical(0, 1)', ConstantExpressionKind.IDENTICAL),
     const ConstantData('"a" "b"', ConstantExpressionKind.CONCATENATE,
                        text: '"ab"'),
@@ -148,7 +149,7 @@
   const factory B({field1}) = A<B<S>>;
   // TODO(johnniwinther): Enable this when the constructor evaluator doesn't 
   // crash:
-  /*const factory B.named() = A<S>;*/
+  const factory B.named() = A<S>;
 }
 class C<U> {
   const factory C({field1}) = A<B<double>>;
@@ -183,14 +184,12 @@
         fields: const {
           'field(A#field1)': '87',
         }),
-    // TODO(johnniwinther): Enable this when the constructor evaluator doesn't
-    // crash:
-    /*const ConstantData('const B<int>.named()',
+    const ConstantData('const B<int>.named()',
         ConstantExpressionKind.CONSTRUCTED,
         type: 'A<int>',
         fields: const {
           'field(A#field1)': '42',
-        }),*/
+        }),
   ]),
 ];
 
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_control_flow_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_control_flow_test.dart
index a444de9..0e5808a 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_control_flow_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_control_flow_test.dart
@@ -130,7 +130,8 @@
   }
 }""","""
 function() {
-  P.identical(V.foo(), true) ? P.print("bad") : P.print("good");
+  V.foo();
+  P.print("good");
   return null;
 }"""),
 ];
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_operators_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_operators_test.dart
index bd4eec4..486bcc7 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_operators_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_operators_test.dart
@@ -16,7 +16,18 @@
   print(foo() ? "hello world" : "bad bad");
 }""",
 """function() {
-  P.print(P.identical(V.foo(), true) ? "hello world" : "bad bad");
+  V.foo();
+  P.print("bad bad");
+  return null;
+}"""),
+  const TestEntry("""
+foo() => null;
+main() {
+  print(foo() ? "hello world" : "bad bad");
+}""",
+"""function() {
+  V.foo();
+  P.print("bad bad");
   return null;
 }"""),
   const TestEntry("""
@@ -25,21 +36,25 @@
   print(foo ? "hello world" : "bad bad");
 }""",
 """function() {
-  P.print(P.identical(V.foo(), true) ? "hello world" : "bad bad");
+  V.foo();
+  P.print("bad bad");
   return null;
 }"""),
   const TestEntry("""
 get foo => foo;
 main() { print(foo && foo); }""",
 """function() {
-  P.print(P.identical(V.foo(), true) && P.identical(V.foo(), true));
+  V.foo();
+  P.print(false);
   return null;
 }"""),
   const TestEntry("""
 get foo => foo;
 main() { print(foo || foo); }""",
 """function() {
-  P.print(P.identical(V.foo(), true) || P.identical(V.foo(), true));
+  V.foo();
+  V.foo();
+  P.print(false);
   return null;
 }"""),
 
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_source_information_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_source_information_test.dart
index 505901f..713281f 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_source_information_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_source_information_test.dart
@@ -43,10 +43,6 @@
   return compiler.enqueuer.codegen.generatedCode[element];
 }
 
-ir.FunctionDefinition getIrNodeForElement(Compiler compiler, Element element) {
-  return compiler.irBuilder.getIr(element);
-}
-
 String getCodeForMethod(Compiler compiler, String name) {
   Element foundElement;
   for (Element element in compiler.enqueuer.codegen.generatedCode.keys) {
@@ -71,13 +67,23 @@
     Map files = {TEST_MAIN_FILE: test.source};
     asyncTest(() {
       Compiler compiler = compilerFor(files, options: <String>['--use-cps-ir']);
+      ir.FunctionDefinition irNodeForMain;
+
+      void cacheIrNodeForMain(Element function, ir.FunctionDefinition irNode) {
+        if (function == compiler.mainFunction) {
+          assert(irNodeForMain == null);
+          irNodeForMain = irNode;
+        }
+      }
+
       Uri uri = Uri.parse('memory:$TEST_MAIN_FILE');
+      compiler.irBuilder.builderCallback = cacheIrNodeForMain;
+
       return compiler.run(uri).then((bool success) {
         Expect.isTrue(success);
 
-        ir.Node irNode = getIrNodeForElement(compiler, compiler.mainFunction);
         IrSourceInformationVisitor irVisitor = new IrSourceInformationVisitor();
-        irNode.accept(irVisitor);
+        irNodeForMain.accept(irVisitor);
 
         js.Node jsNode = getJsNodeForElement(compiler, compiler.mainFunction);
         JsSourceInformationVisitor jsVisitor = new JsSourceInformationVisitor();
@@ -90,7 +96,7 @@
               'Expected:\n$expectation\n'
               'but found\n${irVisitor.sourceInformation}\n'
               'in\n${test.source}'
-              'CPS:\n${irNode.accept(new ir.SExpressionStringifier())}');
+              'CPS:\n${irNodeForMain.accept(new ir.SExpressionStringifier())}');
         Expect.listEquals(expectation, jsVisitor.sourceInformation,
               'Unexpected JS source information. '
               'Expected:\n$expectation\n'
diff --git a/tests/compiler/dart2js/memory_compiler.dart b/tests/compiler/dart2js/memory_compiler.dart
index 017db0a..482bb7c 100644
--- a/tests/compiler/dart2js/memory_compiler.dart
+++ b/tests/compiler/dart2js/memory_compiler.dart
@@ -6,6 +6,8 @@
 
 import 'memory_source_file_helper.dart';
 
+import 'package:compiler/src/compile_time_constants.dart';
+
 import 'package:compiler/src/dart2jslib.dart'
        show NullSink;
 
@@ -155,6 +157,8 @@
     // this call.
     compiler.onLibrariesLoaded(new MemoryLoadedLibraries(copiedLibraries));
 
+    compiler.backend.constantCompilerTask.copyConstantValues(
+        cachedCompiler.backend.constantCompilerTask);
     compiler.symbolConstructor = cachedCompiler.symbolConstructor;
     compiler.mirrorSystemClass = cachedCompiler.mirrorSystemClass;
     compiler.mirrorsUsedClass = cachedCompiler.mirrorsUsedClass;
diff --git a/tests/compiler/dart2js/message_kind_helper.dart b/tests/compiler/dart2js/message_kind_helper.dart
index 9fd6638..7bc63ce 100644
--- a/tests/compiler/dart2js/message_kind_helper.dart
+++ b/tests/compiler/dart2js/message_kind_helper.dart
@@ -10,6 +10,8 @@
 import 'package:compiler/src/dart2jslib.dart' show
     Compiler,
     MessageKind;
+import 'package:compiler/src/dart_backend/dart_backend.dart' show
+    DartBackend;
 
 import 'memory_compiler.dart';
 
@@ -69,12 +71,21 @@
       messages.add(message);
     }
 
+    bool oldBackendIsDart;
+    if (cachedCompiler != null) {
+      oldBackendIsDart = cachedCompiler.backend is DartBackend;
+    }
+    bool newBackendIsDart = kind.options.contains('--output-type=dart');
+
     Compiler compiler = compilerFor(
         example,
         diagnosticHandler: collect,
         options: ['--analyze-only',
                   '--enable-experimental-mirrors']..addAll(kind.options),
-        cachedCompiler: cachedCompiler);
+        cachedCompiler:
+             // TODO(johnniwinther): Remove this restriction when constant
+             // values can be computed directly from the expressions.
+             oldBackendIsDart == newBackendIsDart ? cachedCompiler : null);
 
     return compiler.run(Uri.parse('memory:main.dart')).then((_) {
 
diff --git a/tests/compiler/dart2js/metadata_test.dart b/tests/compiler/dart2js/metadata_test.dart
index 62e6fecb..847f469 100644
--- a/tests/compiler/dart2js/metadata_test.dart
+++ b/tests/compiler/dart2js/metadata_test.dart
@@ -36,7 +36,8 @@
         'Unexpected metadata count on $element.');
     PartialMetadataAnnotation annotation = element.metadata.head;
     annotation.ensureResolved(compiler);
-    PrimitiveConstantValue value = annotation.constant.value;
+    PrimitiveConstantValue value =
+        compiler.constants.getConstantValue(annotation.constant);
     Expect.stringEquals('xyz', value.primitiveValue.slowToString());
 
     checkPosition(annotation, annotation.cachedNode, source1, compiler);
@@ -59,8 +60,10 @@
     Expect.isFalse(identical(annotation1, annotation2),
                    'expected unique instances');
     Expect.notEquals(annotation1, annotation2, 'expected unequal instances');
-    PrimitiveConstantValue value1 = annotation1.constant.value;
-    PrimitiveConstantValue value2 = annotation2.constant.value;
+    PrimitiveConstantValue value1 =
+        compiler.constants.getConstantValue(annotation1.constant);
+    PrimitiveConstantValue value2 =
+        compiler.constants.getConstantValue(annotation2.constant);
     Expect.identical(value1, value2, 'expected same compile-time constant');
     Expect.stringEquals('xyz', value1.primitiveValue.slowToString());
     Expect.stringEquals('xyz', value2.primitiveValue.slowToString());
@@ -89,7 +92,8 @@
     Expect.equals(1, length(element.metadata));
     PartialMetadataAnnotation annotation = element.metadata.head;
     annotation.ensureResolved(compiler);
-    PrimitiveConstantValue value = annotation.constant.value;
+    PrimitiveConstantValue value =
+        compiler.constants.getConstantValue(annotation.constant);
     Expect.stringEquals('xyz', value.primitiveValue.slowToString());
 
     checkPosition(annotation, annotation.cachedNode, source3, compiler);
@@ -118,8 +122,10 @@
     Expect.isFalse(identical(annotation1, annotation2),
                    'expected unique instances');
     Expect.notEquals(annotation1, annotation2, 'expected unequal instances');
-    PrimitiveConstantValue value1 = annotation1.constant.value;
-    PrimitiveConstantValue value2 = annotation2.constant.value;
+    PrimitiveConstantValue value1 =
+        compiler.constants.getConstantValue(annotation1.constant);
+    PrimitiveConstantValue value2 =
+        compiler.constants.getConstantValue(annotation2.constant);
     Expect.identical(value1, value2, 'expected same compile-time constant');
     Expect.stringEquals('xyz', value1.primitiveValue.slowToString());
     Expect.stringEquals('xyz', value2.primitiveValue.slowToString());
@@ -168,7 +174,8 @@
 
       PartialMetadataAnnotation annotation = metadata.head;
       annotation.ensureResolved(compiler);
-      PrimitiveConstantValue value = annotation.constant.value;
+      PrimitiveConstantValue value =
+          compiler.constants.getConstantValue(annotation.constant);
       Expect.stringEquals('xyz', value.primitiveValue.slowToString());
 
       checkPosition(annotation, annotation.cachedNode, source, compiler);
diff --git a/tests/compiler/dart2js/semantic_visitor_test.dart b/tests/compiler/dart2js/semantic_visitor_test.dart
index c9a487e..21ab642 100644
--- a/tests/compiler/dart2js/semantic_visitor_test.dart
+++ b/tests/compiler/dart2js/semantic_visitor_test.dart
@@ -168,38 +168,52 @@
 }

 

 const List<VisitKind> UNTESTABLE_KINDS = const <VisitKind>[

+  // A final field shadowing a non-final field is currently not supported in

+  // resolution.

+  VisitKind.VISIT_SUPER_FIELD_FIELD_COMPOUND,

+  VisitKind.VISIT_SUPER_FIELD_FIELD_PREFIX,

+  VisitKind.VISIT_SUPER_FIELD_FIELD_POSTFIX,

+  // Combination of method and setter with the same name is currently not

+  // supported by the element model.

   VisitKind.VISIT_STATIC_METHOD_SETTER_COMPOUND,

   VisitKind.VISIT_STATIC_METHOD_SETTER_PREFIX,

   VisitKind.VISIT_STATIC_METHOD_SETTER_POSTFIX,

   VisitKind.VISIT_TOP_LEVEL_METHOD_SETTER_COMPOUND,

   VisitKind.VISIT_TOP_LEVEL_METHOD_SETTER_PREFIX,

   VisitKind.VISIT_TOP_LEVEL_METHOD_SETTER_POSTFIX,

-  VisitKind.VISIT_SUPER_FIELD_FIELD_COMPOUND,

-  VisitKind.VISIT_SUPER_FIELD_FIELD_PREFIX,

-  VisitKind.VISIT_SUPER_FIELD_FIELD_POSTFIX,

   VisitKind.VISIT_SUPER_METHOD_SETTER_COMPOUND,

   VisitKind.VISIT_SUPER_METHOD_SETTER_PREFIX,

   VisitKind.VISIT_SUPER_METHOD_SETTER_POSTFIX,

+  // Invalid use of setters is currently reported through an erroneous element.

+  VisitKind.VISIT_STATIC_SETTER_INVOKE,

+  VisitKind.VISIT_STATIC_SETTER_GET,

+  VisitKind.VISIT_TOP_LEVEL_SETTER_GET,

+  VisitKind.VISIT_TOP_LEVEL_SETTER_INVOKE,

+  // The constant expressions of assignment to constant type literals cannot be

+  // handled the compile constant evaluator.

   VisitKind.VISIT_CLASS_TYPE_LITERAL_SET,

   VisitKind.VISIT_TYPEDEF_TYPE_LITERAL_SET,

-  VisitKind.VISIT_TYPE_VARIABLE_TYPE_LITERAL_SET,

   VisitKind.VISIT_DYNAMIC_TYPE_LITERAL_SET,

+  // Invalid assignments is currently report through an erroneous element.

+  VisitKind.VISIT_TYPE_VARIABLE_TYPE_LITERAL_SET,

   VisitKind.VISIT_FINAL_PARAMETER_SET,

   VisitKind.VISIT_FINAL_LOCAL_VARIABLE_SET,

   VisitKind.VISIT_LOCAL_FUNCTION_SET,

   VisitKind.VISIT_STATIC_GETTER_SET,

-  VisitKind.VISIT_STATIC_SETTER_GET,

-  VisitKind.VISIT_STATIC_SETTER_INVOKE,

   VisitKind.VISIT_FINAL_STATIC_FIELD_SET,

   VisitKind.VISIT_STATIC_FUNCTION_SET,

   VisitKind.VISIT_FINAL_TOP_LEVEL_FIELD_SET,

   VisitKind.VISIT_TOP_LEVEL_GETTER_SET,

-  VisitKind.VISIT_TOP_LEVEL_SETTER_GET,

-  VisitKind.VISIT_TOP_LEVEL_SETTER_INVOKE,

   VisitKind.VISIT_TOP_LEVEL_FUNCTION_SET,

   VisitKind.VISIT_FINAL_SUPER_FIELD_SET,

   VisitKind.VISIT_SUPER_GETTER_SET,

   VisitKind.VISIT_SUPER_METHOD_SET,

+  // The only undefined unary, `+`, is currently handled and skipped in the

+  // parser.

+  VisitKind.ERROR_UNDEFINED_UNARY_EXPRESSION,

+  // Constant expression are currently not computed during resolution.

+  VisitKind.VISIT_CONSTANT_GET,

+  VisitKind.VISIT_CONSTANT_INVOKE,

 ];

 

 main(List<String> arguments) {

@@ -245,7 +259,8 @@
                             m.simpleName != #apply)

               .map((m) => m.simpleName).toSet();

       symbols2.removeAll(symbols1);

-      print("Untested visit methods:\n  ${symbols2.join(',\n  ')},\n");

+      Expect.isTrue(symbols2.isEmpty,

+          "Untested visit methods:\n  ${symbols2.join(',\n  ')},\n");

     }

   ], (f) => f()));

 }

@@ -281,15 +296,13 @@
   sourceFiles['main.dart'] = mainSource.toString();

 

   Compiler compiler = compilerFor(sourceFiles,

-      options: ['--analyze-all', '--analyze-only']);

+      options: ['--analyze-all',

+                '--analyze-only',

+                '--enable-null-aware-operators']);

   return compiler.run(Uri.parse('memory:main.dart')).then((_) {

     testMap.forEach((String filename, Test test) {

       LibraryElement library = compiler.libraryLoader.lookupLibrary(

           Uri.parse('memory:$filename'));

-      var expectedVisits = test.expectedVisits;

-      if (expectedVisits is! List) {

-        expectedVisits = [expectedVisits];

-      }

       Element element;

       String cls = test.cls;

       String method = test.method;

@@ -302,6 +315,18 @@
                          "${library.compilationUnit.script.text}");

         element = classElement.localLookup(method);

       }

+      var expectedVisits = test.expectedVisits;

+      if (expectedVisits == null) {

+        Expect.isTrue(element.isErroneous,

+            "Element '$method' expected to be have parse errors in:\n"

+            "${library.compilationUnit.script.text}");

+        return;

+      } else if (expectedVisits is! List) {

+        expectedVisits = [expectedVisits];

+      }

+      Expect.isFalse(element.isErroneous,

+          "Element '$method' is not expected to be have parse errors in:\n"

+          "${library.compilationUnit.script.text}");

 

       void testAstElement(AstElement astElement) {

         Expect.isNotNull(astElement, "Element '$method' not found in:\n"

@@ -622,10 +647,15 @@
   VISIT_AS,

 

   VISIT_CONST_CONSTRUCTOR_INVOKE,

+  VISIT_BOOL_FROM_ENVIRONMENT_CONSTRUCTOR_INVOKE,

+  VISIT_INT_FROM_ENVIRONMENT_CONSTRUCTOR_INVOKE,

+  VISIT_STRING_FROM_ENVIRONMENT_CONSTRUCTOR_INVOKE,

   VISIT_GENERATIVE_CONSTRUCTOR_INVOKE,

   VISIT_REDIRECTING_GENERATIVE_CONSTRUCTOR_INVOKE,

   VISIT_FACTORY_CONSTRUCTOR_INVOKE,

   VISIT_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,

+  VISIT_CONSTRUCTOR_INCOMPATIBLE_INVOKE,

+  ERROR_NON_CONSTANT_CONSTRUCTOR_INVOKE,

 

   VISIT_SUPER_CONSTRUCTOR_INVOKE,

   VISIT_IMPLICIT_SUPER_CONSTRUCTOR_INVOKE,

@@ -661,5 +691,18 @@
   VISIT_UNRESOLVED_PREFIX,

   VISIT_UNRESOLVED_POSTFIX,

 

-  // TODO(johnniwinther): Add tests for more error cases.

+  VISIT_IF_NULL,

+  VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_GET,

+  VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_SET,

+  VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_INVOKE,

+  VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_COMPOUND,

+  VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_PREFIX,

+  VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_POSTFIX,

+

+  ERROR_INVALID_ASSERT,

+  ERROR_UNDEFINED_UNARY_EXPRESSION,

+  ERROR_UNDEFINED_BINARY_EXPRESSION,

+

+  VISIT_CONSTANT_GET,

+  VISIT_CONSTANT_INVOKE,

 }

diff --git a/tests/compiler/dart2js/semantic_visitor_test_decl_visitor.dart b/tests/compiler/dart2js/semantic_visitor_test_decl_visitor.dart
index d4d7600..253f1f3 100644
--- a/tests/compiler/dart2js/semantic_visitor_test_decl_visitor.dart
+++ b/tests/compiler/dart2js/semantic_visitor_test_decl_visitor.dart
@@ -480,149 +480,4 @@
     applyParameters(parameters, arg);

     apply(body, arg);

   }

-

-  @override

-  visitUnresolvedClassConstructorInvoke(

-      NewExpression node,

-      Element constructor,

-      MalformedType type,

-      NodeList arguments,

-      Selector selector,

-      arg) {

-    // TODO(johnniwinther): Test [type] and [selector].

-    visits.add(new Visit(

-        VisitKind.VISIT_UNRESOLVED_CLASS_CONSTRUCTOR_INVOKE,

-        arguments: arguments));

-    apply(arguments, arg);

-  }

-

-  @override

-  visitUnresolvedConstructorInvoke(

-      NewExpression node,

-      Element constructor,

-      DartType type,

-      NodeList arguments,

-      Selector selector,

-      arg) {

-    // TODO(johnniwinther): Test [type] and [selector].

-    visits.add(new Visit(

-        VisitKind.VISIT_UNRESOLVED_CONSTRUCTOR_INVOKE,

-        arguments: arguments));

-    apply(arguments, arg);

-  }

-

-  @override

-  visitConstConstructorInvoke(

-      NewExpression node,

-      ConstructedConstantExpression constant,

-      arg) {

-    visits.add(new Visit(VisitKind.VISIT_CONST_CONSTRUCTOR_INVOKE,

-                         constant: constant.getText()));

-  }

-

-  @override

-  visitFactoryConstructorInvoke(

-      NewExpression node,

-      ConstructorElement constructor,

-      InterfaceType type,

-      NodeList arguments,

-      CallStructure callStructure,

-      arg) {

-    visits.add(new Visit(

-        VisitKind.VISIT_FACTORY_CONSTRUCTOR_INVOKE,

-        element: constructor,

-        type: type,

-        arguments: arguments,

-        selector: callStructure));

-    apply(arguments, arg);

-  }

-

-  @override

-  visitGenerativeConstructorInvoke(

-      NewExpression node,

-      ConstructorElement constructor,

-      InterfaceType type,

-      NodeList arguments,

-      CallStructure callStructure,

-      arg) {

-    visits.add(new Visit(

-        VisitKind.VISIT_GENERATIVE_CONSTRUCTOR_INVOKE,

-        element: constructor,

-        type: type,

-        arguments: arguments,

-        selector: callStructure));

-    apply(arguments, arg);

-  }

-

-  @override

-  visitRedirectingFactoryConstructorInvoke(

-      NewExpression node,

-      ConstructorElement constructor,

-      InterfaceType type,

-      ConstructorElement effectiveTarget,

-      InterfaceType effectiveTargetType,

-      NodeList arguments,

-      CallStructure callStructure,

-      arg) {

-    visits.add(new Visit(

-        VisitKind.VISIT_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,

-        element: constructor,

-        type: type,

-        target: effectiveTarget,

-        targetType: effectiveTargetType,

-        arguments: arguments,

-        selector: callStructure));

-    apply(arguments, arg);

-  }

-

-  @override

-  visitRedirectingGenerativeConstructorInvoke(

-      NewExpression node,

-      ConstructorElement constructor,

-      InterfaceType type,

-      NodeList arguments,

-      CallStructure callStructure,

-      arg) {

-    visits.add(new Visit(

-        VisitKind.VISIT_REDIRECTING_GENERATIVE_CONSTRUCTOR_INVOKE,

-        element: constructor,

-        type: type,

-        arguments: arguments,

-        selector: callStructure));

-    apply(arguments, arg);

-  }

-

-  @override

-  visitAbstractClassConstructorInvoke(

-      NewExpression node,

-      ConstructorElement constructor,

-      InterfaceType type,

-      NodeList arguments,

-      CallStructure callStructure,

-      arg) {

-    visits.add(new Visit(

-        VisitKind.VISIT_ABSTRACT_CLASS_CONSTRUCTOR_INVOKE,

-        element: constructor,

-        type: type,

-        arguments: arguments,

-        selector: callStructure));

-    apply(arguments, arg);

-  }

-

-  @override

-  visitUnresolvedRedirectingFactoryConstructorInvoke(

-      NewExpression node,

-      ConstructorElement constructor,

-      InterfaceType type,

-      NodeList arguments,

-      CallStructure callStructure,

-      arg) {

-    visits.add(new Visit(

-        VisitKind.VISIT_UNRESOLVED_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,

-        element: constructor,

-        type: type,

-        arguments: arguments,

-        selector: callStructure));

-    apply(arguments, arg);

-  }

 }

diff --git a/tests/compiler/dart2js/semantic_visitor_test_send_data.dart b/tests/compiler/dart2js/semantic_visitor_test_send_data.dart
index 87eecc3..e99f58b 100644
--- a/tests/compiler/dart2js/semantic_visitor_test_send_data.dart
+++ b/tests/compiler/dart2js/semantic_visitor_test_send_data.dart
@@ -306,7 +306,7 @@
     const Test.clazz(

         '''

         class C {

-          static static get o => 42;

+          static get o => 42;

           m() { o = 42; }

         }

         ''',

@@ -316,7 +316,7 @@
     const Test.clazz(

         '''

         class C {

-          static static get o => 42;

+          static get o => 42;

           m() { C.o = 42; }

         }

         ''',

@@ -326,7 +326,7 @@
     const Test.prefix(

         '''

         class C {

-          static static get o => 42;

+          static get o => 42;

         }

         ''',

         'm() { p.C.o = 42; }',

@@ -1382,6 +1382,16 @@
         m() { assert(false); }

         ''',

         const Visit(VisitKind.VISIT_ASSERT, expression: 'false')),

+    const Test(

+        '''

+        m() { assert(); }

+        ''',

+        const Visit(VisitKind.ERROR_INVALID_ASSERT, arguments: '()')),

+    const Test(

+        '''

+        m() { assert(42, true); }

+        ''',

+        const Visit(VisitKind.ERROR_INVALID_ASSERT, arguments: '(42,true)')),

   ],

   'Logical and': const [

     // Logical and

@@ -1541,6 +1551,18 @@
         const Visit(VisitKind.VISIT_UNRESOLVED_SUPER_BINARY,

                     operator: '+',

                     right: '42')),

+    const Test(

+        '''

+        m() => 2 === 3;

+        ''',

+        const Visit(VisitKind.ERROR_UNDEFINED_BINARY_EXPRESSION,

+                    left: '2', operator: '===', right: '3')),

+    const Test(

+        '''

+        m() => 2 !== 3;

+        ''',

+        const Visit(VisitKind.ERROR_UNDEFINED_BINARY_EXPRESSION,

+                    left: '2', operator: '!==', right: '3')),

   ],

   'Index': const [

     // Index

@@ -1782,6 +1804,14 @@
         m() => !0;

         ''',

         const Visit(VisitKind.VISIT_NOT, expression: '0')),

+    const Test(

+        '''

+        m() => +false;

+        ''',

+        // TODO(johnniwinther): Should this be an

+        // ERROR_UNDEFINED_UNARY_EXPRESSION? Currently the parser just skips

+        // the `+`.

+        const []),

   ],

   'Index set': const [

     // Index set

@@ -1851,7 +1881,7 @@
     const Test(

         '''

         m() {

-          final a;

+          final a = 0;

           a += 42;

         }

         ''',

@@ -2125,7 +2155,7 @@
           var a;

         }

         class B extends A {

-          final a;

+          final a = 0;

         }

 

         class C extends B {

@@ -3089,6 +3119,44 @@
             constant: 'const Class(true, 42)')),

     const Test(

         '''

+        m() => const bool.fromEnvironment('foo');

+        ''',

+        const Visit(VisitKind.VISIT_BOOL_FROM_ENVIRONMENT_CONSTRUCTOR_INVOKE,

+            constant:

+                'const bool.fromEnvironment("foo")')),

+    const Test(

+        '''

+        m() => const bool.fromEnvironment('foo', defaultValue: true);

+        ''',

+        const Visit(VisitKind.VISIT_BOOL_FROM_ENVIRONMENT_CONSTRUCTOR_INVOKE,

+            constant: 'const bool.fromEnvironment("foo", defaultValue: true)')),

+    const Test(

+        '''

+        m() => const int.fromEnvironment('foo');

+        ''',

+        const Visit(VisitKind.VISIT_INT_FROM_ENVIRONMENT_CONSTRUCTOR_INVOKE,

+            constant: 'const int.fromEnvironment("foo")')),

+    const Test(

+        '''

+        m() => const String.fromEnvironment('foo');

+        ''',

+        const Visit(VisitKind.VISIT_STRING_FROM_ENVIRONMENT_CONSTRUCTOR_INVOKE,

+            constant:

+                'const String.fromEnvironment("foo")')),

+    const Test(

+        '''

+        class Class {

+          Class(a, b);

+        }

+        m() => const Class(true, 42);

+        ''',

+        const Visit(VisitKind.ERROR_NON_CONSTANT_CONSTRUCTOR_INVOKE,

+            element: 'generative_constructor(Class#)',

+            arguments: '(true,42)',

+            type: 'Class',

+            selector: 'CallStructure(arity=2)')),

+    const Test(

+        '''

         class Class {}

         m() => new Class();

         ''',

@@ -3123,6 +3191,16 @@
             selector: 'CallStructure(arity=2)')),

     const Test(

         '''

+        class Class {}

+        m() => new Class(true, 42);

+        ''',

+        const Visit(VisitKind.VISIT_CONSTRUCTOR_INCOMPATIBLE_INVOKE,

+            element: 'generative_constructor(Class#)',

+            arguments: '(true,42)',

+            type: 'Class',

+            selector: 'CallStructure(arity=2)')),

+    const Test(

+        '''

         class Class {

           Class(a, b) : this._(a, b);

           Class._(a, b);

@@ -3137,6 +3215,19 @@
     const Test(

         '''

         class Class {

+          Class() : this._(true, 42);

+          Class._(a, b);

+        }

+        m() => new Class(true, 42);

+        ''',

+        const Visit(VisitKind.VISIT_CONSTRUCTOR_INCOMPATIBLE_INVOKE,

+            element: 'generative_constructor(Class#)',

+            arguments: '(true,42)',

+            type: 'Class',

+            selector: 'CallStructure(arity=2)')),

+    const Test(

+        '''

+        class Class {

           factory Class(a, b) => new Class._(a, b);

           Class._(a, b);

         }

@@ -3149,6 +3240,19 @@
             selector: 'CallStructure(arity=2)')),

     const Test(

         '''

+        class Class {

+          factory Class() => new Class._(true, 42);

+          Class._(a, b);

+        }

+        m() => new Class(true, 42);

+        ''',

+        const Visit(VisitKind.VISIT_CONSTRUCTOR_INCOMPATIBLE_INVOKE,

+            element: 'function(Class#)',

+            arguments: '(true,42)',

+            type: 'Class',

+            selector: 'CallStructure(arity=2)')),

+    const Test(

+        '''

         class Class<T> {

           factory Class(a, b) = Class<int>.a;

           factory Class.a(a, b) = Class<Class<T>>.b;

@@ -3165,6 +3269,51 @@
             selector: 'CallStructure(arity=2)')),

     const Test(

         '''

+        class Class<T> {

+          factory Class(a) = Class<int>.a;

+          factory Class.a(a, [b]) = Class<Class<T>>.b;

+          Class.b(a, [b]);

+        }

+        m() => new Class<double>(true, 42);

+        ''',

+        const Visit(VisitKind.VISIT_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,

+            element: 'function(Class#)',

+            arguments: '(true,42)',

+            type: 'Class<double>',

+            target: 'generative_constructor(Class#b)',

+            targetType: 'Class<Class<int>>',

+            selector: 'CallStructure(arity=2)')),

+    const Test(

+        '''

+        class Class {

+          factory Class() = Class._;

+          Class._();

+        }

+        m() => new Class(true, 42);

+        ''',

+        const Visit(

+            VisitKind.VISIT_UNRESOLVED_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,

+            element: 'function(Class#)',

+            arguments: '(true,42)',

+            type: 'Class',

+            selector: 'CallStructure(arity=2)')),

+    const Test(

+        '''

+        class Class<T> {

+          factory Class(a, b) = Class<int>.a;

+          factory Class.a(a, b) = Class<Class<T>>.b;

+          Class.b(a);

+        }

+        m() => new Class<double>(true, 42);

+        ''',

+        const Visit(

+            VisitKind.VISIT_UNRESOLVED_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,

+            element: 'function(Class#)',

+            arguments: '(true,42)',

+            type: 'Class<double>',

+            selector: 'CallStructure(arity=2)')),

+    const Test(

+        '''

         class Class {

           Class(a, b);

         }

@@ -3248,4 +3397,116 @@
             type: 'Class',

             selector: 'CallStructure(arity=2)')),

   ],

+  'If not null expressions': const [

+    const Test(

+        '''

+        m(a) => a?.b;

+        ''',

+        const [

+          const Visit(

+              VisitKind.VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_GET,

+              receiver: 'a',

+              name: 'b'),

+          const Visit(

+              VisitKind.VISIT_PARAMETER_GET,

+              element: 'parameter(m#a)'),

+        ]),

+    const Test(

+        '''

+        m(a) => a?.b = 42;

+        ''',

+        const [

+          const Visit(

+              VisitKind.VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_SET,

+              receiver: 'a',

+              name: 'b',

+              rhs: '42'),

+          const Visit(

+              VisitKind.VISIT_PARAMETER_GET,

+              element: 'parameter(m#a)'),

+        ]),

+    const Test(

+        '''

+        m(a) => a?.b(42, true);

+        ''',

+        const [

+          const Visit(

+              VisitKind.VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_INVOKE,

+              receiver: 'a',

+              arguments: '(42,true)',

+              selector: 'Selector(call, b, arity=2)'),

+          const Visit(

+              VisitKind.VISIT_PARAMETER_GET,

+              element: 'parameter(m#a)'),

+        ]),

+    const Test(

+        '''

+        m(a) => ++a?.b;

+        ''',

+        const [

+          const Visit(

+              VisitKind.VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_PREFIX,

+              receiver: 'a',

+              getter: 'Selector(getter, b, arity=0)',

+              setter: 'Selector(setter, b, arity=1)',

+              operator: '++'),

+          const Visit(

+              VisitKind.VISIT_PARAMETER_GET,

+              element: 'parameter(m#a)'),

+        ]),

+    const Test(

+        '''

+        m(a) => a?.b--;

+        ''',

+        const [

+          const Visit(

+              VisitKind.VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_POSTFIX,

+              receiver: 'a',

+              getter: 'Selector(getter, b, arity=0)',

+              setter: 'Selector(setter, b, arity=1)',

+              operator: '--'),

+          const Visit(

+              VisitKind.VISIT_PARAMETER_GET,

+              element: 'parameter(m#a)'),

+        ]),

+    const Test(

+        '''

+        m(a) => a?.b *= 42;

+        ''',

+        const [

+          const Visit(

+              VisitKind.VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_COMPOUND,

+              receiver: 'a',

+              getter: 'Selector(getter, b, arity=0)',

+              setter: 'Selector(setter, b, arity=1)',

+              operator: '*=',

+              rhs: '42'),

+          const Visit(

+              VisitKind.VISIT_PARAMETER_GET,

+              element: 'parameter(m#a)'),

+        ]),

+    const Test(

+        '''

+        m(a, b) => a ?? b;

+        ''',

+        const [

+          const Visit(VisitKind.VISIT_IF_NULL,

+                      left: 'a', right: 'b'),

+          const Visit(

+              VisitKind.VISIT_PARAMETER_GET,

+              element: 'parameter(m#a)'),

+          const Visit(

+              VisitKind.VISIT_PARAMETER_GET,

+              element: 'parameter(m#b)'),

+       ]),

+    const Test(

+        '''

+        m(a) => a ??= 42;

+        ''',

+        const Visit(

+            VisitKind.VISIT_PARAMETER_COMPOUND,

+            element: 'parameter(m#a)',

+            operator: '??=',

+            rhs: '42')),

+  ],

 };

diff --git a/tests/compiler/dart2js/semantic_visitor_test_send_visitor.dart b/tests/compiler/dart2js/semantic_visitor_test_send_visitor.dart
index f5a3953..196df43 100644
--- a/tests/compiler/dart2js/semantic_visitor_test_send_visitor.dart
+++ b/tests/compiler/dart2js/semantic_visitor_test_send_visitor.dart
@@ -25,7 +25,16 @@
       Node expression,

       arg) {

     visits.add(new Visit(VisitKind.VISIT_ASSERT, expression: expression));

-    apply(expression, arg);

+    super.visitAssert(node, expression, arg);

+  }

+

+  @override

+  errorInvalidAssert(

+      Send node,

+      NodeList arguments,

+      arg) {

+    visits.add(new Visit(VisitKind.ERROR_INVALID_ASSERT, arguments: arguments));

+    super.errorInvalidAssert(node, arguments, arg);

   }

 

   @override

@@ -37,8 +46,19 @@
       arg) {

     visits.add(new Visit(VisitKind.VISIT_BINARY,

         left: left, operator: operator, right: right));

-    apply(left, arg);

-    apply(right, arg);

+    super.visitBinary(node, left, operator, right, arg);

+  }

+

+  @override

+  errorUndefinedBinaryExpression(

+      Send node,

+      Node left,

+      Operator operator,

+      Node right,

+      arg) {

+    visits.add(new Visit(VisitKind.ERROR_UNDEFINED_BINARY_EXPRESSION,

+        left: left, operator: operator, right: right));

+    super.errorUndefinedBinaryExpression(node, left, operator, right, arg);

   }

 

   @override

@@ -848,7 +868,18 @@
       arg) {

     visits.add(new Visit(VisitKind.VISIT_UNARY,

         expression: expression, operator: operator));

-    apply(expression, arg);

+    super.visitUnary(node, operator, expression, arg);

+  }

+

+  @override

+  errorUndefinedUnaryExpression(

+      Send node,

+      Operator operator,

+      Node expression,

+      arg) {

+    visits.add(new Visit(VisitKind.ERROR_UNDEFINED_UNARY_EXPRESSION,

+        expression: expression, operator: operator));

+    super.errorUndefinedUnaryExpression(node, operator, expression, arg);

   }

 

   @override

@@ -2338,6 +2369,70 @@
       arg) {

     visits.add(new Visit(VisitKind.VISIT_CONST_CONSTRUCTOR_INVOKE,

                          constant: constant.getText()));

+    super.visitConstConstructorInvoke(node, constant, arg);

+  }

+

+  @override

+  visitBoolFromEnvironmentConstructorInvoke(

+      NewExpression node,

+      BoolFromEnvironmentConstantExpression constant,

+      arg) {

+    visits.add(new Visit(

+        VisitKind.VISIT_BOOL_FROM_ENVIRONMENT_CONSTRUCTOR_INVOKE,

+        constant: constant.getText()));

+    super.visitBoolFromEnvironmentConstructorInvoke(node, constant, arg);

+  }

+

+  @override

+  visitIntFromEnvironmentConstructorInvoke(

+      NewExpression node,

+      IntFromEnvironmentConstantExpression constant,

+      arg) {

+    visits.add(new Visit(

+        VisitKind.VISIT_INT_FROM_ENVIRONMENT_CONSTRUCTOR_INVOKE,

+        constant: constant.getText()));

+    super.visitIntFromEnvironmentConstructorInvoke(node, constant, arg);

+  }

+

+  @override

+  visitStringFromEnvironmentConstructorInvoke(

+      NewExpression node,

+      StringFromEnvironmentConstantExpression constant,

+      arg) {

+    visits.add(new Visit(

+        VisitKind.VISIT_STRING_FROM_ENVIRONMENT_CONSTRUCTOR_INVOKE,

+        constant: constant.getText()));

+    super.visitStringFromEnvironmentConstructorInvoke(node, constant, arg);

+  }

+

+  @override

+  errorNonConstantConstructorInvoke(

+        NewExpression node,

+        Element element,

+        DartType type,

+        NodeList arguments,

+        CallStructure callStructure,

+        arg) {

+    visits.add(new Visit(VisitKind.ERROR_NON_CONSTANT_CONSTRUCTOR_INVOKE,

+        element: element, type: type,

+        arguments: arguments, selector: callStructure));

+    super.errorNonConstantConstructorInvoke(

+        node, element, type, arguments, callStructure, arg);

+  }

+

+  @override

+  visitConstructorIncompatibleInvoke(

+        NewExpression node,

+        ConstructorElement constructor,

+        InterfaceType type,

+        NodeList arguments,

+        CallStructure callStructure,

+        arg) {

+    visits.add(new Visit(VisitKind.VISIT_CONSTRUCTOR_INCOMPATIBLE_INVOKE,

+        element: constructor, type: type,

+        arguments: arguments, selector: callStructure));

+    super.visitConstructorIncompatibleInvoke(

+        node, constructor, type, arguments, callStructure, arg);

   }

 

   @override

@@ -2717,4 +2812,118 @@
     visits.add(new Visit(VisitKind.VISIT_UNRESOLVED_SUPER_SETTER_PREFIX,

         getter: getter, operator: operator));

   }

+

+  @override

+  visitIfNotNullDynamicPropertyGet(

+      Send node,

+      Node receiver,

+      Selector selector,

+      arg) {

+    visits.add(new Visit(VisitKind.VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_GET,

+        receiver: receiver, name: selector.name));

+    super.visitIfNotNullDynamicPropertyGet(node, receiver, selector, arg);

+  }

+

+  @override

+  visitIfNotNullDynamicPropertySet(

+      Send node,

+      Node receiver,

+      Selector selector,

+      Node rhs,

+      arg) {

+    visits.add(new Visit(VisitKind.VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_SET,

+        receiver: receiver, name: selector.name, rhs: rhs));

+    super.visitIfNotNullDynamicPropertySet(node, receiver, selector, rhs, arg);

+  }

+

+  @override

+  visitIfNotNullDynamicPropertyInvoke(

+      Send node,

+      Node receiver,

+      NodeList arguments,

+      Selector selector,

+      arg) {

+    visits.add(new Visit(VisitKind.VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_INVOKE,

+        receiver: receiver, selector: selector, arguments: arguments));

+    super.visitIfNotNullDynamicPropertyInvoke(

+        node, receiver, arguments, selector, arg);

+  }

+

+  @override

+  visitIfNotNullDynamicPropertyPrefix(

+      Send node,

+      Node receiver,

+      IncDecOperator operator,

+      Selector getterSelector,

+      Selector setterSelector,

+      arg) {

+    visits.add(new Visit(VisitKind.VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_PREFIX,

+        receiver: receiver, operator: operator,

+        getter: getterSelector, setter: setterSelector));

+    super.visitIfNotNullDynamicPropertyPrefix(

+        node, receiver, operator, getterSelector, setterSelector, arg);

+  }

+

+  @override

+  visitIfNotNullDynamicPropertyPostfix(

+      Send node,

+      Node receiver,

+      IncDecOperator operator,

+      Selector getterSelector,

+      Selector setterSelector,

+      arg) {

+    visits.add(new Visit(VisitKind.VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_POSTFIX,

+        receiver: receiver, operator: operator,

+        getter: getterSelector, setter: setterSelector));

+    super.visitIfNotNullDynamicPropertyPostfix(

+        node, receiver, operator, getterSelector, setterSelector, arg);

+  }

+

+  @override

+  visitIfNotNullDynamicPropertyCompound(

+      Send node,

+      Node receiver,

+      AssignmentOperator operator,

+      Node rhs,

+      Selector getterSelector,

+      Selector setterSelector,

+      arg) {

+    visits.add(new Visit(VisitKind.VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_COMPOUND,

+        receiver: receiver, operator: operator, rhs: rhs,

+        getter: getterSelector, setter: setterSelector));

+    super.visitIfNotNullDynamicPropertyCompound(

+        node, receiver, operator, rhs, getterSelector, setterSelector, arg);

+  }

+

+  @override

+  visitIfNull(

+      Send node,

+      Node left,

+      Node right,

+      arg) {

+    visits.add(new Visit(VisitKind.VISIT_IF_NULL, left: left, right: right));

+    super.visitIfNull(node, left, right, arg);

+  }

+

+  @override

+  visitConstantGet(

+      Send node,

+      ConstantExpression constant,

+      arg) {

+    visits.add(new Visit(VisitKind.VISIT_CONSTANT_GET,

+        constant: constant.getText()));

+    super.visitConstantGet(node, constant, arg);

+  }

+

+  @override

+  visitConstantInvoke(

+      Send node,

+      ConstantExpression constant,

+      NodeList arguments,

+      CallStructure callStructure,

+      arg) {

+    visits.add(new Visit(VisitKind.VISIT_CONSTANT_INVOKE,

+        constant: constant.getText()));

+    super.visitConstantInvoke(node, constant, arguments, callStructure, arg);

+  }

 }

diff --git a/tests/compiler/dart2js_extra/dart2js_extra.status b/tests/compiler/dart2js_extra/dart2js_extra.status
index 423c545..b848d9d 100644
--- a/tests/compiler/dart2js_extra/dart2js_extra.status
+++ b/tests/compiler/dart2js_extra/dart2js_extra.status
@@ -86,15 +86,13 @@
 conditional_send_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 constant_javascript_semantics2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 constant_javascript_semantics3_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-deferred/deferred_class_test: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred/deferred_constant2_test: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred/deferred_constant3_test: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred/deferred_constant4_test: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred/deferred_function_test: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred/deferred_mirrors1_test: Crash # (lazy.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred/deferred_overlapping_test: Crash # (lib1.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_fail_and_retry_test: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_fail_and_retry_worker_test: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
+deferred/deferred_class_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+deferred/deferred_constant2_test: RuntimeError # Please triage this failure.
+deferred/deferred_constant3_test: RuntimeError # Please triage this failure.
+deferred/deferred_constant4_test: RuntimeError # Please triage this failure.
+deferred/deferred_function_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+deferred/deferred_mirrors1_test: RuntimeError # Please triage this failure.
+deferred/deferred_overlapping_test: RuntimeError # Please triage this failure.
 generics_factories_test: Crash # Please triage this failure.
 inference_nsm_mirrors_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 inferrer_is_int_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index 477641c..97080cb 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -211,7 +211,6 @@
 
 [ $compiler == dart2js && $cps_ir ]
 apply2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-bool_from_environment_test: RuntimeError # Please triage this failure.
 collection_removes_test: RuntimeError # Please triage this failure.
 const_list_remove_range_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 const_list_set_range_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
@@ -235,7 +234,6 @@
 hash_set_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 hash_set_type_check_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 hashcode_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-int_from_environment_test: RuntimeError # Please triage this failure.
 int_parse_radix_test/01: Crash # Please triage this failure.
 int_parse_radix_test/02: Crash # Please triage this failure.
 int_parse_radix_test/none: Crash # Please triage this failure.
@@ -306,8 +304,6 @@
 splay_tree_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 string_buffer_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 string_codeunits_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-string_from_environment2_test: RuntimeError # Please triage this failure.
-string_from_environment_test: RuntimeError # Please triage this failure.
 string_fromcharcode_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 string_fromcharcodes_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 string_operations_with_null_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
diff --git a/tests/corelib/nan_infinity_test.dart b/tests/corelib/nan_infinity_test.dart
index 9496584..6957b05 100644
--- a/tests/corelib/nan_infinity_test.dart
+++ b/tests/corelib/nan_infinity_test.dart
@@ -54,7 +54,7 @@
   Expect.isFalse(identical(double.NAN, double.INFINITY));
   Expect.isFalse(identical(double.NAN, double.NEGATIVE_INFINITY));
   Expect.isFalse(identical(double.INFINITY, double.NEGATIVE_INFINITY));
-  Expect.isTrue(identical(double.NAN, -double.NAN));  /// 01: continued
+  Expect.isFalse(identical(double.NAN, -double.NAN));
   Expect.isTrue(identical(double.INFINITY, -double.NEGATIVE_INFINITY));
   Expect.isTrue(identical(double.NEGATIVE_INFINITY, -double.INFINITY));
 
diff --git a/tests/isolate/checked_test.dart b/tests/isolate/checked_test.dart
new file mode 100644
index 0000000..87f6a03
--- /dev/null
+++ b/tests/isolate/checked_test.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:isolate";
+import "dart:async";
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+
+void main([args, message]) {
+  if (message != null) return isolateMain(message);
+
+  bool isChecked = false;
+  assert((isChecked = true));
+  if (isChecked) return;  // Skip this test in checked mode.
+
+  var responses = {};
+  var port = new RawReceivePort();
+  port.handler = (pair) {
+    responses[pair[0]] = pair[1];
+    if (responses.length == 3) {
+      port.close();
+      Expect.isTrue(responses[true], "true @ $isChecked");
+      Expect.isTrue(responses[false], "false @ $isChecked");
+      Expect.isTrue(responses[null], "null @ $isChecked");
+    }
+  };
+  test(checked) {
+    Isolate.spawnUri(Uri.parse("checked_test.dart"), [],
+                     [checked, isChecked, port.sendPort],
+                     checked: checked);
+  }
+  test(true);
+  test(false);
+  test(null);
+}
+
+
+void isolateMain(args) {
+  var checkedFlag = args[0];
+  var parentIsChecked = args[1];
+  var responsePort = args[2];
+  bool isChecked = false;
+  assert((isChecked = true));
+  bool expected = checkedFlag;
+  if (checkedFlag == null) expected = parentIsChecked;
+  responsePort.send([checkedFlag, expected == isChecked]);
+}
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index 420d6a4..5c2a946 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -6,6 +6,9 @@
 browser/*: SkipByDesign  # Browser specific tests
 isolate_stress_test: Fail # Issue 12588: This should be able to pass when we have wrapper-less tests.
 
+[ $runtime != vm ]
+checked_test: Skip # Unsupported.
+
 [ $runtime == vm && $arch == mips && $mode == debug ]
 mandel_isolate_test: Skip # Uses 600 MB Ram on our 1 GB test device.
 
@@ -123,17 +126,15 @@
 package_root_test: SkipByDesign # Uses dart:io.
 
 [ $compiler == dart2js && $cps_ir ]
-bool_from_environment_default_value_test: RuntimeError # Please triage this failure.
 count_test: Crash # Instance of 'TypeOperator': type casts not implemented.
 cross_isolate_message_test: Crash #  Unhandled node
-deferred_in_isolate2_test: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
+deferred_in_isolate2_test: Crash # Instance of 'TypeOperator': type casts not implemented.
 function_send_test: Crash # (try {p.send(func);}finally {p.send(0);}): try/finally
 handle_error2_test: Crash #  Unhandled node
 handle_error3_test: Crash #  Unhandled node
 handle_error_test: Crash #  Unhandled node
 illegal_msg_function_test: Crash # Instance of 'TypeOperator': type casts not implemented.
 illegal_msg_mirror_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-int_from_environment_default_value_test: RuntimeError # Please triage this failure.
 isolate_complex_messages_test: Crash # Instance of 'TypeOperator': type casts not implemented.
 isolate_current_test: Crash #  Unhandled node
 mandel_isolate_test: Crash # Instance of 'TypeOperator': type casts not implemented.
@@ -158,6 +159,5 @@
 spawn_uri_multi_test/none: Crash # Instance of 'TypeOperator': type casts not implemented.
 stacktrace_message_test: Crash # Instance of 'TypeOperator': type casts not implemented.
 static_function_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-string_from_environment_default_value_test: RuntimeError # Please triage this failure.
 timer_isolate_test: Crash # Instance of 'TypeOperator': type casts not implemented.
 unresolved_ports_test: Crash # Instance of 'TypeOperator': type casts not implemented.
diff --git a/tests/isolate/message3_test.dart b/tests/isolate/message3_test.dart
index a29c8f9..c07a7e6 100644
--- a/tests/isolate/message3_test.dart
+++ b/tests/isolate/message3_test.dart
@@ -211,6 +211,8 @@
     Expect.isTrue(x is LinkedHashMap);
     Expect.listEquals(["foo", "bar"], x.keys.toList());
     Expect.listEquals([499, 32], x.values.toList());
+    Expect.equals(499, x["foo"]);
+    Expect.equals(32, x["bar"]);
     // Must be mutable.
     x["foo"] = 22;
     Expect.equals(22, x["foo"]);
@@ -219,6 +221,28 @@
     Expect.equals(499, x["gee"]);
   });
 
+  Map<String, int> mapWithRemovedKey = {"foo": 499, "bar": 32};
+  mapWithRemovedKey.remove("foo");
+  ping.send(mapWithRemovedKey);
+  checks.add((x) {
+    Expect.isTrue(x is LinkedHashMap);
+    Expect.listEquals(["bar"], x.keys.toList());
+    Expect.listEquals([32], x.values.toList());
+    Expect.equals(32, x["bar"]);
+  });
+
+  // Test map where a key does not define ==/hashCode.
+  Map<A, int> mapWithIdentityKey = new Map<A, int>();
+  mapWithIdentityKey[new A()] = 499;
+  ping.send(mapWithIdentityKey);
+  checks.add((x) {
+    Expect.isTrue(x is LinkedHashMap);
+    int value = x.values.first;
+    Expect.equals(499, value);
+    A key = x.keys.first;
+    Expect.equals(499, x[key]);
+  });
+
   ping.send({0: 499, 1: 32});
   checks.add((x) {
     Expect.isTrue(x is LinkedHashMap);
diff --git a/tests/language/bootstrap_test.dart b/tests/language/bootstrap_test.dart
index 747dbf9..ba4e802 100644
--- a/tests/language/bootstrap_test.dart
+++ b/tests/language/bootstrap_test.dart
@@ -1,8 +1,6 @@
 // Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
-// Dart test for testing binary operations.
-// VMOptions=--verify_implements  --check-function-fingerprints
 
 class BootstrapTest {
 
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 776f8f2..81ff460 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -19,6 +19,7 @@
 async_star_test: RuntimeError # Jsshell does not provide non-zero timers, Issue 7728
 
 [ $compiler == dart2js ]
+nan_identical_test: Fail # Issue 11551
 symbol_literal_test/*: Fail # Issue 21825
 constructor_duplicate_final_test/01: Fail # Issue 13363
 constructor_duplicate_final_test/02: Fail # Issue 13363
@@ -380,9 +381,9 @@
 cast_test/14: Crash # Instance of 'TypeOperator': type casts not implemented.
 cast_test/15: Crash # Instance of 'TypeOperator': type casts not implemented.
 cast_test/none: Crash # Instance of 'TypeOperator': type casts not implemented.
-cha_deopt1_test: Crash # (d.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-cha_deopt2_test: Crash # (d.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-cha_deopt3_test: Crash # (d.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
+cha_deopt1_test: RuntimeError # Please triage this failure.
+cha_deopt2_test: RuntimeError # Please triage this failure.
+cha_deopt3_test: RuntimeError # Please triage this failure.
 checked_null_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 checked_setter2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 checked_setter3_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
@@ -453,9 +454,7 @@
 constructor10_test/02: Crash # Please triage this failure.
 constructor11_test: Crash # Please triage this failure.
 constructor12_test: RuntimeError # Please triage this failure.
-constructor3_negative_test: Crash # Please triage this failure.
 constructor5_test: Crash # Please triage this failure.
-constructor_call_wrong_argument_count_negative_test: Crash # Please triage this failure.
 constructor_initializer_test/01: Crash # Please triage this failure.
 constructor_with_mixin_test: Crash # Please triage this failure.
 continue_test: Crash # (switch (0){case 0:i=22;continue;default:i=25;break;}): Unhandled node
@@ -464,59 +463,58 @@
 custom_await_stack_trace_test: Crash #  cannot handle async/sync*/async* functions
 deferred_call_empty_before_load_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 deferred_closurize_load_library_test: RuntimeError # Please triage this failure.
-deferred_constant_list_test: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_constraints_constants_test/constructor1: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_constraints_constants_test/constructor2: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_constraints_constants_test/default_argument1: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_constraints_constants_test/default_argument2: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_constraints_constants_test/metadata1: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_constraints_constants_test/metadata2: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_constraints_constants_test/metadata3: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_constraints_constants_test/none: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_constraints_constants_test/reference1: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_constraints_constants_test/reference2: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_constraints_constants_test/reference_after_load: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_constraints_type_annotation_test/as_operation: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_constraints_type_annotation_test/catch_check: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_constraints_type_annotation_test/is_check: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_constraints_type_annotation_test/new: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_constraints_type_annotation_test/new_before_load: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_constraints_type_annotation_test/new_generic1: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_constraints_type_annotation_test/new_generic2: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_constraints_type_annotation_test/new_generic3: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_constraints_type_annotation_test/none: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_constraints_type_annotation_test/static_method: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_constraints_type_annotation_test/type_annotation1: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_constraints_type_annotation_test/type_annotation_generic1: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_constraints_type_annotation_test/type_annotation_generic2: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_constraints_type_annotation_test/type_annotation_generic3: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_constraints_type_annotation_test/type_annotation_generic4: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_constraints_type_annotation_test/type_annotation_non_deferred: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_constraints_type_annotation_test/type_annotation_null: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_constraints_type_annotation_test/type_annotation_top_level: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_function_type_test: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_global_test: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
+deferred_constant_list_test: RuntimeError # Please triage this failure.
+deferred_constraints_constants_test/constructor1: Crash # (const lib.Const()): Unexpected constant kind null: null
+deferred_constraints_constants_test/constructor2: Crash # (const lib.Const.namedConstructor()): Unexpected constant kind null: null
+deferred_constraints_constants_test/default_argument1: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+deferred_constraints_constants_test/default_argument2: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+deferred_constraints_constants_test/metadata1: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+deferred_constraints_constants_test/metadata2: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+deferred_constraints_constants_test/metadata3: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+deferred_constraints_constants_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+deferred_constraints_constants_test/reference1: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+deferred_constraints_constants_test/reference2: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+deferred_constraints_constants_test/reference_after_load: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+deferred_constraints_type_annotation_test/as_operation: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+deferred_constraints_type_annotation_test/catch_check: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+deferred_constraints_type_annotation_test/is_check: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+deferred_constraints_type_annotation_test/new: RuntimeError # Please triage this failure.
+deferred_constraints_type_annotation_test/new_before_load: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+deferred_constraints_type_annotation_test/new_generic1: RuntimeError # Please triage this failure.
+deferred_constraints_type_annotation_test/new_generic2: RuntimeError # Please triage this failure.
+deferred_constraints_type_annotation_test/new_generic3: RuntimeError # Please triage this failure.
+deferred_constraints_type_annotation_test/none: RuntimeError # Please triage this failure.
+deferred_constraints_type_annotation_test/static_method: RuntimeError # Please triage this failure.
+deferred_constraints_type_annotation_test/type_annotation1: RuntimeError # Please triage this failure.
+deferred_constraints_type_annotation_test/type_annotation_generic1: RuntimeError # Please triage this failure.
+deferred_constraints_type_annotation_test/type_annotation_generic2: RuntimeError # Please triage this failure.
+deferred_constraints_type_annotation_test/type_annotation_generic3: RuntimeError # Please triage this failure.
+deferred_constraints_type_annotation_test/type_annotation_generic4: RuntimeError # Please triage this failure.
+deferred_constraints_type_annotation_test/type_annotation_non_deferred: RuntimeError # Please triage this failure.
+deferred_constraints_type_annotation_test/type_annotation_null: RuntimeError # Please triage this failure.
+deferred_constraints_type_annotation_test/type_annotation_top_level: RuntimeError # Please triage this failure.
+deferred_function_type_test: Crash # Instance of 'TypeOperator': type check unimplemented for F.
+deferred_global_test: RuntimeError # Please triage this failure.
 deferred_inheritance_constraints_test/redirecting_constructor: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-deferred_inlined_test: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_load_constants_test/01: Crash # (foo.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_load_constants_test/02: Crash # (foo.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_load_constants_test/03: Crash # (foo.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_load_constants_test/04: Crash # (foo.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_load_constants_test/05: Crash # (foo.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_load_constants_test/none: Crash # (foo.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_load_inval_code_test: Crash # (d.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_load_library_wrong_args_test/01: Crash # (lib.loadLibrary(10)): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_load_library_wrong_args_test/none: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_mixin_test: Crash # (lib1.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_no_such_method_test: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
+deferred_inlined_test: RuntimeError # Please triage this failure.
+deferred_load_constants_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+deferred_load_constants_test/02: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+deferred_load_constants_test/03: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+deferred_load_constants_test/04: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+deferred_load_constants_test/05: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+deferred_load_constants_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+deferred_load_inval_code_test: RuntimeError # Please triage this failure.
+deferred_load_library_wrong_args_test/none: RuntimeError # Please triage this failure.
+deferred_mixin_test: RuntimeError # Please triage this failure.
+deferred_no_such_method_test: RuntimeError # Please triage this failure.
 deferred_not_loaded_check_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-deferred_only_constant_test: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_optimized_test: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
+deferred_only_constant_test: RuntimeError # Please triage this failure.
+deferred_optimized_test: RuntimeError # Please triage this failure.
 deferred_redirecting_factory_test: Crash #  cannot handle async/sync*/async* functions
-deferred_regression_22995_test: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_shadow_load_library_test: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_shared_and_unshared_classes_test: Crash # (lib1.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-deferred_static_seperate_test: Crash # (lib1.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
+deferred_regression_22995_test: Crash # Instance of 'TypeOperator': type check unimplemented for Ti.
+deferred_shadow_load_library_test: RuntimeError # Please triage this failure.
+deferred_shared_and_unshared_classes_test: RuntimeError # Please triage this failure.
+deferred_static_seperate_test: RuntimeError # Please triage this failure.
 deopt_inlined_function_lazy_test: Crash # (try {return x+12342353257893275483274832;}finally {}): try/finally
 div_with_power_of_two2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 double_to_string_as_exponential2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
@@ -543,8 +541,6 @@
 execute_finally9_test: Crash #  try/finally
 factory_redirection3_cyclic_test/01: Crash # Please triage this failure.
 factory_redirection_test/04: Crash # Please triage this failure.
-factory_redirection_test/05: MissingRuntimeError # Please triage this failure.
-factory_redirection_test/06: MissingRuntimeError # Please triage this failure.
 factory_return_type_checked_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 factory_type_parameter2_test: Crash # Please triage this failure.
 factory_type_parameter_test: Crash # Please triage this failure.
@@ -725,7 +721,7 @@
 issue14014_3_test: Crash # Instance of 'TypeOperator': type check unimplemented for foo<T>.
 issue20476_test: Crash # (try {try {return 1;}catch (e1){}finally {return 3;}}catch (e2){}finally {return 5;}): try/finally
 issue7525_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-issue_1751477_test: Crash # (lib1.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
+issue_1751477_test: RuntimeError # Please triage this failure.
 label_test: Crash # (switch (i){case 111:while(doAgain()){break L;}default:i-- ;}): Unhandled node
 large_class_declaration_test: Crash # Please triage this failure.
 lazy_static3_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
@@ -758,8 +754,6 @@
 mixin_field_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 mixin_forwarding_constructor1_test: Crash # Please triage this failure.
 mixin_forwarding_constructor3_test: Crash # Please triage this failure.
-mixin_illegal_constructor_test/13: MissingRuntimeError # Please triage this failure.
-mixin_illegal_constructor_test/15: MissingRuntimeError # Please triage this failure.
 mixin_illegal_cycles_test/02: Crash # Please triage this failure.
 mixin_illegal_cycles_test/03: Crash # Please triage this failure.
 mixin_illegal_cycles_test/04: Crash # Please triage this failure.
@@ -796,13 +790,9 @@
 naming_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 nested_switch_label_test: Crash #  Unhandled node
 no_such_constructor2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-no_such_constructor_test/01: MissingRuntimeError # Please triage this failure.
 no_such_method_dispatcher_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 no_such_method_empty_selector_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 no_such_method_test: RuntimeError # Please triage this failure.
-non_const_super_negative_test: Crash # Please triage this failure.
-not_enough_positional_arguments_test/00: MissingRuntimeError # Please triage this failure.
-not_enough_positional_arguments_test/03: Crash # Please triage this failure.
 null_inline_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 null_no_such_method_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 null_test/01: Crash # Instance of 'TypeOperator': type casts not implemented.
@@ -847,7 +837,7 @@
 regress_18535_test: Crash # Please triage this failure.
 regress_21795_test: Crash # (try {foo(t);}finally {if(t==0){try {}catch (err,st){}}}): try/finally
 regress_22438_test: Crash #  cannot handle async/sync*/async* functions
-regress_22443_test: Crash # (D.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
+regress_22443_test: RuntimeError # Please triage this failure.
 regress_22445_test: Crash #  cannot handle async/sync*/async* functions
 regress_22579_test: Crash #  cannot handle async/sync*/async* functions
 regress_22700_test: Crash # Please triage this failure.
@@ -860,6 +850,7 @@
 regress_23500_test/01: Crash #  cannot handle async/sync*/async* functions
 regress_23500_test/02: Crash #  cannot handle async/sync*/async* functions
 regress_23500_test/none: Crash #  cannot handle async/sync*/async* functions
+regress_23537_test: Crash # try/finally
 reify_typevar_static_test/01: Crash # Please triage this failure.
 return_type_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 side_effect_throw_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
diff --git a/tests/language/nan_identical_test.dart b/tests/language/nan_identical_test.dart
new file mode 100644
index 0000000..b4bba9a
--- /dev/null
+++ b/tests/language/nan_identical_test.dart
@@ -0,0 +1,51 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for 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 a new statement by itself.
+// VMOptions=--optimization-counter-threshold=4 --no-use-osr
+
+import 'dart:typed_data';
+
+import "package:expect/expect.dart";
+
+double uint64toDouble(int i) {
+  var buffer = new Uint8List(8).buffer;
+  var bdata = new ByteData.view(buffer);
+  bdata.setUint64(0, i);
+  return bdata.getFloat64(0);
+}
+
+double createOtherNAN() {
+  return uint64toDouble((1 << 64) - 2);
+}
+
+main() {
+  var otherNAN = createOtherNAN();
+  for (int i = 0; i < 100; i++) {
+    Expect.isFalse(checkIdentical(double.NAN, -double.NAN));
+    Expect.isTrue(checkIdentical(double.NAN, double.NAN));
+    Expect.isTrue(checkIdentical(-double.NAN, -double.NAN));
+
+    Expect.isFalse(checkIdentical(otherNAN, -otherNAN));
+    Expect.isTrue(checkIdentical(otherNAN, otherNAN));
+    Expect.isTrue(checkIdentical(-otherNAN, -otherNAN));
+
+    var a = otherNAN;
+    var b = double.NAN;
+    Expect.isFalse(checkIdentical(a, b));
+    Expect.isFalse(checkIdentical(-a, -b));
+    Expect.isFalse(checkIdentical(-a, b));
+    Expect.isFalse(checkIdentical(a, -b));
+
+    a = -a;
+    Expect.isFalse(checkIdentical(a, b));
+    Expect.isFalse(checkIdentical(-a, -b));
+    Expect.isFalse(checkIdentical(-a, b));
+    Expect.isFalse(checkIdentical(a, -b));
+
+    Expect.isTrue(checkIdentical(-(-a), a));
+    Expect.isTrue(checkIdentical(-(-b), b));
+  }
+}
+
+checkIdentical(a, b) => identical(a, b);
\ No newline at end of file
diff --git a/tests/language/regress_23537_test.dart b/tests/language/regress_23537_test.dart
new file mode 100644
index 0000000..c8c6667
--- /dev/null
+++ b/tests/language/regress_23537_test.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+var d;
+
+test(a) {
+  while (true) {
+    try {
+      var b;
+      try {
+        for (int i = 0; i < 10; i++) {
+          // Closurizing i, a, and b, thus the return statement
+          // executes at context level 3, and the code in
+          // the finally blocks runs at context level 1 and 2.
+          return () => i + a + b;
+        }
+      } finally {
+        b = 10;
+        while (true) {
+          // Chain a new context.
+          var c = 5;
+          d = () => a + b + c;
+          break;
+        }
+      }
+    } finally {
+      a = 1;
+    }
+    break;
+  }
+}
+
+main() {
+  var c = test(0);
+  Expect.equals(11, c());
+  Expect.equals(16, d());
+}
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index b603b06..006ecc0 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -90,6 +90,7 @@
 mirrors/reflected_type_typedefs_test: RuntimeError # Issue 12607
 mirrors/reflected_type_typevars_test: RuntimeError # Issue 12607
 mirrors/relation_assignable_test: RuntimeError # Issue 6490
+mirrors/relation_assignable2_test: RuntimeError # Issue 6490
 mirrors/relation_subtype_test: RuntimeError # Issue 6490
 mirrors/repeated_private_anon_mixin_app_test: RuntimeError # Issue 14670
 mirrors/symbol_validation_test/01: RuntimeError # Issue 13597
@@ -406,9 +407,9 @@
 mirrors/constructors_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 mirrors/dart2js_mirrors_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 mirrors/declarations_type_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-mirrors/deferred_mirrors_metadata_test: Crash # (lib1.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-mirrors/deferred_mirrors_metatarget_test: Crash # (lib.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
-mirrors/deferred_mirrors_update_test: Crash # (l.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
+mirrors/deferred_mirrors_metadata_test: RuntimeError # Please triage this failure.
+mirrors/deferred_mirrors_metatarget_test: RuntimeError # Please triage this failure.
+mirrors/deferred_mirrors_update_test: RuntimeError # Please triage this failure.
 mirrors/deferred_type_test: Crash # Instance of 'TypeOperator': type casts not implemented.
 mirrors/delegate_call_through_getter_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 mirrors/delegate_test: RuntimeError # Please triage this failure.
@@ -491,10 +492,10 @@
 mirrors/libraries_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 mirrors/library_declarations_test/01: Crash # (=Superclass.inheritedNormalFactory;): Unhandled node
 mirrors/library_declarations_test/none: Crash # (=Superclass.inheritedNormalFactory;): Unhandled node
-mirrors/library_enumeration_deferred_loading_test: Crash # (other.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
+mirrors/library_enumeration_deferred_loading_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 mirrors/library_exports_hidden_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 mirrors/library_exports_shown_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/library_import_deferred_loading_test: Crash # (other.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
+mirrors/library_import_deferred_loading_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 mirrors/library_imports_bad_metadata_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 mirrors/library_imports_bad_metadata_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 mirrors/library_imports_deferred_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
@@ -624,7 +625,7 @@
 mirrors/type_variable_owner_test/01: Crash # Instance of 'TypeOperator': type casts not implemented.
 mirrors/type_variable_owner_test/none: Crash # Instance of 'TypeOperator': type casts not implemented.
 mirrors/typearguments_mirror_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/typedef_deferred_library_test: Crash # (def.loadLibrary()): handleStaticGetterInvoke: foreign: getter(loadLibrary)
+mirrors/typedef_deferred_library_test: RuntimeError # Please triage this failure.
 mirrors/typedef_reflected_type_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 mirrors/typedef_reflected_type_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 mirrors/unnamed_library_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index 35ada31..3f62300 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -194,7 +194,6 @@
 io/file_read_encoded_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 io/file_system_delete_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 io/file_system_links_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/file_system_watcher_test: Crash #  Unhandled node
 io/file_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
 io/file_typed_data_test: Crash # Please triage this failure.
 io/file_uri_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
diff --git a/third_party/pkg_tested/pkg_tested.status b/third_party/pkg_tested/pkg_tested.status
index f5502f2..e25c931 100644
--- a/third_party/pkg_tested/pkg_tested.status
+++ b/third_party/pkg_tested/pkg_tested.status
@@ -16,7 +16,6 @@
 pub/test/transformer/loads_a_diamond_transformer_dependency_graph_test: Pass, Slow
 
 [ $browser ]
-analyzer_cli/*: SkipByDesign # Uses dart:io.
 dart_style/*: SkipByDesign
 pub/*: SkipByDesign
 
@@ -29,8 +28,6 @@
 dart_style/test/formatter_test: Skip # The test controller does not take into account that tests take much longer in debug mode or on simulators/mips.
 
 [ $compiler == dart2js && $cps_ir ]
-analyzer_cli/test/error_test: Crash # (try {return fn(tempDir);}finally {new Directory(tempDir).deleteSync(recursive:true);}): try/finally
-analyzer_cli/test/options_test: Crash #  try/finally
 dart_style/test/command_line_test: Crash #  try/finally
 dart_style/test/formatter_test: Crash #  try/finally
 dart_style/test/io_test: Crash #  try/finally
diff --git a/tools/VERSION b/tools/VERSION
index 05c219c..4c22d07 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 1
 MINOR 11
 PATCH 0
-PRERELEASE 4
+PRERELEASE 5
 PRERELEASE_PATCH 0
diff --git a/tools/apps/update_homebrew/bin/update_homebrew.dart b/tools/apps/update_homebrew/bin/update_homebrew.dart
index dfdf41f..7e21db9 100644
--- a/tools/apps/update_homebrew/bin/update_homebrew.dart
+++ b/tools/apps/update_homebrew/bin/update_homebrew.dart
@@ -33,7 +33,8 @@
 
 final FILES = []..addAll(SDK_FILES)..addAll(DARTIUM_FILES);
 
-Future<String> getHash256(String channel, int revision, String download) async {
+Future<String> getHash256(
+    String channel, String revision, String download) async {
   var client = new http.Client();
   try {
     var api = new storage.StorageApi(client);
@@ -48,7 +49,7 @@
   }
 }
 
-Future<String> getVersion(String channel, int revision) async {
+Future<String> getVersion(String channel, String revision) async {
   var client = new http.Client();
   try {
     var api = new storage.StorageApi(client);
@@ -68,7 +69,16 @@
   var lines = await (new File('$repository/dart.rb')).readAsLines();
 
   for (var channel in CHANNELS) {
-    final regExp = new RegExp('channels/$channel/release/(\\d*)/sdk');
+    /// This RegExp between release/ and /sdk matches
+    /// * 1 digit followed by
+    /// * Any number of letters, numbers, dashes and dots
+    /// This covers both numeric- and version-formatted revisions
+    ///
+    /// Note: all of the regexp escape slashes `\` are double-escaped within the
+    /// Dart string
+    final regExp =
+        new RegExp('channels/$channel/release/(\\d[\\w\\d\\-\\.]*)/sdk');
+
     revisions[channel] =
         regExp.firstMatch(lines.firstWhere(regExp.hasMatch)).group(1);
   }
@@ -87,7 +97,7 @@
   return Future.wait(waitOn);
 }
 
-Future writeHomebrewInfo(String channel, int revision) async {
+Future writeHomebrewInfo(String channel, String revision) async {
   var revisions = {};
   var hashes = {};
 
diff --git a/tools/bots/cross-vm.py b/tools/bots/cross-vm.py
index bf09cb1..f11777e 100644
--- a/tools/bots/cross-vm.py
+++ b/tools/bots/cross-vm.py
@@ -70,7 +70,7 @@
   test_args = [sys.executable, test_py, '--progress=line', '--report',
                '--time', '--compiler=none', '--runtime=vm', '--write-debug-log',
                '--write-test-outcome-log', '--mode=' + mode, '--arch=' + arch,
-               '--exclude-suite=pkg,pkg_tested']
+               '--exclude-suite=pkg']
 
   revision = os.environ['BUILDBOT_GOT_REVISION']
   tarball = tarball_name(arch, mode, revision)
diff --git a/tools/bots/dart_sdk.py b/tools/bots/dart_sdk.py
index cbaecd6..c124c5d 100644
--- a/tools/bots/dart_sdk.py
+++ b/tools/bots/dart_sdk.py
@@ -187,6 +187,10 @@
   return bot.RunProcess(command)
 
 if __name__ == '__main__':
+  if CHANNEL != bot_utils.Channel.BLEEDING_EDGE:
+    # We always clobber the bot, to make sure releases are build from scratch
+    bot.Clobber(force=True)
+
   CreateUploadSDK()
   if BUILD_OS == 'linux':
     CreateUploadVersionFile()
diff --git a/tools/deps/dartium.deps/DEPS b/tools/deps/dartium.deps/DEPS
index 4f4f47f..b88d2f1 100644
--- a/tools/deps/dartium.deps/DEPS
+++ b/tools/deps/dartium.deps/DEPS
@@ -13,7 +13,7 @@
   "dartium_chromium_commit": "62a7524d4f71c9e0858d24b0aa1bbff3a2d09bff",
   "chromium_base_revision": "297060",
   "dartium_webkit_branch": "/blink/branches/dart/dartium",
-  "dartium_webkit_revision": "195544",
+  "dartium_webkit_revision": "196634",
 
   "args_tag": "@0.13.0",
   "barback_rev" : "@29ee90dbcf77cfd64632fa2797a4c8a4f29a4b51",
diff --git a/tools/dom/templates/html/dartium/svg_dartium.darttemplate b/tools/dom/templates/html/dartium/svg_dartium.darttemplate
index 408068f..faa3d4f 100644
--- a/tools/dom/templates/html/dartium/svg_dartium.darttemplate
+++ b/tools/dom/templates/html/dartium/svg_dartium.darttemplate
@@ -1,6 +1,14 @@
 // DO NOT EDIT
 // Auto-generated dart:svg library.
 
+/**
+ * Scalable Vector Graphics:
+ * Two-dimensional vector graphics with support for events and animation.
+ *
+ * For details about the features and syntax of SVG, a W3C standard,
+ * refer to the
+ * [Scalable Vector Graphics Specification](http://www.w3.org/TR/SVG/).
+ */
 library dart.dom.svg;
 
 import 'dart:async';
diff --git a/tools/dom/templates/html/dartium/web_audio_dartium.darttemplate b/tools/dom/templates/html/dartium/web_audio_dartium.darttemplate
index 2cf02e8..52ed27d 100644
--- a/tools/dom/templates/html/dartium/web_audio_dartium.darttemplate
+++ b/tools/dom/templates/html/dartium/web_audio_dartium.darttemplate
@@ -1,6 +1,9 @@
 // DO NOT EDIT
 // Auto-generated dart:audio library.
 
+/**
+ * High-fidelity audio programming in the browser.
+ */
 library dart.dom.web_audio;
 
 import 'dart:async';
diff --git a/tools/dom/templates/html/dartium/web_gl_dartium.darttemplate b/tools/dom/templates/html/dartium/web_gl_dartium.darttemplate
index bced666..86c642c 100644
--- a/tools/dom/templates/html/dartium/web_gl_dartium.darttemplate
+++ b/tools/dom/templates/html/dartium/web_gl_dartium.darttemplate
@@ -1,6 +1,9 @@
 // DO NOT EDIT
 // Auto-generated dart:web_gl library.
 
+/**
+ * 3D programming in the browser.
+ */
 library dart.dom.web_gl;
 
 import 'dart:async';
diff --git a/tools/task_kill.py b/tools/task_kill.py
index 457e45f..a091164 100755
--- a/tools/task_kill.py
+++ b/tools/task_kill.py
@@ -172,7 +172,9 @@
 
 def KillBrowsers():
   status = Kill('firefox')
-  status += Kill('chrome')
+  # We don't give error on killing chrome. It happens quite often that the
+  # browser controller fails in killing chrome, so we silently do it here.
+  Kill('chrome')
   status += Kill('iexplore')
   status += Kill('safari')
   status += Kill('content_shell')
diff --git a/tools/testing/dart/test_options.dart b/tools/testing/dart/test_options.dart
index a33224a..ca0adad 100644
--- a/tools/testing/dart/test_options.dart
+++ b/tools/testing/dart/test_options.dart
@@ -14,8 +14,7 @@
 const List<String> defaultTestSelectors =
     const ['samples', 'standalone', 'corelib', 'co19', 'language',
            'isolate', 'vm', 'html', 'benchmark_smoke',
-           'utils', 'lib', 'pkg', 'analyze_library', 'service',
-           'pkg_tested'];
+           'utils', 'lib', 'pkg', 'analyze_library', 'service'];
 
 /**
  * Specification of a single test option.
@@ -348,13 +347,6 @@
               false,
               type: 'bool'),
           new _TestOptionSpecification(
-              'clear_safari_cache',
-              'Clear the safari cache (i.e., delete it).',
-              ['--clear_safari_cache'],
-              [],
-              false,
-              type: 'bool'),
-          new _TestOptionSpecification(
               'clear_browser_cache',
               'Browser specific clearing of caches(i.e., delete it).',
               ['--clear_browser_cache'],
@@ -724,12 +716,6 @@
     // Allow suppression that is valid for all ie versions
     configuration['ie'] = runtime.startsWith('ie');
 
-    // Temporary grace period for clear_safaci_cache
-    // See issue 18478
-    if (configuration['clear_safari_cache']) {
-      configuration['clear_browser_cache'] = true;
-    }
-
     // Expand the test selectors into a suite name and a simple
     // regular expressions to be used on the full path of a test file
     // in that test suite. If no selectors are explicitly given use
diff --git a/utils/dartanalyzer/dartanalyzer.gyp b/utils/dartanalyzer/dartanalyzer.gyp
index fa15434..3b4f5de 100644
--- a/utils/dartanalyzer/dartanalyzer.gyp
+++ b/utils/dartanalyzer/dartanalyzer.gyp
@@ -18,7 +18,7 @@
             '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)dart<(EXECUTABLE_SUFFIX)',
             '../../sdk/lib/_internal/libraries.dart',
             '<(SHARED_INTERMEDIATE_DIR)/packages.stamp',
-            '<!@(["python", "../../tools/list_files.py", "\\.dart$", "../../third_party/pkg_tested/analyzer_cli"])',
+            '<!@(["python", "../../tools/list_files.py", "\\.dart$", "../../third_party/pkg/analyzer_cli"])',
           ],
           'outputs': [
             '<(SHARED_INTERMEDIATE_DIR)/dartanalyzer.dart.snapshot',
@@ -27,7 +27,7 @@
             '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)dart<(EXECUTABLE_SUFFIX)',
             '--snapshot=<(SHARED_INTERMEDIATE_DIR)/dartanalyzer.dart.snapshot',
             '--package-root=<(PRODUCT_DIR)/packages/',
-            '../../third_party/pkg_tested/analyzer_cli/bin/analyzer.dart',
+            '../../third_party/pkg/analyzer_cli/bin/analyzer.dart',
           ],
         },
       ],