Version 1.20.0-dev.8.0

Merge commit 'ce596133ad507f3fe118c4c79a2b909bac0f0f6a' into dev
diff --git a/.gn b/.gn
new file mode 100644
index 0000000..fc54abe
--- /dev/null
+++ b/.gn
@@ -0,0 +1,14 @@
+# Copyright 2016 The Dart project authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This file is used by the gn meta-buildsystem find the root of the source tree
+# and to set startup options.
+
+# The location of the build configuration file.
+buildconfig = "//build/config/BUILDCONFIG.gn"
+
+# The secondary source root is a parallel directory tree where
+# GN build files are placed when they can not be placed directly
+# in the source tree, e.g. for third party source trees.
+secondary_source = "//build/secondary/"
diff --git a/.travis.yml b/.travis.yml
index 1424eaf..1a877df 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -70,6 +70,7 @@
     - env: TEST=node
     - env: ANALYZER=master DDC_BROWSERS=Firefox
     - env: ANALYZER=master CXX=clang++
+    - env: ANALYZER=master CXX=g++
 notifications:
   email:
     recipients:
diff --git a/BUILD.gn b/BUILD.gn
new file mode 100644
index 0000000..d86d84a
--- /dev/null
+++ b/BUILD.gn
@@ -0,0 +1,21 @@
+# Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+# This target will be built if no target is specified when invoking ninja.
+group("default") {
+  deps = [
+    ":runtime",
+  ]
+}
+
+group("runtime") {
+  deps = [
+    "//runtime/bin:dart",
+    "//runtime/bin:dart_bootstrap($host_toolchain)",
+    "//runtime/bin:run_vm_tests",
+    "//runtime/bin:process_test",
+    "//runtime/bin:test_extension",
+    "//runtime/bin:sample_extension",
+  ]
+}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cef042e..4285fc9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -23,6 +23,7 @@
   directory containing root certificate files hashed using `c_rehash`.
 
 ### Core library changes
+
 * `dart:core`: Remove deprecated `Resource` class.
   Use the class in `package:resource` instead.
 * `dart:async`
@@ -107,14 +108,12 @@
     class C extends A {}
     ```
 
-* Breaking change - ingore `dynamic` when doing inference.
+### Tool changes
 
-    ```dart
-    main() {
-      dynamic d = 42;
-      List<int> list = /*infer <int>*/[123, /*implicit cast*/d];
-    }
-    ```
+* `dartfmt` - upgraded to v0.2.10
+    * Don't crash on annotations before parameters with trailing commas.
+    * Always split enum declarations if they end in a trailing comma.
+    * Add `--set-exit-if-changed` to set the exit code on a change.
 
 ## 1.19.0
 
diff --git a/DEPS b/DEPS
index f2fc204..0c56803 100644
--- a/DEPS
+++ b/DEPS
@@ -30,8 +30,7 @@
   "gyp_rev": "@6ee91ad8659871916f9aa840d42e1513befdf638",
   "co19_rev": "@d4767b4caea3c5828ad8e053cd051d44a59061af",
 
-  # Revisions of GN/Mojo/Flutter related dependencies.
-  "base_revision": "@672b04e54b937ec899429a6bd5409c5a6300d151",
+  # Revisions of GN related dependencies.
   "buildtools_revision": "@565d04e8741429fb1b4f26d102f2c6c3b849edeb",
 
   "gperftools_revision": "@7822b5b0b9fa7e016e1f6b46ea86f26f4691a457",
@@ -45,11 +44,11 @@
   "barback_tag" : "@0.15.2+9",
   "bazel_worker_tag": "@0.1.1",
   "boolean_selector_tag" : "@1.0.2",
-  "boringssl_gen_rev": "@e3a1b341a3890ab10d372dc2fe6d1c6798828293",
+  "boringssl_gen_rev": "@1e8e5da213d0d5b1d50fcc1356c4783091bcc20d",
   "boringssl_rev" : "@8d343b44bbab829d1a28fdef650ca95f7db4412e",
   "charcode_tag": "@1.1.0",
   "chrome_rev" : "@19997",
-  "cli_util_tag" : "@0.0.1+2",
+  "cli_util_tag" : "@0.0.1+3",
   "code_transformers_tag": "@v0.4.2+3",
   "collection_tag": "@1.9.1",
   "convert_tag": "@2.0.1",
@@ -57,7 +56,7 @@
   "csslib_tag" : "@0.13.2",
   "dart2js_info_tag" : "@0.2.7+1",
   "dart_services_rev" : "@7aea2574e6f3924bf409a80afb8ad52aa2be4f97",
-  "dart_style_tag": "@0.2.9+1",
+  "dart_style_tag": "@0.2.10",
   "dartdoc_tag" : "@v0.9.7+3",
   "fixnum_tag": "@0.10.5",
   "func_tag": "@0.1.0",
@@ -73,8 +72,8 @@
   "isolate_tag": "@0.2.3",
   "jinja2_rev": "@2222b31554f03e62600cd7e383376a7c187967a1",
   "json_rpc_2_tag": "@2.0.2",
-  "kernel_rev": "@9677d68402ea15d0eca6430d64f631bb3e505499",
-  "linter_tag": "@0.1.26",
+  "kernel_rev": "@449803b82e850a41148e636db1a6e4a848284aed",
+  "linter_tag": "@0.1.27",
   "logging_tag": "@0.11.3+1",
   "markdown_rev": "@4aaadf3d940bb172e1f6285af4d2b1710d309982",
   "matcher_tag": "@0.12.0+2",
@@ -92,7 +91,7 @@
   "pool_tag": "@1.2.4",
   "protobuf_tag": "@0.5.3",
   "pub_cache_tag": "@v0.1.0",
-  "pub_rev": "@101aa44a4aebaefd0796ce44e6d155cd79fe2db4",
+  "pub_rev": "@4ef3e3e8ad8089733d617505cc66fa3d8049b4ae",
   "pub_semver_tag": "@1.3.0",
   "quiver_tag": "@0.22.0",
   "resource_rev":"@a49101ba2deb29c728acba6fb86000a8f730f4b1",
@@ -131,11 +130,7 @@
   Var("dart_root") + "/third_party/gyp":
       Var('chromium_git') + '/external/gyp.git' + Var("gyp_rev"),
 
-  # Stuff needed for GN/Mojo/Flutter.
-  Var("dart_root") + "/base":
-     Var('chromium_git') + '/external/github.com/domokit/base'
-     + Var('base_revision'),
-
+  # Stuff needed for GN build.
   Var("dart_root") + "/buildtools":
      Var('chromium_git') + '/chromium/buildtools.git' +
      Var('buildtools_revision'),
@@ -363,6 +358,83 @@
 # TODO(iposva): Move the necessary tools so that hooks can be run
 # without the runtime being available.
 hooks = [
+  # Pull GN binaries. This needs to be before running GYP below.
+  {
+    'name': 'gn_linux64',
+    'pattern': '.',
+    'action': [
+      'download_from_google_storage',
+      '--no_auth',
+      '--no_resume',
+      '--quiet',
+      '--platform=linux*',
+      '--bucket',
+      'chromium-gn',
+      '-s',
+      Var('dart_root') + '/buildtools/linux64/gn.sha1',
+    ],
+  },
+  {
+    'name': 'gn_mac',
+    'pattern': '.',
+    'action': [
+      'download_from_google_storage',
+      '--no_auth',
+      '--no_resume',
+      '--quiet',
+      '--platform=darwin',
+      '--bucket',
+      'chromium-gn',
+      '-s',
+      Var('dart_root') + '/buildtools/mac/gn.sha1',
+    ],
+  },
+  {
+    'name': 'gn_win',
+    'pattern': '.',
+    'action': [
+      'download_from_google_storage',
+      '--no_auth',
+      '--no_resume',
+      '--quiet',
+      '--platform=win*',
+      '--bucket',
+      'chromium-gn',
+      '-s',
+      Var('dart_root') + '/buildtools/win/gn.exe.sha1',
+    ],
+  },
+  # Pull clang-format binaries using checked-in hashes.
+  {
+    'name': 'clang_format_linux',
+    'pattern': '.',
+    'action': [
+      'download_from_google_storage',
+      '--no_auth',
+      '--no_resume',
+      '--quiet',
+      '--platform=linux*',
+      '--bucket',
+      'chromium-clang-format',
+      '-s',
+      Var('dart_root') + '/buildtools/linux64/clang-format.sha1',
+    ],
+  },
+  {
+    'name': 'clang_format_mac',
+    'pattern': '.',
+    'action': [
+      'download_from_google_storage',
+      '--no_auth',
+      '--no_resume',
+      '--quiet',
+      '--platform=darwin',
+      '--bucket',
+      'chromium-clang-format',
+      '-s',
+      Var('dart_root') + '/buildtools/mac/clang-format.sha1',
+    ],
+  },
   {
     'name': 'd8_testing_binaries',
     'pattern': '.',
@@ -498,6 +570,12 @@
     ],
   },
   {
+    # Pull clang if needed or requested via GYP_DEFINES.
+    'name': 'gn_clang',
+    'pattern': '.',
+    'action': ['python', 'sdk/tools/clang/scripts/update.py', '--if-needed'],
+  },
+  {
     "pattern": ".",
     "action": ["python", Var("dart_root") + "/tools/gyp_dart.py"],
   },
diff --git a/build/config/BUILD.gn b/build/config/BUILD.gn
index 0af90cd..93243a1 100644
--- a/build/config/BUILD.gn
+++ b/build/config/BUILD.gn
@@ -2,433 +2,23 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/config/allocator.gni")
-import("//build/config/chrome_build.gni")
-import("//build/config/crypto.gni")
-import("//build/config/features.gni")
-import("//build/config/ui.gni")
-import("//build/module_args/v8.gni")
-
-declare_args() {
-  # When set, turns off the (normally-on) iterator debugging and related stuff
-  # that is normally turned on for Debug builds. These are generally useful for
-  # catching bugs but in some cases may cause conflicts or excessive slowness.
-  disable_iterator_debugging = false
-
-  # Set to true to not store any build metadata, e.g. ifdef out all __DATE__
-  # and __TIME__. Set to 0 to reenable the use of these macros in the code
-  # base. See http://crbug.com/314403.
-  #
-  # Continue to embed build meta data in Official builds, basically the
-  # time it was built.
-  # TODO(maruel): This decision should be revisited because having an
-  # official deterministic build has high value too but MSVC toolset can't
-  # generate anything deterministic with WPO enabled AFAIK.
-  dont_embed_build_metadata = !is_official_build
-
-  # Set to true to enable dcheck in Release builds.
-  dcheck_always_on = false
-
-  # Set to true to compile with the OpenGL ES 2.0 conformance tests.
-  internal_gles2_conform_tests = false
-}
-
-# TODO(brettw) Most of these should be removed. Instead of global feature
-# flags, we should have more modular flags that apply only to a target and its
-# dependents. For example, depending on the "x11" meta-target should define
-# USE_X11 for all dependents so that everything that could use X11 gets the
-# define, but anything that doesn't depend on X11 doesn't see it.
-#
-# For now we define these globally to match the current GYP build.
-config("feature_flags") {
-  # TODO(brettw) this probably needs to be parameterized.
-  defines = [ "V8_DEPRECATION_WARNINGS" ]  # Don't use deprecated V8 APIs anywhere.
-
-  if (cld_version > 0) {
-    defines += [ "CLD_VERSION=$cld_version" ]
-  }
-  if (enable_mdns) {
-    defines += [ "ENABLE_MDNS=1" ]
-  }
-  if (enable_notifications) {
-    defines += [ "ENABLE_NOTIFICATIONS" ]
-  }
-  if (enable_pepper_cdms) {
-    # TODO(brettw) should probably be "=1"
-    defines += [ "ENABLE_PEPPER_CDMS" ]
-  }
-  if (enable_browser_cdms) {
-    # TODO(brettw) should probably be "=1"
-    defines += [ "ENABLE_BROWSER_CDMS" ]
-  }
-  if (enable_plugins) {
-    defines += [ "ENABLE_PLUGINS=1" ]
-  }
-  if (enable_basic_printing || enable_print_preview) {
-    # Convenience define for ENABLE_BASIC_PRINTING || ENABLE_PRINT_PREVIEW.
-    defines += [ "ENABLE_PRINTING=1" ]
-    if (enable_basic_printing) {
-      # Enable basic printing support and UI.
-      defines += [ "ENABLE_BASIC_PRINTING=1" ]
-    }
-    if (enable_print_preview) {
-      # Enable printing with print preview.
-      # Can be defined without ENABLE_BASIC_PRINTING.
-      defines += [ "ENABLE_PRINT_PREVIEW=1" ]
-    }
-  }
-  if (enable_spellcheck) {
-    defines += [ "ENABLE_SPELLCHECK=1" ]
-  }
-  if (use_platform_spellchecker) {
-    defines += [ "USE_PLATFORM_SPELLCHECKER=1" ]
-  }
-  if (dont_embed_build_metadata) {
-    defines += [ "DONT_EMBED_BUILD_METADATA" ]
-  }
-  if (dcheck_always_on) {
-    defines += [ "DCHECK_ALWAYS_ON=1" ]
-  }
-  if (use_udev) {
-    # TODO(brettw) should probably be "=1".
-    defines += [ "USE_UDEV" ]
-  }
-  if (ui_compositor_image_transport) {
-    # TODO(brettw) should probably be "=1".
-    defines += [ "UI_COMPOSITOR_IMAGE_TRANSPORT" ]
-  }
-  if (use_ash) {
-    defines += [ "USE_ASH=1" ]
-  }
-  if (use_aura) {
-    defines += [ "USE_AURA=1" ]
-  }
-  if (use_glfw) {
-    defines += [ "USE_GLFW=1" ]
-  }
-  if (use_pango) {
-    defines += [ "USE_PANGO=1" ]
-  }
-  if (use_cairo) {
-    defines += [ "USE_CAIRO=1" ]
-  }
-  if (use_clipboard_aurax11) {
-    defines += [ "USE_CLIPBOARD_AURAX11=1" ]
-  }
-  if (use_default_render_theme) {
-    defines += [ "USE_DEFAULT_RENDER_THEME=1" ]
-  }
-  if (use_openssl) {
-    defines += [ "USE_OPENSSL=1" ]
-  }
-  if (use_openssl_certs) {
-    defines += [ "USE_OPENSSL_CERTS=1" ]
-  }
-  if (use_nss_certs) {
-    defines += [ "USE_NSS_CERTS=1" ]
-  }
-  if (use_ozone) {
-    defines += [ "USE_OZONE=1" ]
-  }
-  if (use_x11) {
-    defines += [ "USE_X11=1" ]
-  }
-  if (use_allocator != "tcmalloc") {
-    defines += [ "NO_TCMALLOC" ]
-  }
-  if (is_asan || is_lsan || is_tsan || is_msan || is_ios) {
-    defines += [
-      "MEMORY_TOOL_REPLACES_ALLOCATOR",
-      "MEMORY_SANITIZER_INITIAL_SIZE",
-    ]
-  }
-  if (is_asan) {
-    defines += [ "ADDRESS_SANITIZER" ]
-  }
-  if (is_lsan) {
-    defines += [
-      "LEAK_SANITIZER",
-      "WTF_USE_LEAK_SANITIZER=1",
-    ]
-  }
-  if (is_tsan) {
-    defines += [
-      "THREAD_SANITIZER",
-      "DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL=1",
-      "WTF_USE_DYNAMIC_ANNOTATIONS_NOIMPL=1",
-    ]
-  }
-  if (is_msan) {
-    defines += [ "MEMORY_SANITIZER" ]
-  }
-  if (enable_webrtc) {
-    defines += [ "ENABLE_WEBRTC=1" ]
-  }
-  if (disable_ftp_support) {
-    defines += [ "DISABLE_FTP_SUPPORT=1" ]
-  }
-  if (!enable_nacl) {
-    defines += [ "DISABLE_NACL" ]
-  }
-  if (enable_extensions) {
-    defines += [ "ENABLE_EXTENSIONS=1" ]
-  }
-  if (enable_configuration_policy) {
-    defines += [ "ENABLE_CONFIGURATION_POLICY" ]
-  }
-  if (enable_task_manager) {
-    defines += [ "ENABLE_TASK_MANAGER=1" ]
-  }
-  if (enable_themes) {
-    defines += [ "ENABLE_THEMES=1" ]
-  }
-  if (enable_captive_portal_detection) {
-    defines += [ "ENABLE_CAPTIVE_PORTAL_DETECTION=1" ]
-  }
-  if (enable_session_service) {
-    defines += [ "ENABLE_SESSION_SERVICE=1" ]
-  }
-  if (enable_rlz) {
-    defines += [ "ENABLE_RLZ" ]
-  }
-  if (enable_plugin_installation) {
-    defines += [ "ENABLE_PLUGIN_INSTALLATION=1" ]
-  }
-  if (enable_app_list) {
-    defines += [ "ENABLE_APP_LIST=1" ]
-  }
-  if (enable_settings_app) {
-    defines += [ "ENABLE_SETTINGS_APP=1" ]
-  }
-  if (enable_supervised_users) {
-    defines += [ "ENABLE_SUPERVISED_USERS=1" ]
-  }
-  if (enable_service_discovery) {
-    defines += [ "ENABLE_SERVICE_DISCOVERY=1" ]
-  }
-  if (enable_autofill_dialog) {
-    defines += [ "ENABLE_AUTOFILL_DIALOG=1" ]
-  }
-  if (enable_wifi_bootstrapping) {
-    defines += [ "ENABLE_WIFI_BOOTSTRAPPING=1" ]
-  }
-  if (enable_image_loader_extension) {
-    defines += [ "IMAGE_LOADER_EXTENSION=1" ]
-  }
-  if (enable_remoting) {
-    defines += [ "ENABLE_REMOTING=1" ]
-  }
-  if (enable_google_now) {
-    defines += [ "ENABLE_GOOGLE_NOW=1" ]
-  }
-  if (enable_one_click_signin) {
-    defines += [ "ENABLE_ONE_CLICK_SIGNIN" ]
-  }
-  if (enable_hidpi) {
-    defines += [ "ENABLE_HIDPI=1" ]
-  }
-  if (enable_topchrome_md) {
-    defines += [ "ENABLE_TOPCHROME_MD=1" ]
-  }
-  if (proprietary_codecs) {
-    defines += [ "USE_PROPRIETARY_CODECS" ]
-  }
-  if (enable_hangout_services_extension) {
-    defines += [ "ENABLE_HANGOUT_SERVICES_EXTENSION=1" ]
-  }
-  if (v8_use_external_startup_data) {
-    defines += [ "V8_USE_EXTERNAL_STARTUP_DATA" ]
-  }
-  if (enable_background) {
-    defines += [ "ENABLE_BACKGROUND=1" ]
-  }
-  if (enable_pre_sync_backup) {
-    defines += [ "ENABLE_PRE_SYNC_BACKUP" ]
-  }
-  if (enable_video_hole) {
-    defines += [ "VIDEO_HOLE=1" ]
-  }
-  if (safe_browsing_mode == 1) {
-    defines += [ "FULL_SAFE_BROWSING" ]
-    defines += [ "SAFE_BROWSING_CSD" ]
-    defines += [ "SAFE_BROWSING_DB_LOCAL" ]
-    defines += [ "SAFE_BROWSING_SERVICE" ]
-  } else if (safe_browsing_mode == 2) {
-    defines += [ "MOBILE_SAFE_BROWSING" ]
-    defines += [ "SAFE_BROWSING_SERVICE" ]
-  } else if (safe_browsing_mode == 3) {
-    defines += [ "MOBILE_SAFE_BROWSING" ]
-    defines += [ "SAFE_BROWSING_DB_REMOTE" ]
-    defines += [ "SAFE_BROWSING_SERVICE" ]
-  }
-  if (is_official_build) {
-    defines += [ "OFFICIAL_BUILD" ]
-  }
-  if (is_chrome_branded) {
-    defines += [ "GOOGLE_CHROME_BUILD" ]
-  } else {
-    defines += [ "CHROMIUM_BUILD" ]
-  }
-  if (enable_media_router) {
-    defines += [ "ENABLE_MEDIA_ROUTER=1" ]
-  }
-  if (enable_webvr) {
-    defines += [ "ENABLE_WEBVR" ]
-  }
-  if (is_fnl) {
-    defines += [ "HAVE_SYS_QUEUE_H_=0" ]
-  }
-}
-
 # Debug/release ----------------------------------------------------------------
 
 config("debug") {
   defines = [
-    "_DEBUG",
-    "DYNAMIC_ANNOTATIONS_ENABLED=1",
-    "WTF_USE_DYNAMIC_ANNOTATIONS=1",
+    "DEBUG",
   ]
-
-  if (is_nacl) {
-    defines += [ "DYNAMIC_ANNOTATIONS_PREFIX=NACL_" ]
-  }
-
-  if (is_win) {
-    if (disable_iterator_debugging) {
-      # Iterator debugging is enabled by the compiler on debug builds, and we
-      # have to tell it to turn it off.
-      defines += [ "_HAS_ITERATOR_DEBUGGING=0" ]
-    }
-  } else if (is_linux && !is_android && current_cpu == "x64" &&
-             !disable_iterator_debugging) {
-    # Enable libstdc++ debugging facilities to help catch problems early, see
-    # http://crbug.com/65151 .
-    # TODO(phajdan.jr): Should we enable this for all of POSIX?
-    defines += [ "_GLIBCXX_DEBUG=1" ]
-  }
 }
 
 config("release") {
-  defines = [ "NDEBUG" ]
-
-  # Sanitizers.
-  # TODO(GYP) The GYP build has "release_valgrind_build == 0" for this
-  # condition. When Valgrind is set up, we need to do the same here.
-  if (is_tsan) {
-    defines += [
-      "DYNAMIC_ANNOTATIONS_ENABLED=1",
-      "WTF_USE_DYNAMIC_ANNOTATIONS=1",
-    ]
-  } else {
-    defines += [ "NVALGRIND" ]
-    if (!is_nacl) {
-      # NaCl always enables dynamic annotations. Currently this value is set to
-      # 1 for all .nexes.
-      defines += [ "DYNAMIC_ANNOTATIONS_ENABLED=0" ]
-    }
-  }
+  defines = [
+    "NDEBUG"
+  ]
 }
 
-# Default libraries ------------------------------------------------------------
-
-# This config defines the default libraries applied to all targets.
-config("default_libs") {
-  if (is_win) {
-    # TODO(brettw) this list of defaults should probably be smaller, and
-    # instead the targets that use the less common ones (e.g. wininet or
-    # winspool) should include those explicitly.
-    libs = [
-      "advapi32.lib",
-      "comdlg32.lib",
-      "dbghelp.lib",
-      "delayimp.lib",
-      "dnsapi.lib",
-      "gdi32.lib",
-      "kernel32.lib",
-      "msimg32.lib",
-      "odbc32.lib",
-      "odbccp32.lib",
-      "ole32.lib",
-      "oleaut32.lib",
-      "psapi.lib",
-      "shell32.lib",
-      "shlwapi.lib",
-      "user32.lib",
-      "usp10.lib",
-      "uuid.lib",
-      "version.lib",
-      "wininet.lib",
-      "winmm.lib",
-      "winspool.lib",
-      "ws2_32.lib",
-
-      # Please don't add more stuff here. We should actually be making this
-      # list smaller, since all common things should be covered. If you need
-      # some extra libraries, please just add a libs = [ "foo.lib" ] to your
-      # target that needs it.
-    ]
-  } else if (is_android) {
-    # Android uses -nostdlib so we need to add even libc here.
-    libs = [
-      # TODO(brettw) write a version of this, hopefully we can express this
-      # without forking out to GCC just to get the library name. The android
-      # toolchain directory should probably be extracted into a .gni file that
-      # this file and the android toolchain .gn file can share.
-      #   # Manually link the libgcc.a that the cross compiler uses.
-      #   '<!(<(android_toolchain)/*-gcc -print-libgcc-file-name)',
-      "c",
-      "dl",
-      "m",
-    ]
-  } else if (is_mac) {
-    libs = [
-      "AppKit.framework",
-      "ApplicationServices.framework",
-      "Carbon.framework",
-      "CoreFoundation.framework",
-      "Foundation.framework",
-      "IOKit.framework",
-      "Security.framework",
-      "OpenGL.framework",
-    ]
-  } else if (is_ios) {
-    # The libraries listed here will be specified for both the target and the
-    # host. Only the common ones should be listed here.
-    libs = [
-      "CoreFoundation.framework",
-      "CoreGraphics.framework",
-      "CoreText.framework",
-      "Foundation.framework",
-    ]
-  } else if (is_linux) {
-    libs = [ "dl" ]
-  }
-}
-
-# Add this config to your target to enable precompiled headers.
-#
-# On Windows, precompiled headers are done on a per-target basis. If you have
-# just a couple of files, the time it takes to precompile (~2 seconds) can
-# actually be longer than the time saved. On a Z620, a 100 file target compiles
-# about 2 seconds faster with precompiled headers, with greater savings for
-# larger targets.
-#
-# Recommend precompiled headers for targets with more than 50 .cc files.
-config("precompiled_headers") {
-  # TODO(brettw) enable this when GN support in the binary has been rolled.
-  #if (is_win) {
-  if (false) {
-    # This is a string rather than a file GN knows about. It has to match
-    # exactly what's in the /FI flag below, and what might appear in the source
-    # code in quotes for an #include directive.
-    precompiled_header = "build/precompile.h"
-
-    # This is a file that GN will compile with the above header. It will be
-    # implicitly added to the sources (potentially multiple times, with one
-    # variant for each language used in the target).
-    precompiled_source = "//build/precompile.cc"
-
-    # Force include the header.
-    cflags = [ "/FI$precompiled_header" ]
-  }
+config("product") {
+  defines = [
+    "NDEBUG",
+    "PRODUCT",
+  ]
 }
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn
index e22b29a..09527af 100644
--- a/build/config/BUILDCONFIG.gn
+++ b/build/config/BUILDCONFIG.gn
@@ -38,17 +38,8 @@
   target_os = host_os
 }
 
-if (target_cpu == "") {
-  if (target_os == "android") {
-    # If we're building for Android, we should assume that we want to
-    # build for ARM by default, not the host_cpu (which is likely x64).
-    # This allows us to not have to specify both target_os and target_cpu
-    # on the command line.
-    target_cpu = "arm"
-  } else {
-    target_cpu = host_cpu
-  }
-}
+assert(host_cpu != "")
+assert(target_cpu != "")
 
 if (current_cpu == "") {
   current_cpu = target_cpu
@@ -110,28 +101,23 @@
 # - Don't call exec_script inside declare_args. This will execute the script
 #   even if the value is overridden, which is wasteful. See first bullet.
 
+# There is no component build for the Dart VM, but build files in some
+# dependencies check this.
+is_component_build = false
+
 declare_args() {
-  # How many symbols to include in the build. This affects the performance of
-  # the build since the symbols are large and dealing with them is slow.
-  #   2 means regular build with symbols.
-  #   1 means minimal symbols, usually enough for backtraces only.
-  #   0 means no symbols.
-  #   -1 means auto-set (off in release, regular in debug).
-  symbol_level = -1
-
-  # Component build.
-  is_component_build = false
-
   # Debug build.
   is_debug = true
 
-  # Whether we're a traditional desktop unix.
-  is_desktop_linux = current_os == "linux" && current_os != "chromeos"
+  # Release build.
+  is_release = false
+
+  # Product build.
+  is_product = false
 
   # Set to true when compiling with the Clang compiler. Typically this is used
   # to configure warnings.
-  is_clang = current_os == "mac" || current_os == "ios" ||
-             current_os == "linux" || current_os == "chromeos"
+  is_clang = current_os == "mac" || current_os == "linux"
 
   # Compile for Address Sanitizer to find memory bugs.
   is_asan = false
@@ -144,15 +130,6 @@
 
   # Compile for Thread Sanitizer to find threading bugs.
   is_tsan = false
-
-  if (current_os == "chromeos") {
-    # Allows the target toolchain to be injected as arguments. This is needed
-    # to support the CrOS build system which supports per-build-configuration
-    # toolchains.
-    cros_use_custom_toolchain = false
-  }
-
-  # DON'T ADD MORE FLAGS HERE. Read the comment above.
 }
 
 # =============================================================================
@@ -176,7 +153,6 @@
 if (current_os == "win") {
   is_android = false
   is_chromeos = false
-  is_fnl = false
   is_ios = false
   is_linux = false
   is_mac = false
@@ -186,7 +162,6 @@
 } else if (current_os == "mac") {
   is_android = false
   is_chromeos = false
-  is_fnl = false
   is_ios = false
   is_linux = false
   is_mac = true
@@ -196,60 +171,15 @@
 } else if (current_os == "android") {
   is_android = true
   is_chromeos = false
-  is_fnl = false
   is_ios = false
   is_linux = false
   is_mac = false
   is_nacl = false
   is_posix = true
   is_win = false
-} else if (current_os == "chromeos") {
-  is_android = false
-  is_chromeos = true
-  is_fnl = false
-  is_ios = false
-  is_linux = true
-  is_mac = false
-  is_nacl = false
-  is_posix = true
-  is_win = false
-} else if (current_os == "nacl") {
-  # current_os == "nacl" will be passed by the nacl toolchain definition.
-  # It is not set by default or on the command line. We treat is as a
-  # Posix variant.
-  is_android = false
-  is_chromeos = false
-  is_fnl = false
-  is_ios = false
-  is_linux = false
-  is_mac = false
-  is_nacl = true
-  is_posix = true
-  is_win = false
-} else if (current_os == "ios") {
-  is_android = false
-  is_chromeos = false
-  is_fnl = false
-  is_ios = true
-  is_linux = false
-  is_mac = false
-  is_nacl = false
-  is_posix = true
-  is_win = false
 } else if (current_os == "linux") {
   is_android = false
   is_chromeos = false
-  is_fnl = false
-  is_ios = false
-  is_linux = true
-  is_mac = false
-  is_nacl = false
-  is_posix = true
-  is_win = false
-} else if (current_os == "fnl") {
-  is_android = false
-  is_chromeos = false
-  is_fnl = true
   is_ios = false
   is_linux = true
   is_mac = false
@@ -259,119 +189,6 @@
 }
 
 # =============================================================================
-# SOURCES FILTERS
-# =============================================================================
-#
-# These patterns filter out platform-specific files when assigning to the
-# sources variable. The magic variable |sources_assignment_filter| is applied
-# to each assignment or appending to the sources variable and matches are
-# automatcally removed.
-#
-# Note that the patterns are NOT regular expressions. Only "*" and "\b" (path
-# boundary = end of string or slash) are supported, and the entire string
-# muct match the pattern (so you need "*.cc" to match all .cc files, for
-# example).
-
-# DO NOT ADD MORE PATTERNS TO THIS LIST, see set_sources_assignment_filter call
-# below.
-sources_assignment_filter = []
-if (!is_posix) {
-  sources_assignment_filter += [
-    "*_posix.h",
-    "*_posix.cc",
-    "*_posix_unittest.h",
-    "*_posix_unittest.cc",
-    "*\bposix/*",
-  ]
-}
-if (!is_win) {
-  sources_assignment_filter += [
-    "*_win.cc",
-    "*_win.h",
-    "*_win_unittest.cc",
-    "*\bwin/*",
-    "*.def",
-    "*.rc",
-  ]
-}
-if (!is_mac) {
-  sources_assignment_filter += [
-    "*_mac.h",
-    "*_mac.cc",
-    "*_mac.mm",
-    "*_mac_unittest.h",
-    "*_mac_unittest.cc",
-    "*_mac_unittest.mm",
-    "*\bmac/*",
-    "*_cocoa.h",
-    "*_cocoa.cc",
-    "*_cocoa.mm",
-    "*_cocoa_unittest.h",
-    "*_cocoa_unittest.cc",
-    "*_cocoa_unittest.mm",
-    "*\bcocoa/*",
-  ]
-}
-if (!is_ios) {
-  sources_assignment_filter += [
-    "*_ios.h",
-    "*_ios.cc",
-    "*_ios.mm",
-    "*_ios_unittest.h",
-    "*_ios_unittest.cc",
-    "*_ios_unittest.mm",
-    "*\bios/*",
-  ]
-}
-if (!is_mac && !is_ios) {
-  sources_assignment_filter += [ "*.mm" ]
-}
-if (!is_linux) {
-  sources_assignment_filter += [
-    "*_linux.h",
-    "*_linux.cc",
-    "*_linux_unittest.h",
-    "*_linux_unittest.cc",
-    "*\blinux/*",
-  ]
-}
-if (!is_android) {
-  sources_assignment_filter += [
-    "*_android.h",
-    "*_android.cc",
-    "*_android_unittest.h",
-    "*_android_unittest.cc",
-    "*\bandroid/*",
-  ]
-}
-if (!is_chromeos) {
-  sources_assignment_filter += [
-    "*_chromeos.h",
-    "*_chromeos.cc",
-    "*_chromeos_unittest.h",
-    "*_chromeos_unittest.cc",
-    "*\bchromeos/*",
-  ]
-}
-
-# DO NOT ADD MORE PATTERNS TO THIS LIST, see set_sources_assignment_filter call
-# below.
-
-# Actually save this list.
-#
-# These patterns are executed for every file in the source tree of every run.
-# Therefore, adding more patterns slows down the build for everybody. We should
-# only add automatic patterns for configurations affecting hundreds of files
-# across many projects in the tree.
-#
-# Therefore, we only add rules to this list corresponding to platforms on the
-# Chromium waterfall.  This is not for non-officially-supported platforms
-# (FreeBSD, etc.) toolkits, (X11, GTK, etc.), or features. For these cases,
-# write a conditional in the target to remove the file(s) from the list when
-# your platform/toolkit/feature doesn't apply.
-set_sources_assignment_filter(sources_assignment_filter)
-
-# =============================================================================
 # BUILD OPTIONS
 # =============================================================================
 
@@ -393,7 +210,6 @@
 # Holds all configs used for making native executables and libraries, to avoid
 # duplication in each target below.
 _native_compiler_configs = [
-  "//build/config:feature_flags",
   "//build/config/compiler:compiler",
   "//build/config/compiler:compiler_arm_fpu",
   "//build/config/compiler:chromium_code",
@@ -413,18 +229,13 @@
 if (is_posix) {
   _native_compiler_configs += [
     "//build/config/gcc:no_exceptions",
-    "//build/config/gcc:symbol_visibility_hidden",
   ]
 }
 
-if (is_fnl) {
-  _native_compiler_configs += [ "//build/config/fnl:sdk" ]
-} else if (is_linux) {
+if (is_linux) {
   _native_compiler_configs += [ "//build/config/linux:sdk" ]
 } else if (is_mac) {
   _native_compiler_configs += [ "//build/config/mac:sdk" ]
-} else if (is_ios) {
-  _native_compiler_configs += [ "//build/config/ios:sdk" ]
 } else if (is_android) {
   _native_compiler_configs += [ "//build/config/android:sdk" ]
 }
@@ -440,36 +251,18 @@
 if (is_debug) {
   _native_compiler_configs += [ "//build/config:debug" ]
   _default_optimization_config = "//build/config/compiler:no_optimize"
-} else {
+} else if (is_release) {
   _native_compiler_configs += [ "//build/config:release" ]
   _default_optimization_config = "//build/config/compiler:optimize"
+} else {
+  assert(is_product)
+  _native_compiler_configs += [ "//build/config:product" ]
+  _default_optimization_config = "//build/config/compiler:optimize"
 }
 _native_compiler_configs += [ _default_optimization_config ]
 
-# If it wasn't manually set, set to an appropriate default.
-if (symbol_level == -1) {
-  # Linux is slowed by having symbols as part of the target binary, whereas
-  # Mac and Windows have them separate, so in Release Linux, default them off.
-  if (is_debug || !is_linux) {
-    symbol_level = 2
-  } else if (is_asan || is_lsan || is_tsan || is_msan) {
-    # Sanitizers require symbols for filename suppressions to work.
-    symbol_level = 1
-  } else {
-    symbol_level = 0
-  }
-}
-
 # Symbol setup.
-if (symbol_level == 2) {
-  _default_symbols_config = "//build/config/compiler:symbols"
-} else if (symbol_level == 1) {
-  _default_symbols_config = "//build/config/compiler:minimal_symbols"
-} else if (symbol_level == 0) {
-  _default_symbols_config = "//build/config/compiler:no_symbols"
-} else {
-  assert(false, "Bad value for symbol_level.")
-}
+_default_symbols_config = "//build/config/compiler:symbols"
 _native_compiler_configs += [ _default_symbols_config ]
 
 # Windows linker setup for EXEs and DLLs.
@@ -486,8 +279,7 @@
 }
 
 # Executable defaults.
-_executable_configs =
-    _native_compiler_configs + [ "//build/config:default_libs" ]
+_executable_configs = _native_compiler_configs
 if (is_win) {
   _executable_configs += _windows_linker_configs
 } else if (is_mac) {
@@ -511,8 +303,7 @@
 }
 
 # Shared library defaults (also for components in component mode).
-_shared_library_configs =
-    _native_compiler_configs + [ "//build/config:default_libs" ]
+_shared_library_configs = _native_compiler_configs
 if (is_win) {
   _shared_library_configs += _windows_linker_configs
 } else if (is_mac) {
@@ -526,29 +317,13 @@
 set_defaults("shared_library") {
   configs = _shared_library_configs
 }
-if (is_component_build) {
-  set_defaults("component") {
-    configs = _shared_library_configs
-  }
-}
 
 # Source set defaults (also for components in non-component mode).
 set_defaults("source_set") {
   configs = _native_compiler_configs
 }
-if (!is_component_build) {
-  set_defaults("component") {
-    configs = _native_compiler_configs
-  }
-}
-
-# Test defaults.
-set_defaults("test") {
-  if (is_android) {
-    configs = _shared_library_configs
-  } else {
-    configs = _executable_configs
-  }
+set_defaults("component") {
+  configs = _native_compiler_configs
 }
 
 # ==============================================================================
@@ -570,7 +345,6 @@
   set_default_toolchain("$host_toolchain")
 } else if (is_android) {
   if (host_os == "linux") {
-    # Use clang for the x86/64 Linux host builds.
     if (host_cpu == "x86" || host_cpu == "x64") {
       host_toolchain = "//build/toolchain/linux:clang_$host_cpu"
     } else {
@@ -594,234 +368,108 @@
     host_toolchain = "//build/toolchain/linux:$host_cpu"
     set_default_toolchain("//build/toolchain/linux:$current_cpu")
   }
-  if (is_chromeos && cros_use_custom_toolchain) {
-    set_default_toolchain("//build/toolchain/cros:target")
-  }
-  if (is_fnl) {
-    set_default_toolchain("//build/toolchain/fnl:target")
-  }
 } else if (is_mac) {
   host_toolchain = "//build/toolchain/mac:clang_x64"
   set_default_toolchain(host_toolchain)
-} else if (is_ios) {
-  host_toolchain = "//build/toolchain/mac:clang_x64"
-  if (use_ios_simulator) {
-    set_default_toolchain("//build/toolchain/mac:ios_clang_x64")
-  } else {
-    set_default_toolchain("//build/toolchain/mac:ios_clang_arm")
-  }
-} else if (is_nacl) {
-  # TODO(GYP): This will need to change when we get NaCl working
-  # on multiple platforms, but this whole block of code (how we define
-  # host_toolchain) needs to be reworked regardless to key off of host_os
-  # and host_cpu rather than the is_* variables.
-  host_toolchain = "//build/toolchain/linux:clang_x64"
 }
 
 # ==============================================================================
 # COMPONENT SETUP
 # ==============================================================================
 
-# TODO(brettw) erase this once the built-in "component" function is removed.
-if (is_component_build) {
-  component_mode = "shared_library"
-} else {
-  component_mode = "source_set"
-}
+# Don't try to do component builds for the standalone Dart VM.
+assert(!is_component_build)
+component_mode = "source_set"
 
 template("component") {
-  if (is_component_build) {
-    shared_library(target_name) {
-      # Configs will always be defined since we set_defaults for a component
-      # above. We want to use those rather than whatever came with the nested
-      # shared/static library inside the component.
-      configs = []  # Prevent list overwriting warning.
-      configs = invoker.configs
+  source_set(target_name) {
+    # See above.
+    configs = []  # Prevent list overwriting warning.
+    configs = invoker.configs
 
-      # The sources assignment filter will have already been applied when the
-      # code was originally executed. We don't want to apply it again, since
-      # the original target may have override it for some assignments.
-      set_sources_assignment_filter([])
+    # See above call.
+    set_sources_assignment_filter([])
 
-      if (defined(invoker.all_dependent_configs)) {
-        all_dependent_configs = invoker.all_dependent_configs
-      }
-      if (defined(invoker.allow_circular_includes_from)) {
-        allow_circular_includes_from = invoker.allow_circular_includes_from
-      }
-      if (defined(invoker.cflags)) {
-        cflags = invoker.cflags
-      }
-      if (defined(invoker.cflags_c)) {
-        cflags_c = invoker.cflags_c
-      }
-      if (defined(invoker.cflags_cc)) {
-        cflags_cc = invoker.cflags_cc
-      }
-      if (defined(invoker.cflags_objc)) {
-        cflags_objc = invoker.cflags_objc
-      }
-      if (defined(invoker.cflags_objcc)) {
-        cflags_objcc = invoker.cflags_objcc
-      }
-      if (defined(invoker.check_includes)) {
-        check_includes = invoker.check_includes
-      }
-      if (defined(invoker.data)) {
-        data = invoker.data
-      }
-      if (defined(invoker.data_deps)) {
-        data_deps = invoker.data_deps
-      }
-      if (defined(invoker.datadeps)) {
-        datadeps = invoker.datadeps
-      }
-      if (defined(invoker.defines)) {
-        defines = invoker.defines
-      }
-
-      # All shared libraries must have the sanitizer deps to properly link in
-      # asan mode (this target will be empty in other cases).
-      if (defined(invoker.deps)) {
-        deps = invoker.deps + [ "//build/config/sanitizers:deps" ]
-      } else {
-        deps = [
-          "//build/config/sanitizers:deps",
-        ]
-      }
-      if (defined(invoker.direct_dependent_configs)) {
-        direct_dependent_configs = invoker.direct_dependent_configs
-      }
-      if (defined(invoker.forward_dependent_configs_from)) {
-        forward_dependent_configs_from = invoker.forward_dependent_configs_from
-      }
-      if (defined(invoker.include_dirs)) {
-        include_dirs = invoker.include_dirs
-      }
-      if (defined(invoker.ldflags)) {
-        ldflags = invoker.ldflags
-      }
-      if (defined(invoker.lib_dirs)) {
-        lib_dirs = invoker.lib_dirs
-      }
-      if (defined(invoker.libs)) {
-        libs = invoker.libs
-      }
-      if (defined(invoker.output_extension)) {
-        output_extension = invoker.output_extension
-      }
-      if (defined(invoker.output_name)) {
-        output_name = invoker.output_name
-      }
-      if (defined(invoker.public)) {
-        public = invoker.public
-      }
-      if (defined(invoker.public_configs)) {
-        public_configs = invoker.public_configs
-      }
-      if (defined(invoker.public_deps)) {
-        public_deps = invoker.public_deps
-      }
-      if (defined(invoker.sources)) {
-        sources = invoker.sources
-      }
-      if (defined(invoker.testonly)) {
-        testonly = invoker.testonly
-      }
-      if (defined(invoker.visibility)) {
-        visibility = invoker.visibility
-      }
+    if (defined(invoker.all_dependent_configs)) {
+      all_dependent_configs = invoker.all_dependent_configs
     }
-  } else {
-    source_set(target_name) {
-      # See above.
-      configs = []  # Prevent list overwriting warning.
-      configs = invoker.configs
-
-      # See above call.
-      set_sources_assignment_filter([])
-
-      if (defined(invoker.all_dependent_configs)) {
-        all_dependent_configs = invoker.all_dependent_configs
-      }
-      if (defined(invoker.allow_circular_includes_from)) {
-        allow_circular_includes_from = invoker.allow_circular_includes_from
-      }
-      if (defined(invoker.cflags)) {
-        cflags = invoker.cflags
-      }
-      if (defined(invoker.cflags_c)) {
-        cflags_c = invoker.cflags_c
-      }
-      if (defined(invoker.cflags_cc)) {
-        cflags_cc = invoker.cflags_cc
-      }
-      if (defined(invoker.cflags_objc)) {
-        cflags_objc = invoker.cflags_objc
-      }
-      if (defined(invoker.cflags_objcc)) {
-        cflags_objcc = invoker.cflags_objcc
-      }
-      if (defined(invoker.check_includes)) {
-        check_includes = invoker.check_includes
-      }
-      if (defined(invoker.data)) {
-        data = invoker.data
-      }
-      if (defined(invoker.data_deps)) {
-        data_deps = invoker.data_deps
-      }
-      if (defined(invoker.datadeps)) {
-        datadeps = invoker.datadeps
-      }
-      if (defined(invoker.defines)) {
-        defines = invoker.defines
-      }
-      if (defined(invoker.deps)) {
-        deps = invoker.deps
-      }
-      if (defined(invoker.direct_dependent_configs)) {
-        direct_dependent_configs = invoker.direct_dependent_configs
-      }
-      if (defined(invoker.forward_dependent_configs_from)) {
-        forward_dependent_configs_from = invoker.forward_dependent_configs_from
-      }
-      if (defined(invoker.include_dirs)) {
-        include_dirs = invoker.include_dirs
-      }
-      if (defined(invoker.ldflags)) {
-        ldflags = invoker.ldflags
-      }
-      if (defined(invoker.lib_dirs)) {
-        lib_dirs = invoker.lib_dirs
-      }
-      if (defined(invoker.libs)) {
-        libs = invoker.libs
-      }
-      if (defined(invoker.output_extension)) {
-        output_extension = invoker.output_extension
-      }
-      if (defined(invoker.output_name)) {
-        output_name = invoker.output_name
-      }
-      if (defined(invoker.public)) {
-        public = invoker.public
-      }
-      if (defined(invoker.public_configs)) {
-        public_configs = invoker.public_configs
-      }
-      if (defined(invoker.public_deps)) {
-        public_deps = invoker.public_deps
-      }
-      if (defined(invoker.sources)) {
-        sources = invoker.sources
-      }
-      if (defined(invoker.testonly)) {
-        testonly = invoker.testonly
-      }
-      if (defined(invoker.visibility)) {
-        visibility = invoker.visibility
-      }
+    if (defined(invoker.allow_circular_includes_from)) {
+      allow_circular_includes_from = invoker.allow_circular_includes_from
+    }
+    if (defined(invoker.cflags)) {
+      cflags = invoker.cflags
+    }
+    if (defined(invoker.cflags_c)) {
+      cflags_c = invoker.cflags_c
+    }
+    if (defined(invoker.cflags_cc)) {
+      cflags_cc = invoker.cflags_cc
+    }
+    if (defined(invoker.cflags_objc)) {
+      cflags_objc = invoker.cflags_objc
+    }
+    if (defined(invoker.cflags_objcc)) {
+      cflags_objcc = invoker.cflags_objcc
+    }
+    if (defined(invoker.check_includes)) {
+      check_includes = invoker.check_includes
+    }
+    if (defined(invoker.data)) {
+      data = invoker.data
+    }
+    if (defined(invoker.data_deps)) {
+      data_deps = invoker.data_deps
+    }
+    if (defined(invoker.datadeps)) {
+      datadeps = invoker.datadeps
+    }
+    if (defined(invoker.defines)) {
+      defines = invoker.defines
+    }
+    if (defined(invoker.deps)) {
+      deps = invoker.deps
+    }
+    if (defined(invoker.direct_dependent_configs)) {
+      direct_dependent_configs = invoker.direct_dependent_configs
+    }
+    if (defined(invoker.forward_dependent_configs_from)) {
+      forward_dependent_configs_from = invoker.forward_dependent_configs_from
+    }
+    if (defined(invoker.include_dirs)) {
+      include_dirs = invoker.include_dirs
+    }
+    if (defined(invoker.ldflags)) {
+      ldflags = invoker.ldflags
+    }
+    if (defined(invoker.lib_dirs)) {
+      lib_dirs = invoker.lib_dirs
+    }
+    if (defined(invoker.libs)) {
+      libs = invoker.libs
+    }
+    if (defined(invoker.output_extension)) {
+      output_extension = invoker.output_extension
+    }
+    if (defined(invoker.output_name)) {
+      output_name = invoker.output_name
+    }
+    if (defined(invoker.public)) {
+      public = invoker.public
+    }
+    if (defined(invoker.public_configs)) {
+      public_configs = invoker.public_configs
+    }
+    if (defined(invoker.public_deps)) {
+      public_deps = invoker.public_deps
+    }
+    if (defined(invoker.sources)) {
+      sources = invoker.sources
+    }
+    if (defined(invoker.testonly)) {
+      testonly = invoker.testonly
+    }
+    if (defined(invoker.visibility)) {
+      visibility = invoker.visibility
     }
   }
 }
diff --git a/build/config/allocator.gni b/build/config/allocator.gni
deleted file mode 100644
index 71418a8..0000000
--- a/build/config/allocator.gni
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# TODO(GYP): Make tcmalloc work on win.
-if (is_android || current_cpu == "mipsel" || is_mac || is_ios || is_asan ||
-    is_lsan || is_tsan || is_msan || is_win) {
-  _default_allocator = "none"
-} else {
-  _default_allocator = "tcmalloc"
-}
-
-declare_args() {
-  # Memory allocator to use. Set to "none" to use default allocator.
-  use_allocator = _default_allocator
-}
diff --git a/build/config/android/config.gni b/build/config/android/config.gni
index 5457b88..a16407b 100644
--- a/build/config/android/config.gni
+++ b/build/config/android/config.gni
@@ -51,10 +51,8 @@
 
   # Defines the name the Android build gives to the current host CPU
   # architecture, which is different than the names GN uses.
-  if (host_cpu == "x64") {
+  if ((host_cpu == "x64") || (host_cpu == "x86")) {
     android_host_arch = "x86_64"
-  } else if (host_cpu == "x86") {
-    android_host_arch = "x86"
   } else {
     assert(false, "Need Android toolchain support for your build CPU arch.")
   }
diff --git a/build/config/chrome_build.gni b/build/config/chrome_build.gni
deleted file mode 100644
index c2132c4..0000000
--- a/build/config/chrome_build.gni
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-declare_args() {
-  # Selects the desired build flavor. Official builds get additional
-  # processing to prepare for release. Normally you will want to develop and
-  # test with this flag off.
-  is_official_build = false
-
-  # Select the desired branding flavor. False means normal Chromium branding,
-  # true means official Google Chrome branding (requires extra Google-internal
-  # resources).
-  is_chrome_branded = false
-
-  # Break chrome.dll into multple pieces based on process type. Only available
-  # on Windows.
-  is_multi_dll_chrome = is_win && !is_component_build
-}
diff --git a/build/config/clang/clang.gni b/build/config/clang/clang.gni
index cb84879..3893ca3 100644
--- a/build/config/clang/clang.gni
+++ b/build/config/clang/clang.gni
@@ -5,5 +5,5 @@
 declare_args() {
   # Indicates if the build should use the Chrome-specific plugins for enforcing
   # coding guidelines, etc. Only used when compiling with Clang.
-  clang_use_chrome_plugins = is_clang && !is_nacl
+  clang_use_chrome_plugins = false
 }
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 04d4bd9..5bc242f 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -3,7 +3,6 @@
 # found in the LICENSE file.
 
 import("//build/config/android/config.gni")
-import("//build/config/chrome_build.gni")
 if (current_cpu == "arm") {
   import("//build/config/arm.gni")
 }
@@ -21,39 +20,6 @@
 import("//build/config/sanitizers/sanitizers.gni")
 
 declare_args() {
-  # Normally, Android builds are lightly optimized, even for debug builds, to
-  # keep binary size down. Setting this flag to true disables such optimization
-  android_full_debug = false
-
-  # Whether to use the binary binutils checked into third_party/binutils.
-  # These are not multi-arch so cannot be used except on x86 and x86-64 (the
-  # only two architectures that are currently checked in). Turn this off when
-  # you are using a custom toolchain and need to control -B in cflags.
-  linux_use_bundled_binutils = is_linux && current_cpu == "x64"
-
-  # Compile in such a way as to enable profiling of the generated code. For
-  # example, don't omit the frame pointer and leave in symbols.
-  enable_profiling = false
-
-  # Compile in such a way as to make it possible for the profiler to unwind full
-  # stack frames. Setting this flag has a large effect on the performance of the
-  # generated code than just setting profiling, but gives the profiler more
-  # information to analyze.
-  # Requires profiling to be set to true.
-  enable_full_stack_frames_for_profiling = false
-
-  # Use gold for linking on 64-bit Linux only (on 32-bit it runs out of
-  # address space, and it doesn't support cross-compiling).
-  use_gold = is_linux && current_cpu == "x64"
-
-  # use_debug_fission: whether to use split DWARF debug info
-  # files. This can reduce link time significantly, but is incompatible
-  # with some utilities such as icecc and ccache. Requires gold and
-  # gcc >= 4.8 or clang.
-  # http://gcc.gnu.org/wiki/DebugFission
-  use_debug_fission = is_debug && !is_win && use_gold &&
-                      linux_use_bundled_binutils && !use_ccache
-
   if (is_win) {
     # Whether the VS xtree header has been patched to disable warning 4702. If
     # it has, then we don't need to disable 4702 (unreachable code warning).
@@ -143,28 +109,20 @@
   } else {
     # Common GCC compiler flags setup.
     # --------------------------------
-    cflags += [ "-fno-strict-aliasing" ]  # See http://crbug.com/32204
     common_flags = [
       # Not exporting C++ inline functions can generally be applied anywhere
       # so we do so here. Normal function visibility is controlled by
       # //build/config/gcc:symbol_visibility_hidden.
       "-fvisibility-inlines-hidden",
+
+      # We need the frame pointer for CPU and heap profiling.
+      "-fno-omit-frame-pointer",
     ]
     cflags_cc += common_flags
     cflags_objcc += common_flags
 
-    # Stack protection.
-    if (is_mac) {
-      cflags += [ "-fstack-protector-all" ]
-    } else if (is_linux) {
-      cflags += [
-        "-fstack-protector",
-        "--param=ssp-buffer-size=4",
-      ]
-    }
-
     # Linker warnings.
-    if (!(is_chromeos && current_cpu == "arm") && !is_mac && !is_ios) {
+    if ((current_cpu != "arm") && !is_mac) {
       # TODO(jochen): Enable this on chromeos on arm. http://crbug.com/356580
       ldflags += [ "-Wl,--fatal-warnings" ]
     }
@@ -173,7 +131,6 @@
     # MemorySanitizer
     if (using_sanitizer) {
       cflags += [
-        "-fno-omit-frame-pointer",
         "-gline-tables-only",
       ]
     }
@@ -217,11 +174,6 @@
         "//buildtools/third_party/libc++abi/trunk/include",
       ]
     }
-
-    if (is_fnl) {
-      # TODO(kulakowski) remove when fnl no longer uses gcc
-      cflags += [ "-Wno-maybe-uninitialized" ]
-    }
   }
 
   if (is_clang && is_debug) {
@@ -237,7 +189,7 @@
     cflags_objcc += extra_flags
   }
 
-  if (is_clang && !is_nacl) {
+  if (is_clang) {
     # This is here so that all files get recompiled after a clang roll and
     # when turning clang on or off. (defines are passed via the command line,
     # and build system rebuild things when their commandline changes). Nothing
@@ -250,9 +202,9 @@
 
   # Mac-specific compiler flags setup.
   # ----------------------------------
-  if (is_mac || is_ios) {
+  if (is_mac) {
     # These flags are shared between the C compiler and linker.
-    common_mac_flags = []
+    common_mac_flags = [ "-fno-exceptions" ]
 
     # CPU architecture.
     if (current_cpu == "x64") {
@@ -293,16 +245,21 @@
       cflags += [
         "-m64",
         "-march=x86-64",
+        "-msse2",
       ]
       ldflags += [ "-m64" ]
     } else if (current_cpu == "x86") {
-      cflags += [ "-m32" ]
+      cflags += [
+        "-m32",
+        "-msse2",
+        "-mfpmath=sse",
+      ]
       ldflags += [ "-m32" ]
       if (is_clang) {
         cflags += [
           # Else building libyuv gives clang's register allocator issues,
           # see llvm.org/PR15798 / crbug.com/233709
-          "-momit-leaf-frame-pointer",
+          "-mno-omit-leaf-frame-pointer",
 
           # Align the stack on 16-byte boundaries, http://crbug.com/418554.
           "-mstack-alignment=16",
@@ -310,6 +267,7 @@
         ]
       }
     } else if (current_cpu == "arm") {
+
       cflags += [
         "-march=$arm_arch",
         "-mfloat-abi=$arm_float_abi",
@@ -339,6 +297,15 @@
         ]
       }
     } else if (current_cpu == "mipsel") {
+      # We have to explicitly request exceptions to get good heap profiles from
+      # tcmalloc.
+      if (is_debug || is_release) {
+        cflags += [
+          "-fexceptions",
+          "-funwind-tables"
+        ]
+      }
+
       if (mips_arch_variant == "r6") {
         cflags += [
           "-mips32r6",
@@ -388,44 +355,8 @@
       }
     }
 
-    defines += [ "_FILE_OFFSET_BITS=64" ]
-
-    if (!is_android) {
-      defines += [
-        "_LARGEFILE_SOURCE",
-        "_LARGEFILE64_SOURCE",
-      ]
-    }
-
-    # Omit unwind support in official builds to save space. We can use breakpad
-    # for these builds.
-    if (is_chrome_branded && is_official_build) {
-      cflags += [
-        "-fno-unwind-tables",
-        "-fno-asynchronous-unwind-tables",
-      ]
-      defines += [ "NO_UNWIND_TABLES" ]
-    } else {
-      cflags += [ "-funwind-tables" ]
-    }
-  }
-
-  if (enable_profiling && !is_debug) {
-    # The GYP build spams this define into every compilation unit, as we do
-    # here, but it only appears to be used in base and a couple other places.
-    # TODO(abarth): Should we move this define closer to where it's used?
-    defines += [ "ENABLE_PROFILING" ]
-
-    cflags += [
-      "-fno-omit-frame-pointer",
-      "-g",
-    ]
-
-    if (enable_full_stack_frames_for_profiling) {
-      cflags += [
-        "-fno-inline",
-        "-fno-optimize-sibling-calls",
-      ]
+    if (current_cpu != "mipsel") {
+      cflags += [ "-fno-exceptions" ]
     }
   }
 
@@ -434,7 +365,6 @@
   if (is_linux || is_android) {
     cflags += [
       "-fPIC",
-      "-pipe",  # Use pipes for communicating between sub-processes. Faster.
     ]
 
     ldflags += [
@@ -443,9 +373,6 @@
       "-Wl,-z,now",
       "-Wl,-z,relro",
     ]
-    if (!using_sanitizer) {
-      ldflags += [ "-Wl,-z,defs" ]
-    }
   }
 
   # Linux-specific compiler flags setup.
@@ -454,46 +381,6 @@
     cflags += [ "-pthread" ]
     ldflags += [ "-pthread" ]
   }
-  if (use_gold) {
-    gold_path = rebase_path("//third_party/binutils/Linux_x64/Release/bin",
-                            root_build_dir)
-    ldflags += [
-      "-B$gold_path",
-
-      # Newer gccs and clangs support -fuse-ld, use the flag to force gold
-      # selection.
-      # gcc -- http://gcc.gnu.org/onlinedocs/gcc-4.8.0/gcc/Optimize-Options.html
-      "-fuse-ld=gold",
-
-      # Experimentation found that using four linking threads
-      # saved ~20% of link time.
-      # https://groups.google.com/a/chromium.org/group/chromium-dev/browse_thread/thread/281527606915bb36
-      # Only apply this to the target linker, since the host
-      # linker might not be gold, but isn't used much anyway.
-      # TODO(raymes): Disable threading because gold is frequently
-      # crashing on the bots: crbug.com/161942.
-      #"-Wl,--threads",
-      #"-Wl,--thread-count=4",
-    ]
-
-    if (!is_asan && !is_msan && !is_lsan && !is_tsan) {
-      # TODO(brettw) common.gypi has this only for target toolset.
-      ldflags += [ "-Wl,--icf=all" ]
-    }
-
-    # TODO(thestig): Make this flag work with GN.
-    #if (!is_official_build && !is_chromeos && !(is_asan || is_lsan || is_tsan || is_msan)) {
-    #  ldflags += [
-    #    "-Wl,--detect-odr-violations",
-    #  ]
-    #}
-  }
-
-  if (linux_use_bundled_binutils) {
-    binutils_path = rebase_path("//third_party/binutils/Linux_x64/Release/bin",
-                                root_build_dir)
-    cflags += [ "-B$binutils_path" ]
-  }
 
   # Clang-specific compiler flags setup.
   # ------------------------------------
@@ -501,20 +388,6 @@
     cflags += [ "-fcolor-diagnostics" ]
   }
 
-  # C++11 compiler flags setup.
-  # ---------------------------
-  if (is_linux || is_android || is_nacl) {
-    # gnu++11 instead of c++11 is needed because some code uses typeof() (a
-    # GNU extension).
-    # TODO(thakis): Eventually switch this to c++11 instead,
-    # http://crbug.com/427584
-    cflags_cc += [ "-std=gnu++11" ]
-  } else if (!is_win) {
-    cc_std = [ "-std=c++11" ]
-    cflags_cc += cc_std
-    cflags_objcc += cc_std
-  }
-
   # Android-specific flags setup.
   # -----------------------------
   if (is_android) {
@@ -552,17 +425,10 @@
     }
 
     ldflags += [
-      "-Wl,--no-undefined",
-
       # Don't allow visible symbols from libgcc or libc++ to be
       # re-exported.
       "-Wl,--exclude-libs=libgcc.a",
       "-Wl,--exclude-libs=libc++_static.a",
-
-      # Don't allow visible symbols from libraries that contain
-      # assembly code with symbols that aren't hidden properly.
-      # http://crbug.com/448386
-      "-Wl,--exclude-libs=libvpx_assembly_arm.a",
     ]
     if (current_cpu == "arm") {
       ldflags += [
@@ -584,7 +450,7 @@
 }
 
 config("compiler_arm_fpu") {
-  if (current_cpu == "arm" && !is_ios) {
+  if (current_cpu == "arm") {
     cflags = [ "-mfpu=$arm_fpu" ]
   }
 }
@@ -833,19 +699,11 @@
     # TODO(abarth): Re-enable once https://github.com/domokit/mojo/issues/728
     #               is fixed.
     # default_warning_flags += [ "-Wnewline-eof" ]
-    if (!is_nacl) {
-      # When compiling Objective-C, warns if a method is used whose
-      # availability is newer than the deployment target. This is not
-      # required when compiling Chrome for iOS.
-      default_warning_flags += [ "-Wpartial-availability" ]
-    }
-  }
 
-  if (gcc_version >= 48) {
-    default_warning_flags_cc += [
-      # See comment for -Wno-c++11-narrowing.
-      "-Wno-narrowing",
-    ]
+    # When compiling Objective-C, warns if a method is used whose
+    # availability is newer than the deployment target. This is not
+    # required when compiling Chrome for iOS.
+    default_warning_flags += [ "-Wpartial-availability" ]
   }
 
   # Suppress warnings about ABI changes on ARM (Clang doesn't give this
@@ -883,43 +741,6 @@
     default_warning_flags += [ "-Wno-unused-local-typedefs" ]
   }
 }
-if (is_clang) {
-  default_warning_flags += [
-    # This warns on using ints as initializers for floats in
-    # initializer lists (e.g. |int a = f(); CGSize s = { a, a };|),
-    # which happens in several places in chrome code. Not sure if
-    # this is worth fixing.
-    "-Wno-c++11-narrowing",
-
-    # Don't die on dtoa code that uses a char as an array index.
-    # This is required solely for base/third_party/dmg_fp/dtoa.cc.
-    # TODO(brettw) move this to that project then!
-    "-Wno-char-subscripts",
-
-    # Warns on switches on enums that cover all enum values but
-    # also contain a default: branch. Chrome is full of that.
-    "-Wno-covered-switch-default",
-
-    # Clang considers the `register` keyword as deprecated, but e.g.
-    # code generated by flex (used in angle) contains that keyword.
-    # http://crbug.com/255186
-    "-Wno-deprecated-register",
-  ]
-
-  # NaCl's Clang compiler and Chrome's hermetic Clang compiler will almost
-  # always have different versions. Certain flags may not be recognized by
-  # one version or the other.
-  if (!is_nacl) {
-    # Flags NaCl does not recognize.
-    default_warning_flags += [
-      # TODO(hans): Get this cleaned up, http://crbug.com/428099
-      "-Wno-inconsistent-missing-override",
-
-      # TODO(thakis): Enable this, crbug.com/507717
-      "-Wno-shift-negative-value",
-    ]
-  }
-}
 
 # chromium_code ---------------------------------------------------------------
 #
@@ -935,14 +756,8 @@
       "-Wextra",
     ]
 
-    # In Chromium code, we define __STDC_foo_MACROS in order to get the
-    # C99 macros on Mac and Linux.
-    defines = [
-      "__STDC_CONSTANT_MACROS",
-      "__STDC_FORMAT_MACROS",
-    ]
-
-    if (!using_sanitizer && (!is_linux || !is_clang || is_official_build)) {
+    defines = []
+    if (!using_sanitizer && (!is_linux || !is_clang)) {
       # _FORTIFY_SOURCE isn't really supported by Clang now, see
       # http://llvm.org/bugs/show_bug.cgi?id=16821.
       # It seems to work fine with Ubuntu 12 headers though, so use it in
@@ -975,37 +790,6 @@
     ]
   }
 
-  if (is_linux) {
-    # Don't warn about ignoring the return value from e.g. close(). This is
-    # off by default in some gccs but on by default in others. BSD systems do
-    # not support this option, since they are usually using gcc 4.2.1, which
-    # does not have this flag yet.
-    cflags += [ "-Wno-unused-result" ]
-  }
-
-  if (is_clang) {
-    cflags += [
-      # TODO(mgiuca): Move this suppression into individual third-party
-      # libraries as required. http://crbug.com/505301.
-      "-Wno-overloaded-virtual",
-
-      # Lots of third-party libraries have unused variables. Instead of
-      # suppressing them individually, we just blanket suppress them here.
-      "-Wno-unused-variable",
-    ]
-  }
-
-  if (is_linux || is_android) {
-    cflags += [
-      # Don't warn about printf format problems. This is off by default in gcc
-      # but on in Ubuntu's gcc(!).
-      "-Wno-format",
-    ]
-    cflags_cc += [
-      # Don't warn about hash_map in third-party code.
-      "-Wno-deprecated",
-    ]
-  }
   cflags += default_warning_flags
   cflags_cc += default_warning_flags_cc
 }
@@ -1029,34 +813,6 @@
   }
 }
 
-# Warnings ---------------------------------------------------------------------
-
-# This will generate warnings when using Clang if code generates exit-time
-# destructors, which will slow down closing the program.
-# TODO(thakis): Make this a blacklist instead, http://crbug.com/101600
-config("wexit_time_destructors") {
-  # TODO: Enable on Windows too, http://crbug.com/404525
-  if (is_clang && !is_win) {
-    cflags = [ "-Wexit-time-destructors" ]
-  }
-}
-
-# On Windows compiling on x64, VC will issue a warning when converting
-# size_t to int because it will truncate the value. Our code should not have
-# these warnings and one should use a static_cast or a checked_cast for the
-# conversion depending on the case. However, a lot of code still needs to be
-# fixed. Apply this config to such targets to disable the warning.
-#
-# Note that this can be applied regardless of platform and architecture to
-# clean up the call sites. This will only apply the flag when necessary.
-#
-# TODO(jschuh): crbug.com/167187 fix this and delete this config.
-config("no_size_t_to_int_warning") {
-  if (is_win && current_cpu == "x64") {
-    cflags = [ "/wd4267" ]
-  }
-}
-
 # Optimization -----------------------------------------------------------------
 #
 # Note that BUILDCONFIG.gn sets up a variable "default_optimization_config"
@@ -1066,9 +822,9 @@
 # add back the one you want to override it with:
 #
 #   configs -= default_optimization_config
-#   configs += [ "//build/config/compiler/optimize_max" ]
+#   configs += [ ":optimize_max" ]
 
-# Shared settings for both "optimize" and "optimize_max" configs.
+# Shared settings.
 # IMPORTANT: On Windows "/O1" and "/O2" must go before the common flags.
 if (is_win) {
   common_optimize_on_cflags = [
@@ -1100,25 +856,15 @@
   common_optimize_on_ldflags = []
 
   if (is_android) {
-    if (!using_sanitizer) {
-      common_optimize_on_cflags += [ "-fomit-frame-pointer" ]
-    }
-
-    # TODO(jdduke) Re-enable on mips after resolving linking
-    # issues with libc++ (crbug.com/456380).
-    if (current_cpu != "mipsel" && current_cpu != "mips64el") {
-      common_optimize_on_ldflags += [
-        # Warn in case of text relocations.
-        "-Wl,--warn-shared-textrel",
-      ]
-    }
+    common_optimize_on_ldflags += [
+      # Warn in case of text relocations.
+      "-Wl,--warn-shared-textrel",
+    ]
   }
 
-  if (is_mac || is_ios) {
-    if (symbol_level == 2) {
-      # Mac dead code stripping requires symbols.
-      common_optimize_on_ldflags += [ "-Wl,-dead_strip" ]
-    }
+  if (is_mac) {
+    # Mac dead code stripping requires symbols.
+    common_optimize_on_ldflags += [ "-Wl,-dead_strip" ]
   } else {
     # Non-Mac Posix linker flags.
     common_optimize_on_ldflags += [
@@ -1143,10 +889,10 @@
     # Favor size over speed, /O1 must be before the common flags. The GYP
     # build also specifies /Os and /GF but these are implied by /O1.
     cflags = [ "/O1" ] + common_optimize_on_cflags + [ "/Oi" ]
-  } else if (is_android || is_ios) {
+  } else if (is_android) {
     cflags = [ "-Os" ] + common_optimize_on_cflags  # Favor size over speed.
   } else {
-    cflags = [ "-O2" ] + common_optimize_on_cflags
+    cflags = [ "-O3" ] + common_optimize_on_cflags
   }
   ldflags = common_optimize_on_ldflags
 }
@@ -1159,7 +905,7 @@
       "/Ob0",  # Disable all inlining (on by default).
       "/RTC1",  # Runtime checks for stack frame and uninitialized variables.
     ]
-  } else if (is_android && !android_full_debug) {
+  } else if (is_android) {
     # On Android we kind of optimize some things that don't affect debugging
     # much even when optimization is disabled to get the binary size down.
     cflags = [
@@ -1167,41 +913,13 @@
       "-fdata-sections",
       "-ffunction-sections",
     ]
-    if (!using_sanitizer) {
-      cflags += [ "-fomit-frame-pointer" ]
-    }
     ldflags = common_optimize_on_ldflags
   } else {
-    cflags = [ "-O0" ]
-  }
-}
-
-# Turns up the optimization level. On Windows, this implies whole program
-# optimization and link-time code generation which is very expensive and should
-# be used sparingly.
-config("optimize_max") {
-  ldflags = common_optimize_on_ldflags
-  if (is_win) {
-    # Favor speed over size, /O2 must be before the common flags. The GYP
-    # build also specifies /Ot, /Oi, and /GF, but these are implied by /O2.
-    cflags = [ "/O2" ] + common_optimize_on_cflags
-    if (is_official_build) {
-      # TODO(GYP): TODO(dpranke): Should these only be on in an official
-      # build, or on all the time? For now we'll require official build so
-      # that the compile is clean.
-      cflags += [
-        "/GL",  # Whole program optimization.
-
-        # Disable Warning 4702 ("Unreachable code") for the WPO/PGO builds.
-        # Probably anything that this would catch that wouldn't be caught in a
-        # normal build isn't going to actually be a bug, so the incremental
-        # value of C4702 for PGO builds is likely very small.
-        "/wd4702",
-      ]
-      ldflags += [ "/LTCG" ]
-    }
-  } else {
-    cflags = [ "-O2" ] + common_optimize_on_cflags
+    cflags = [
+      "-O1",
+      "-fdata-sections",
+      "-ffunction-sections",
+    ]
   }
 }
 
@@ -1217,27 +935,9 @@
     }
     ldflags = [ "/DEBUG" ]
   } else {
-    cflags = [ "-g2" ]
-    if (use_debug_fission) {
-      cflags += [ "-gsplit-dwarf" ]
-    }
-  }
-}
-
-config("minimal_symbols") {
-  if (is_win) {
-    # Linker symbols for backtraces only.
-    ldflags = [ "/DEBUG" ]
-  } else {
-    cflags = [ "-g1" ]
-    if (use_debug_fission) {
-      cflags += [ "-gsplit-dwarf" ]
-    }
-  }
-}
-
-config("no_symbols") {
-  if (!is_win) {
-    cflags = [ "-g0" ]
+    cflags = [
+      "-g3",
+      "-ggdb3",
+    ]
   }
 }
diff --git a/build/config/crypto.gni b/build/config/crypto.gni
deleted file mode 100644
index 2cd72d3..0000000
--- a/build/config/crypto.gni
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright (c) 2013 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This file declares build flags for the SSL library configuration.
-#
-# TODO(brettw) this should probably be moved to src/crypto or somewhere, and
-# the global build dependency on it should be removed.
-#
-# PLEASE TRY TO AVOID ADDING FLAGS TO THIS FILE in cases where grit isn't
-# required. See the declare_args block of BUILDCONFIG.gn for advice on how
-# to set up feature flags.
-
-declare_args() {
-  # Use OpenSSL instead of NSS. This is used for all platforms but iOS. (See
-  # http://crbug.com/338886).
-  use_openssl = !is_ios
-}
-
-# True when we're using OpenSSL for representing certificates. When targeting
-# Android, the platform certificate library is used for certificate
-# verification. On other targets, this flag also enables OpenSSL for certificate
-# verification, but this configuration is unsupported.
-use_openssl_certs = is_android
-
-# True if NSS is used for certificate verification. Note that this is
-# independent from use_openssl. It is possible to use OpenSSL for the crypto
-# library, but NSS for the platform certificate library.
-use_nss_certs = false
diff --git a/build/config/features.gni b/build/config/features.gni
deleted file mode 100644
index 93b19dd..0000000
--- a/build/config/features.gni
+++ /dev/null
@@ -1,204 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This file contains Chrome-feature-related build flags (see ui.gni for
-# UI-related ones). These should theoretically be moved to the build files of
-# the features themselves.
-#
-# However, today we have many "bad" dependencies on some of these flags from,
-# e.g. base, so they need to be global to match the GYP configuration. Also,
-# anything that needs a grit define must be in either this file or ui.gni.
-#
-# PLEASE TRY TO AVOID ADDING FLAGS TO THIS FILE in cases where grit isn't
-# required. See the declare_args block of BUILDCONFIG.gn for advice on how
-# to set up feature flags.
-
-import("//build/config/chrome_build.gni")
-if (is_android) {
-  import("//build/config/android/config.gni")
-}
-
-declare_args() {
-  # Multicast DNS.
-  enable_mdns = is_win || is_linux
-
-  enable_plugins = !is_android && !is_ios
-
-  # Enables Native Client support.
-  # TODO(GYP): Get NaCl linking on other platforms.
-  # Also, see if we can always get rid of enable_nacl_untrusted and
-  # enable_pnacl and always build them if enable_nacl is true.
-  # The "is_nacl" part of the condition is needed to ensure that
-  # the untrusted code is built properly; arguably it should be
-  # guarded by "is_nacl" directly rather than enable_nacl_untrusted, but
-  # this will go away when Mac and Win are working and we can just use
-  # the commented out logic.
-  # Eventually we want this to be:
-  #   enable_nacl = !is_ios && !is_android
-  enable_nacl = (is_linux && !is_chromeos && current_cpu == "x64") || is_nacl
-  enable_nacl_untrusted = enable_nacl
-  enable_pnacl = enable_nacl_untrusted
-
-  # If debug_devtools is set to true, JavaScript files for DevTools are stored
-  # as is and loaded from disk. Otherwise, a concatenated file is stored in
-  # resources.pak. It is still possible to load JS files from disk by passing
-  # --debug-devtools cmdline switch.
-  debug_devtools = false
-
-  # Enables WebRTC.
-  # TODO(GYP) make mac and android work.
-  enable_webrtc = !is_ios && !is_mac && !is_android
-
-  # Enables the Media Router.
-  enable_media_router = !is_ios && !is_android
-
-  # Enables proprietary codecs and demuxers; e.g. H264, MOV, AAC, and MP3.
-  # Android OS includes support for proprietary codecs regardless of building
-  # Chromium or Google Chrome. We also ship Google Chrome and Chromecast with
-  # proprietary codecs.
-  # TODO(GYP) The GYP build has || chromecast==1 for this:
-  proprietary_codecs = is_android || is_chrome_branded
-
-  enable_configuration_policy = true
-
-  # Enables support for background apps.
-  enable_background = !is_ios && !is_android
-
-  enable_captive_portal_detection = !is_android && !is_ios
-
-  # Enables use of the session service, which is enabled by default.
-  # Android stores them separately on the Java side.
-  enable_session_service = !is_android && !is_ios
-
-  enable_plugin_installation = is_win || is_mac
-
-  enable_app_list = !is_ios && !is_android
-
-  enable_supervised_users = !is_ios
-
-  enable_autofill_dialog = !is_ios
-
-  enable_google_now = !is_ios && !is_android
-
-  enable_one_click_signin = is_win || is_mac || (is_linux && !is_chromeos)
-
-  enable_remoting = !is_ios && !is_android
-
-  # Enable hole punching for the protected video.
-  enable_video_hole = is_android
-
-  # Enables browser side Content Decryption Modules. Required for embedders
-  # (e.g. Android and ChromeCast) that use a browser side CDM.
-  enable_browser_cdms = is_android
-
-  # Variable safe_browsing is used to control the build time configuration
-  # for safe browsing feature. Safe browsing can be compiled in 4 different
-  # levels: 0 disables it, 1 enables it fully, and 2 enables only UI and
-  # reporting features for use with Data Saver on Mobile, and 3 enables
-  # extended mobile protection via an external API.  When 3 is fully deployed,
-  # it will replace 2.
-  if (is_android) {
-    safe_browsing_mode = 2
-  } else if (is_ios) {
-    safe_browsing_mode = 0
-  } else {
-    safe_browsing_mode = 1
-  }
-}
-
-# Additional dependent variables -----------------------------------------------
-
-# Set the version of CLD.
-#   0: Don't specify the version. This option is for the Finch testing.
-#   1: Use only CLD1.
-#   2: Use only CLD2.
-if (is_android) {
-  cld_version = 1
-} else {
-  cld_version = 2
-}
-
-# libudev usage. This currently only affects the content layer.
-use_udev = is_linux
-
-# Enable the spell checker.
-enable_spellcheck = !is_android
-
-# Use the operating system's spellchecker rather than hunspell.
-use_platform_spellchecker = is_android || is_mac
-
-enable_pepper_cdms = enable_plugins && (is_linux || is_mac || is_win)
-
-# Enable basic printing support and UI.
-enable_basic_printing = !is_chromeos
-
-# Enable printing with print preview. It does not imply
-# enable_basic_printing. It's possible to build Chrome with preview only.
-enable_print_preview = !is_android
-
-# The seccomp-bpf sandbox is only supported on three architectures
-# currently.
-# Do not disable seccomp_bpf anywhere without talking to
-# security@chromium.org!
-use_seccomp_bpf = (is_linux || is_android) &&
-                  (current_cpu == "x86" || current_cpu == "x64" ||
-                   current_cpu == "arm" || current_cpu == "mipsel")
-
-# Enable notifications everywhere except iOS.
-enable_notifications = !is_ios
-
-# TODO(brettw) this should be moved to net and only dependents get this define.
-disable_ftp_support = is_ios
-
-enable_web_speech = !is_android && !is_ios
-
-use_dbus = is_linux
-
-enable_extensions = !is_android && !is_ios
-
-enable_task_manager = !is_ios && !is_android
-
-use_cups = is_desktop_linux || is_mac
-
-enable_themes = !is_android && !is_ios
-
-# TODO(scottmg) remove this when we've fixed printing.
-win_pdf_metafile_for_printing = true
-
-# Whether we are using the rlz library or not.  Platforms like Android send
-# rlz codes for searches but do not use the library.
-enable_rlz_support = is_win || is_mac || is_ios || is_chromeos
-enable_rlz = is_chrome_branded && enable_rlz_support
-
-enable_settings_app = enable_app_list && !is_chromeos
-
-enable_service_discovery = enable_mdns || is_mac
-
-enable_wifi_bootstrapping = is_win || is_mac
-
-# Image loader extension is enabled on ChromeOS only.
-enable_image_loader_extension = is_chromeos
-
-# Chrome OS: whether to also build the upcoming version of
-# ChromeVox, which can then be enabled via a command-line switch.
-enable_chromevox_next = false
-
-# Use brlapi from brltty for braille display support.
-use_brlapi = is_chromeos
-
-# Option controlling the use of GConf (the classic GNOME configuration
-# system).
-# TODO(GYP) also require !embedded to enable.
-use_gconf = is_linux && !is_chromeos
-
-# Hangout services is an extension that adds extra features to Hangouts.
-# For official GYP builds, this flag is set, it will likely need to be
-# parameterized in the future for a similar use.
-enable_hangout_services_extension = false
-
-# Whether to back up data before sync.
-enable_pre_sync_backup = is_win || is_mac || (is_linux && !is_chromeos)
-
-# WebVR support disabled until platform implementations have been added
-enable_webvr = false
diff --git a/build/config/linux/BUILD.gn b/build/config/linux/BUILD.gn
index 71a73b2..4b02a25 100644
--- a/build/config/linux/BUILD.gn
+++ b/build/config/linux/BUILD.gn
@@ -2,10 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/config/linux/pkg_config.gni")
-import("//build/config/features.gni")
 import("//build/config/sysroot.gni")
-import("//build/config/ui.gni")
 
 config("sdk") {
   if (sysroot != "") {
@@ -22,41 +19,3 @@
                              "value") ]
   }
 }
-
-config("fontconfig") {
-  libs = [ "fontconfig" ]
-}
-
-pkg_config("freetype2") {
-  packages = [ "freetype2" ]
-}
-
-config("x11") {
-  libs = [
-    "X11",
-    "Xcomposite",
-    "Xcursor",
-    "Xdamage",
-    "Xext",
-    "Xfixes",
-    "Xi",
-    "Xrender",
-    "Xtst",
-  ]
-}
-
-config("xrandr") {
-  libs = [ "Xrandr" ]
-}
-
-config("xinerama") {
-  libs = [ "Xinerama" ]
-}
-
-config("xcomposite") {
-  libs = [ "Xcomposite" ]
-}
-
-config("xext") {
-  libs = [ "Xext" ]
-}
diff --git a/build/config/sysroot.gni b/build/config/sysroot.gni
index 5bce02e..37faae0 100644
--- a/build/config/sysroot.gni
+++ b/build/config/sysroot.gni
@@ -5,8 +5,6 @@
 # This header file defines the "sysroot" variable which is the absolute path
 # of the sysroot. If no sysroot applies, the variable will be an empty string.
 
-import("//build/config/chrome_build.gni")
-
 declare_args() {
   # The absolute path of the sysroot that is applied when compiling using
   # the target toolchain.
@@ -32,29 +30,9 @@
   } else {
     sysroot = ""
   }
-} else if (is_linux && is_chrome_branded && is_official_build && !is_chromeos) {
-  # For official builds, use the sysroot checked into the internal source repo
-  # so that the builds work on older versions of Linux.
-  if (current_cpu == "x64") {
-    sysroot = rebase_path("//build/linux/debian_wheezy_amd64-sysroot")
-  } else if (current_cpu == "x86") {
-    sysroot = rebase_path("//build/linux/debian_wheezy_i386-sysroot")
-  } else {
-    # Any other builds don't use a sysroot.
-    sysroot = ""
-  }
-} else if (is_linux && !is_chromeos) {
-  if (current_cpu == "mipsel") {
-    sysroot = rebase_path("//mipsel-sysroot/sysroot")
-  } else {
-    sysroot = ""
-  }
 } else if (is_mac) {
   import("//build/config/mac/mac_sdk.gni")
   sysroot = mac_sdk_path
-} else if (is_ios) {
-  import("//build/config/ios/ios_sdk.gni")
-  sysroot = ios_sdk_path
 } else {
   sysroot = ""
 }
diff --git a/build/config/ui.gni b/build/config/ui.gni
deleted file mode 100644
index c2dff4a..0000000
--- a/build/config/ui.gni
+++ /dev/null
@@ -1,68 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This file contains UI-related build flags. It should theoretically be in the
-# src/ui directory and only things that depend on the ui module should get the
-# definitions.
-#
-# However, today we have many "bad" dependencies on some of these flags from,
-# e.g. base, so they need to be global.
-#
-# See also build/config/features.gni
-
-declare_args() {
-  # Indicates if Ash is enabled. Ash is the Aura Shell which provides a
-  # desktop-like environment for Aura. Requires use_aura = true
-  use_ash = is_win || is_linux
-
-  # Indicates if Ozone is enabled. Ozone is a low-level library layer for Linux
-  # that does not require X11.
-  use_ozone = false
-
-  # Indicates if GLFW is enabled. GLFW is an abstraction layer for the
-  # windowing system and OpenGL rendering, providing cross-platform support
-  # for creating windows and OpenGL surfaces and contexts, and handling
-  # window system events and input.
-  use_glfw = false
-
-  # Support ChromeOS touchpad gestures with ozone.
-  use_evdev_gestures = false
-
-  # Indicates if Aura is enabled. Aura is a low-level windowing library, sort
-  # of a replacement for GDI or GTK.
-  use_aura = is_win || is_linux
-
-  # True means the UI is built using the "views" framework.
-  toolkit_views = is_mac || is_win || is_chromeos || use_aura
-
-  # Whether the entire browser uses toolkit-views on Mac instead of Cocoa.
-  mac_views_browser = false
-
-  # Whether we should use glib, a low level C utility library.
-  use_glib = is_linux && !use_ozone
-}
-
-# Additional dependent variables -----------------------------------------------
-#
-# These variables depend on other variables and can't be set externally.
-
-use_cairo = false
-use_pango = false
-
-# Use GPU accelerated cross process image transport by default on linux builds
-# with the Aura window manager.
-ui_compositor_image_transport = use_aura && is_linux
-
-use_default_render_theme = use_aura || is_linux
-
-# Indicates if the UI toolkit depends on X11.
-use_x11 = is_linux && !use_ozone && !use_glfw
-
-use_ozone_evdev = use_ozone
-
-use_clipboard_aurax11 = is_linux && use_aura && use_x11
-
-enable_hidpi = is_mac || is_chromeos || is_win || is_linux
-
-enable_topchrome_md = false
diff --git a/build/config/win/BUILD.gn b/build/config/win/BUILD.gn
index 261a1ac..c939100 100644
--- a/build/config/win/BUILD.gn
+++ b/build/config/win/BUILD.gn
@@ -141,7 +141,7 @@
 # config should be applied to large modules to turn off incremental linking
 # when it won't work.
 config("default_large_module_incremental_linking") {
-  if (symbol_level > 0 && (current_cpu == "x86" || !is_component_build)) {
+  if (current_cpu == "x86" || !is_component_build) {
     # When symbols are on, things get so large that the tools fail due to the
     # size of the .ilk files.
     ldflags = incremental_linking_off_switch
diff --git a/build/gyp_chromium b/build/gyp_chromium
deleted file mode 100755
index 9dac871..0000000
--- a/build/gyp_chromium
+++ /dev/null
@@ -1,333 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This script is wrapper for Chromium that adds some support for how GYP
-# is invoked by Chromium beyond what can be done in the gclient hooks.
-
-import argparse
-import glob
-import gyp_environment
-import os
-import re
-import shlex
-import subprocess
-import string
-import sys
-import vs_toolchain
-
-script_dir = os.path.dirname(os.path.realpath(__file__))
-chrome_src = os.path.abspath(os.path.join(script_dir, os.pardir))
-
-sys.path.insert(0, os.path.join(chrome_src, 'tools', 'gyp', 'pylib'))
-import gyp
-
-# Assume this file is in a one-level-deep subdirectory of the source root.
-SRC_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-
-# Add paths so that pymod_do_main(...) can import files.
-sys.path.insert(1, os.path.join(chrome_src, 'android_webview', 'tools'))
-sys.path.insert(1, os.path.join(chrome_src, 'build', 'android', 'gyp'))
-sys.path.insert(1, os.path.join(chrome_src, 'chrome', 'tools', 'build'))
-sys.path.insert(1, os.path.join(chrome_src, 'chromecast', 'tools', 'build'))
-sys.path.insert(1, os.path.join(chrome_src, 'ios', 'chrome', 'tools', 'build'))
-sys.path.insert(1, os.path.join(chrome_src, 'native_client', 'build'))
-sys.path.insert(1, os.path.join(chrome_src, 'native_client_sdk', 'src',
-    'build_tools'))
-sys.path.insert(1, os.path.join(chrome_src, 'remoting', 'tools', 'build'))
-sys.path.insert(1, os.path.join(chrome_src, 'third_party', 'liblouis'))
-sys.path.insert(1, os.path.join(chrome_src, 'third_party', 'WebKit',
-    'Source', 'build', 'scripts'))
-sys.path.insert(1, os.path.join(chrome_src, 'tools'))
-sys.path.insert(1, os.path.join(chrome_src, 'tools', 'generate_shim_headers'))
-sys.path.insert(1, os.path.join(chrome_src, 'tools', 'grit'))
-
-# On Windows, Psyco shortens warm runs of build/gyp_chromium by about
-# 20 seconds on a z600 machine with 12 GB of RAM, from 90 down to 70
-# seconds.  Conversely, memory usage of build/gyp_chromium with Psyco
-# maxes out at about 158 MB vs. 132 MB without it.
-#
-# Psyco uses native libraries, so we need to load a different
-# installation depending on which OS we are running under. It has not
-# been tested whether using Psyco on our Mac and Linux builds is worth
-# it (the GYP running time is a lot shorter, so the JIT startup cost
-# may not be worth it).
-if sys.platform == 'win32':
-  try:
-    sys.path.insert(0, os.path.join(chrome_src, 'third_party', 'psyco_win32'))
-    import psyco
-  except:
-    psyco = None
-else:
-  psyco = None
-
-
-def GetSupplementalFiles():
-  """Returns a list of the supplemental files that are included in all GYP
-  sources."""
-  return glob.glob(os.path.join(chrome_src, '*', 'supplement.gypi'))
-
-
-def ProcessGypDefinesItems(items):
-  """Converts a list of strings to a list of key-value pairs."""
-  result = []
-  for item in items:
-    tokens = item.split('=', 1)
-    # Some GYP variables have hyphens, which we don't support.
-    if len(tokens) == 2:
-      result += [(tokens[0], tokens[1])]
-    else:
-      # No value supplied, treat it as a boolean and set it. Note that we
-      # use the string '1' here so we have a consistent definition whether
-      # you do 'foo=1' or 'foo'.
-      result += [(tokens[0], '1')]
-  return result
-
-
-def GetGypVars(supplemental_files):
-  """Returns a dictionary of all GYP vars."""
-  # Find the .gyp directory in the user's home directory.
-  home_dot_gyp = os.environ.get('GYP_CONFIG_DIR', None)
-  if home_dot_gyp:
-    home_dot_gyp = os.path.expanduser(home_dot_gyp)
-  if not home_dot_gyp:
-    home_vars = ['HOME']
-    if sys.platform in ('cygwin', 'win32'):
-      home_vars.append('USERPROFILE')
-    for home_var in home_vars:
-      home = os.getenv(home_var)
-      if home != None:
-        home_dot_gyp = os.path.join(home, '.gyp')
-        if not os.path.exists(home_dot_gyp):
-          home_dot_gyp = None
-        else:
-          break
-
-  if home_dot_gyp:
-    include_gypi = os.path.join(home_dot_gyp, "include.gypi")
-    if os.path.exists(include_gypi):
-      supplemental_files += [include_gypi]
-
-  # GYP defines from the supplemental.gypi files.
-  supp_items = []
-  for supplement in supplemental_files:
-    with open(supplement, 'r') as f:
-      try:
-        file_data = eval(f.read(), {'__builtins__': None}, None)
-      except SyntaxError, e:
-        e.filename = os.path.abspath(supplement)
-        raise
-      variables = file_data.get('variables', [])
-      for v in variables:
-        supp_items += [(v, str(variables[v]))]
-
-  # GYP defines from the environment.
-  env_items = ProcessGypDefinesItems(
-      shlex.split(os.environ.get('GYP_DEFINES', '')))
-
-  # GYP defines from the command line.
-  parser = argparse.ArgumentParser()
-  parser.add_argument('-D', dest='defines', action='append', default=[])
-  cmdline_input_items = parser.parse_known_args()[0].defines
-  cmdline_items = ProcessGypDefinesItems(cmdline_input_items)
-
-  vars_dict = dict(supp_items + env_items + cmdline_items)
-  return vars_dict
-
-
-def GetOutputDirectory():
-  """Returns the output directory that GYP will use."""
-
-  # Handle command line generator flags.
-  parser = argparse.ArgumentParser()
-  parser.add_argument('-G', dest='genflags', default=[], action='append')
-  genflags = parser.parse_known_args()[0].genflags
-
-  # Handle generator flags from the environment.
-  genflags += shlex.split(os.environ.get('GYP_GENERATOR_FLAGS', ''))
-
-  needle = 'output_dir='
-  for item in genflags:
-    if item.startswith(needle):
-      return item[len(needle):]
-
-  return 'out'
-
-
-def additional_include_files(supplemental_files, args=[]):
-  """
-  Returns a list of additional (.gypi) files to include, without duplicating
-  ones that are already specified on the command line. The list of supplemental
-  include files is passed in as an argument.
-  """
-  # Determine the include files specified on the command line.
-  # This doesn't cover all the different option formats you can use,
-  # but it's mainly intended to avoid duplicating flags on the automatic
-  # makefile regeneration which only uses this format.
-  specified_includes = set()
-  for arg in args:
-    if arg.startswith('-I') and len(arg) > 2:
-      specified_includes.add(os.path.realpath(arg[2:]))
-
-  result = []
-  def AddInclude(path):
-    if os.path.realpath(path) not in specified_includes:
-      result.append(path)
-
-  if os.environ.get('GYP_INCLUDE_FIRST') != None:
-    AddInclude(os.path.join(chrome_src, os.environ.get('GYP_INCLUDE_FIRST')))
-
-  # Always include common.gypi.
-  AddInclude(os.path.join(script_dir, 'common.gypi'))
-
-  # Optionally add supplemental .gypi files if present.
-  for supplement in supplemental_files:
-    AddInclude(supplement)
-
-  if os.environ.get('GYP_INCLUDE_LAST') != None:
-    AddInclude(os.path.join(chrome_src, os.environ.get('GYP_INCLUDE_LAST')))
-
-  return result
-
-
-if __name__ == '__main__':
-  # Disabling garbage collection saves about 1 second out of 16 on a Linux
-  # z620 workstation. Since this is a short-lived process it's not a problem to
-  # leak a few cyclyc references in order to spare the CPU cycles for
-  # scanning the heap.
-  import gc
-  gc.disable()
-
-  args = sys.argv[1:]
-
-  use_analyzer = len(args) and args[0] == '--analyzer'
-  if use_analyzer:
-    args.pop(0)
-    os.environ['GYP_GENERATORS'] = 'analyzer'
-    args.append('-Gconfig_path=' + args.pop(0))
-    args.append('-Ganalyzer_output_path=' + args.pop(0))
-
-  if int(os.environ.get('GYP_CHROMIUM_NO_ACTION', 0)):
-    print 'Skipping gyp_chromium due to GYP_CHROMIUM_NO_ACTION env var.'
-    sys.exit(0)
-
-  # Use the Psyco JIT if available.
-  if psyco:
-    psyco.profile()
-    print "Enabled Psyco JIT."
-
-  # Fall back on hermetic python if we happen to get run under cygwin.
-  # TODO(bradnelson): take this out once this issue is fixed:
-  #    http://code.google.com/p/gyp/issues/detail?id=177
-  if sys.platform == 'cygwin':
-    import find_depot_tools
-    depot_tools_path = find_depot_tools.add_depot_tools_to_path()
-    python_dir = sorted(glob.glob(os.path.join(depot_tools_path,
-                                               'python2*_bin')))[-1]
-    env = os.environ.copy()
-    env['PATH'] = python_dir + os.pathsep + env.get('PATH', '')
-    cmd = [os.path.join(python_dir, 'python.exe')] + sys.argv
-    sys.exit(subprocess.call(cmd, env=env))
-
-  # This could give false positives since it doesn't actually do real option
-  # parsing.  Oh well.
-  gyp_file_specified = any(arg.endswith('.gyp') for arg in args)
-
-  gyp_environment.SetEnvironment()
-
-  # If we didn't get a file, check an env var, and then fall back to
-  # assuming 'all.gyp' from the same directory as the script.
-  if not gyp_file_specified:
-    gyp_file = os.environ.get('CHROMIUM_GYP_FILE')
-    if gyp_file:
-      # Note that CHROMIUM_GYP_FILE values can't have backslashes as
-      # path separators even on Windows due to the use of shlex.split().
-      args.extend(shlex.split(gyp_file))
-    else:
-      args.append(os.path.join(script_dir, 'all.gyp'))
-
-  supplemental_includes = GetSupplementalFiles()
-  gyp_vars_dict = GetGypVars(supplemental_includes)
-  # There shouldn't be a circular dependency relationship between .gyp files,
-  # but in Chromium's .gyp files, on non-Mac platforms, circular relationships
-  # currently exist.  The check for circular dependencies is currently
-  # bypassed on other platforms, but is left enabled on iOS, where a violation
-  # of the rule causes Xcode to misbehave badly.
-  # TODO(mark): Find and kill remaining circular dependencies, and remove this
-  # option.  http://crbug.com/35878.
-  # TODO(tc): Fix circular dependencies in ChromiumOS then add linux2 to the
-  # list.
-  if gyp_vars_dict.get('OS') != 'ios':
-    args.append('--no-circular-check')
-
-  # libtool on Mac warns about duplicate basenames in static libraries, so
-  # they're disallowed in general by gyp. We are lax on this point, so disable
-  # this check other than on Mac. GN does not use static libraries as heavily,
-  # so over time this restriction will mostly go away anyway, even on Mac.
-  # https://code.google.com/p/gyp/issues/detail?id=384
-  if sys.platform != 'darwin':
-    args.append('--no-duplicate-basename-check')
-
-  # We explicitly don't support the make gyp generator (crbug.com/348686). Be
-  # nice and fail here, rather than choking in gyp.
-  if re.search(r'(^|,|\s)make($|,|\s)', os.environ.get('GYP_GENERATORS', '')):
-    print 'Error: make gyp generator not supported (check GYP_GENERATORS).'
-    sys.exit(1)
-
-  # We explicitly don't support the native msvs gyp generator. Be nice and
-  # fail here, rather than generating broken projects.
-  if re.search(r'(^|,|\s)msvs($|,|\s)', os.environ.get('GYP_GENERATORS', '')):
-    print 'Error: msvs gyp generator not supported (check GYP_GENERATORS).'
-    print 'Did you mean to use the `msvs-ninja` generator?'
-    sys.exit(1)
-
-  # If CHROMIUM_GYP_SYNTAX_CHECK is set to 1, it will invoke gyp with --check
-  # to enfore syntax checking.
-  syntax_check = os.environ.get('CHROMIUM_GYP_SYNTAX_CHECK')
-  if syntax_check and int(syntax_check):
-    args.append('--check')
-
-  # TODO(dmikurube): Remove these checks and messages after a while.
-  if ('linux_use_tcmalloc' in gyp_vars_dict or
-      'android_use_tcmalloc' in gyp_vars_dict):
-    print '*****************************************************************'
-    print '"linux_use_tcmalloc" and "android_use_tcmalloc" are deprecated!'
-    print '-----------------------------------------------------------------'
-    print 'You specify "linux_use_tcmalloc" or "android_use_tcmalloc" in'
-    print 'your GYP_DEFINES. Please switch them into "use_allocator" now.'
-    print 'See http://crbug.com/345554 for the details.'
-    print '*****************************************************************'
-
-  # Automatically turn on crosscompile support for platforms that need it.
-  # (The Chrome OS build sets CC_host / CC_target which implicitly enables
-  # this mode.)
-  if all(('ninja' in os.environ.get('GYP_GENERATORS', ''),
-          gyp_vars_dict.get('OS') in ['android', 'ios'],
-          'GYP_CROSSCOMPILE' not in os.environ)):
-    os.environ['GYP_CROSSCOMPILE'] = '1'
-  if gyp_vars_dict.get('OS') == 'android':
-    args.append('--check')
-
-  args.extend(
-      ['-I' + i for i in additional_include_files(supplemental_includes, args)])
-
-  args.extend(['-D', 'gyp_output_dir=' + GetOutputDirectory()])
-
-  if not use_analyzer:
-    print 'Updating projects from gyp files...'
-    sys.stdout.flush()
-
-  # Off we go...
-  gyp_rc = gyp.main(args)
-
-  if not use_analyzer:
-    vs2013_runtime_dll_dirs = vs_toolchain.SetEnvironmentAndGetRuntimeDllDirs()
-    if vs2013_runtime_dll_dirs:
-      x64_runtime, x86_runtime = vs2013_runtime_dll_dirs
-      vs_toolchain.CopyVsRuntimeDlls(
-        os.path.join(chrome_src, GetOutputDirectory()),
-        (x86_runtime, x64_runtime))
-
-  sys.exit(gyp_rc)
diff --git a/build/gyp_chromium.py b/build/gyp_chromium.py
deleted file mode 100644
index f9e8ac8..0000000
--- a/build/gyp_chromium.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This file is (possibly, depending on python version) imported by
-# gyp_chromium when GYP_PARALLEL=1 and it creates sub-processes
-# through the multiprocessing library.
-
-# Importing in Python 2.6 (fixed in 2.7) on Windows doesn't search for
-# imports that don't end in .py (and aren't directories with an
-# __init__.py). This wrapper makes "import gyp_chromium" work with
-# those old versions and makes it possible to execute gyp_chromium.py
-# directly on Windows where the extension is useful.
-
-import os
-
-path = os.path.abspath(os.path.split(__file__)[0])
-execfile(os.path.join(path, 'gyp_chromium'))
diff --git a/build/gyp_chromium_test.py b/build/gyp_chromium_test.py
deleted file mode 100755
index 0c0e479..0000000
--- a/build/gyp_chromium_test.py
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import os
-import sys
-import unittest
-
-SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__))
-SRC_DIR = os.path.dirname(SCRIPT_DIR)
-
-sys.path.append(os.path.join(SRC_DIR, 'third_party', 'pymock'))
-
-import mock
-
-# TODO(sbc): Make gyp_chromium more testable by putting the code in
-# a .py file.
-gyp_chromium = __import__('gyp_chromium')
-
-
-class TestGetOutputDirectory(unittest.TestCase):
-  @mock.patch('os.environ', {})
-  @mock.patch('sys.argv', [__file__])
-  def testDefaultValue(self):
-    self.assertEqual(gyp_chromium.GetOutputDirectory(), 'out')
-
-  @mock.patch('os.environ', {'GYP_GENERATOR_FLAGS': 'output_dir=envfoo'})
-  @mock.patch('sys.argv', [__file__])
-  def testEnvironment(self):
-    self.assertEqual(gyp_chromium.GetOutputDirectory(), 'envfoo')
-
-  @mock.patch('os.environ', {'GYP_GENERATOR_FLAGS': 'output_dir=envfoo'})
-  @mock.patch('sys.argv', [__file__, '-Goutput_dir=cmdfoo'])
-  def testGFlagOverridesEnv(self):
-    self.assertEqual(gyp_chromium.GetOutputDirectory(), 'cmdfoo')
-
-  @mock.patch('os.environ', {})
-  @mock.patch('sys.argv', [__file__, '-G', 'output_dir=foo'])
-  def testGFlagWithSpace(self):
-    self.assertEqual(gyp_chromium.GetOutputDirectory(), 'foo')
-
-
-class TestGetGypVars(unittest.TestCase):
-  @mock.patch('os.environ', {})
-  def testDefault(self):
-    self.assertEqual(gyp_chromium.GetGypVars([]), {})
-
-  @mock.patch('os.environ', {})
-  @mock.patch('sys.argv', [__file__, '-D', 'foo=bar'])
-  def testDFlags(self):
-    self.assertEqual(gyp_chromium.GetGypVars([]), {'foo': 'bar'})
-
-  @mock.patch('os.environ', {})
-  @mock.patch('sys.argv', [__file__, '-D', 'foo'])
-  def testDFlagsNoValue(self):
-    self.assertEqual(gyp_chromium.GetGypVars([]), {'foo': '1'})
-
-  @mock.patch('os.environ', {})
-  @mock.patch('sys.argv', [__file__, '-D', 'foo=bar', '-Dbaz'])
-  def testDFlagMulti(self):
-    self.assertEqual(gyp_chromium.GetGypVars([]), {'foo': 'bar', 'baz': '1'})
-
-
-if __name__ == '__main__':
-  unittest.main()
diff --git a/build/json_schema_api.gni b/build/json_schema_api.gni
deleted file mode 100644
index e1c2d33..0000000
--- a/build/json_schema_api.gni
+++ /dev/null
@@ -1,242 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# Defines a static library corresponding to the output of schema compiler tools
-# over a set of extensions API schemas (IDL or JSON format.) The library target
-# has implicit hard dependencies on all schema files listed by the invoker and
-# is itself a hard dependency.
-#
-# Invocations of this template may use the following variables:
-#
-# sources [required] A list of schema files to be compiled.
-#
-# root_namespace [required]
-#     A Python string substituion pattern used to generate the C++
-#     namespace for each API. Use %(namespace)s to replace with the API
-#     namespace, like "toplevel::%(namespace)s_api".
-#
-# schema_include_rules [optional]
-#     A list of paths to include when searching for referenced objects,
-#     with the namespace separated by a :.
-#     Example:
-#       [ '/foo/bar:Foo::Bar::%(namespace)s' ]
-#
-# schemas [optional, default = false]
-#   Boolean indicating if the schema files should be generated.
-#
-# bundle [optional, default = false]
-#   Boolean indicating if the schema bundle files should be generated.
-#
-# bundle_registration [optional, default = false]
-#   Boolean indicating if the API registration bundle files should be generated.
-#
-# impl_dir [required if bundle_registration = true, otherwise unused]
-#   The path containing C++ implementations of API functions. This path is
-#   used as the root path when looking for {schema}/{schema}_api.h headers
-#   when generating API registration bundles. Such headers, if found, are
-#   automatically included by the generated code.
-#
-# uncompiled_sources [optional, only used when bundle = true or
-#     bundle_registration = true]
-#   A list of schema files which should not be compiled, but which should still
-#   be processed for API bundle generation.
-#
-# deps [optional]
-#   If any deps are specified they will be inherited by the static library
-#   target.
-#
-# generate_static_library [optional, defaults to false]
-#   Produces a static library instead of a source_set.
-#
-# The generated library target also inherits the visibility and output_name
-# of its invoker.
-
-template("json_schema_api") {
-  assert(defined(invoker.sources),
-         "\"sources\" must be defined for the $target_name template.")
-  assert(defined(invoker.root_namespace),
-         "\"root_namespace\" must be defined for the $target_name template.")
-
-  schemas = defined(invoker.schemas) && invoker.schemas
-  bundle = defined(invoker.bundle) && invoker.bundle
-  bundle_registration =
-      defined(invoker.bundle_registration) && invoker.bundle_registration
-
-  schema_include_rules = ""
-  if (defined(invoker.schema_include_rules)) {
-    schema_include_rules = invoker.schema_include_rules
-  }
-
-  # Keep a copy of the target_name here since it will be trampled
-  # in nested targets.
-  target_visibility = [ ":$target_name" ]
-
-  generated_config_name = target_name + "_generated_config"
-  config(generated_config_name) {
-    include_dirs = [ root_gen_dir ]
-    visibility = target_visibility
-  }
-
-  root_namespace = invoker.root_namespace
-
-  compiler_root = "//tools/json_schema_compiler"
-  compiler_script = "$compiler_root/compiler.py"
-  compiler_sources = [
-    "$compiler_root/cc_generator.py",
-    "$compiler_root/code.py",
-    "$compiler_root/compiler.py",
-    "$compiler_root/cpp_generator.py",
-    "$compiler_root/cpp_type_generator.py",
-    "$compiler_root/cpp_util.py",
-    "$compiler_root/h_generator.py",
-    "$compiler_root/idl_schema.py",
-    "$compiler_root/model.py",
-    "$compiler_root/util_cc_helper.py",
-  ]
-
-  if (schemas) {
-    schema_generator_name = target_name + "_schema_generator"
-    action_foreach(schema_generator_name) {
-      script = compiler_script
-      sources = invoker.sources
-      inputs = compiler_sources
-      outputs = [
-        "$target_gen_dir/{{source_name_part}}.cc",
-        "$target_gen_dir/{{source_name_part}}.h",
-      ]
-      args = [
-        "{{source}}",
-        "--root=" + rebase_path("//", root_build_dir),
-        "--destdir=" + rebase_path(root_gen_dir, root_build_dir),
-        "--namespace=$root_namespace",
-        "--generator=cpp",
-        "--include-rules=$schema_include_rules",
-      ]
-
-      if (defined(invoker.visibility)) {
-        # If visibility is restricted, add our own target to it.
-        visibility = invoker.visibility + target_visibility
-      }
-    }
-  }
-
-  if (bundle) {
-    uncompiled_sources = []
-    if (defined(invoker.uncompiled_sources)) {
-      uncompiled_sources = invoker.uncompiled_sources
-    }
-
-    bundle_generator_schema_name = target_name + "_bundle_generator_schema"
-    action(bundle_generator_schema_name) {
-      script = compiler_script
-      inputs = compiler_sources + invoker.sources + uncompiled_sources
-      outputs = [
-        "$target_gen_dir/generated_schemas.cc",
-        "$target_gen_dir/generated_schemas.h",
-      ]
-      args = [
-               "--root=" + rebase_path("//", root_build_dir),
-               "--destdir=" + rebase_path(root_gen_dir, root_build_dir),
-               "--namespace=$root_namespace",
-               "--generator=cpp-bundle-schema",
-               "--include-rules=$schema_include_rules",
-             ] + rebase_path(invoker.sources, root_build_dir) +
-             rebase_path(uncompiled_sources, root_build_dir)
-    }
-  }
-
-  if (bundle_registration) {
-    uncompiled_sources = []
-    if (defined(invoker.uncompiled_sources)) {
-      uncompiled_sources = invoker.uncompiled_sources
-    }
-
-    assert(defined(invoker.impl_dir),
-           "\"impl_dir\" must be defined for the $target_name template.")
-
-    # Child directory inside the generated file tree.
-    gen_child_dir = rebase_path(invoker.impl_dir, "//")
-
-    bundle_generator_registration_name =
-        target_name + "_bundle_generator_registration"
-    action(bundle_generator_registration_name) {
-      script = compiler_script
-      inputs = compiler_sources + invoker.sources + uncompiled_sources
-      outputs = [
-        "$root_gen_dir/$gen_child_dir/generated_api_registration.cc",
-        "$root_gen_dir/$gen_child_dir/generated_api_registration.h",
-      ]
-      args = [
-               "--root=" + rebase_path("//", root_build_dir),
-               "--destdir=" + rebase_path(root_gen_dir, root_build_dir),
-               "--namespace=$root_namespace",
-               "--generator=cpp-bundle-registration",
-               "--impl-dir=$gen_child_dir",
-               "--include-rules=$schema_include_rules",
-             ] + rebase_path(invoker.sources, root_build_dir) +
-             rebase_path(uncompiled_sources, root_build_dir)
-    }
-  }
-
-  # Compute the contents of the library/source set.
-  lib_sources = invoker.sources
-  lib_deps = []
-  lib_public_deps = []
-  lib_extra_configs = []
-
-  if (schemas) {
-    lib_sources += get_target_outputs(":$schema_generator_name")
-    lib_public_deps += [ ":$schema_generator_name" ]
-    lib_deps += [ "//tools/json_schema_compiler:generated_api_util" ]
-    lib_extra_configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
-  }
-
-  if (bundle) {
-    lib_sources += get_target_outputs(":$bundle_generator_schema_name")
-    lib_deps += [ ":$bundle_generator_schema_name" ]
-  }
-
-  if (bundle_registration) {
-    lib_sources += get_target_outputs(":$bundle_generator_registration_name")
-    lib_deps += [ ":$bundle_generator_registration_name" ]
-  }
-
-  if (defined(invoker.deps)) {
-    lib_deps += invoker.deps
-  }
-
-  # Generate either a static library or a source set.
-  if (defined(invoker.generate_static_library) &&
-      invoker.generate_static_library) {
-    static_library(target_name) {
-      sources = lib_sources
-      deps = lib_deps
-      public_deps = lib_public_deps
-      configs += lib_extra_configs
-      public_configs = [ ":$generated_config_name" ]
-
-      if (defined(invoker.visibility)) {
-        visibility = invoker.visibility
-      }
-      if (defined(invoker.output_name)) {
-        output_name = invoker.output_name
-      }
-    }
-  } else {
-    source_set(target_name) {
-      sources = lib_sources
-      deps = lib_deps
-      public_deps = lib_public_deps
-      configs += lib_extra_configs
-      public_configs = [ ":$generated_config_name" ]
-
-      if (defined(invoker.visibility)) {
-        visibility = invoker.visibility
-      }
-      if (defined(invoker.output_name)) {
-        output_name = invoker.output_name
-      }
-    }
-  }
-}
diff --git a/build/json_schema_bundle_compile.gypi b/build/json_schema_bundle_compile.gypi
deleted file mode 100644
index a302013..0000000
--- a/build/json_schema_bundle_compile.gypi
+++ /dev/null
@@ -1,83 +0,0 @@
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-{
-  'variables': {
-    # When including this gypi, the following variables must be set:
-    #   schema_files:
-    #     An array of json or idl files that comprise the api model.
-    #   schema_include_rules (optional):
-    #     An array of paths to include when searching for referenced objects,
-    #     with the namespace separated by a :.
-    #     Example:
-    #       [ '/foo/bar:Foo::Bar::%(namespace)s' ]
-    #   cc_dir:
-    #     The directory to put the generated code in.
-    #   root_namespace:
-    #     A Python string substituion pattern used to generate the C++
-    #     namespace for each API. Use %(namespace)s to replace with the API
-    #     namespace, like "toplevel::%(namespace)s_api".
-    #
-    # Functions and namespaces can be excluded by setting "nocompile" to true.
-    # The default root path of API implementation sources is
-    # chrome/browser/extensions/api and can be overridden by setting "impl_dir".
-    'api_gen_dir': '<(DEPTH)/tools/json_schema_compiler',
-    'api_gen': '<(api_gen_dir)/compiler.py',
-    'generator_files': [
-      '<(api_gen_dir)/cc_generator.py',
-      '<(api_gen_dir)/code.py',
-      '<(api_gen_dir)/compiler.py',
-      '<(api_gen_dir)/cpp_bundle_generator.py',
-      '<(api_gen_dir)/cpp_type_generator.py',
-      '<(api_gen_dir)/cpp_util.py',
-      '<(api_gen_dir)/h_generator.py',
-      '<(api_gen_dir)/idl_schema.py',
-      '<(api_gen_dir)/json_schema.py',
-      '<(api_gen_dir)/model.py',
-      '<(api_gen_dir)/util_cc_helper.py',
-    ],
-    'schema_include_rules': [],
-  },
-  'actions': [
-    {
-      'action_name': 'genapi_bundle_schema',
-      'inputs': [
-        '<@(generator_files)',
-        '<@(schema_files)',
-        '<@(non_compiled_schema_files)',
-      ],
-      'outputs': [
-        '<(SHARED_INTERMEDIATE_DIR)/<(cc_dir)/generated_schemas.h',
-        '<(SHARED_INTERMEDIATE_DIR)/<(cc_dir)/generated_schemas.cc',
-      ],
-      'action': [
-        'python',
-        '<(api_gen)',
-        '--root=<(DEPTH)',
-        '--destdir=<(SHARED_INTERMEDIATE_DIR)',
-        '--namespace=<(root_namespace)',
-        '--generator=cpp-bundle-schema',
-        '--include-rules=<(schema_include_rules)',
-        '<@(schema_files)',
-        '<@(non_compiled_schema_files)',
-      ],
-      'message': 'Generating C++ API bundle code for schemas',
-      'process_outputs_as_sources': 1,
-      # Avoid running MIDL compiler on IDL input files.
-      'explicit_idl_action': 1,
-    },
-  ],
-  'include_dirs': [
-    '<(SHARED_INTERMEDIATE_DIR)',
-    '<(DEPTH)',
-  ],
-  'direct_dependent_settings': {
-    'include_dirs': [
-      '<(SHARED_INTERMEDIATE_DIR)',
-    ]
-  },
-  # This target exports a hard dependency because it generates header
-  # files.
-  'hard_dependency': 1,
-}
diff --git a/build/json_schema_bundle_registration_compile.gypi b/build/json_schema_bundle_registration_compile.gypi
deleted file mode 100644
index 8c5af4e..0000000
--- a/build/json_schema_bundle_registration_compile.gypi
+++ /dev/null
@@ -1,78 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-{
-  'variables': {
-    # When including this gypi, the following variables must be set:
-    #   schema_files:
-    #     An array of json or idl files that comprise the api model.
-    #   impl_dir_:
-    #     The root path of API implementations; also used for the
-    #     output location. (N.B. Named as such to prevent gyp from
-    #     expanding it as a relative path.)
-    #   root_namespace:
-    #     A Python string substituion pattern used to generate the C++
-    #     namespace for each API. Use %(namespace)s to replace with the API
-    #     namespace, like "toplevel::%(namespace)s_api".
-    #
-    # Functions and namespaces can be excluded by setting "nocompile" to true.
-    'api_gen_dir': '<(DEPTH)/tools/json_schema_compiler',
-    'api_gen': '<(api_gen_dir)/compiler.py',
-    'generator_files': [
-      '<(api_gen_dir)/cc_generator.py',
-      '<(api_gen_dir)/code.py',
-      '<(api_gen_dir)/compiler.py',
-      '<(api_gen_dir)/cpp_bundle_generator.py',
-      '<(api_gen_dir)/cpp_type_generator.py',
-      '<(api_gen_dir)/cpp_util.py',
-      '<(api_gen_dir)/h_generator.py',
-      '<(api_gen_dir)/idl_schema.py',
-      '<(api_gen_dir)/json_schema.py',
-      '<(api_gen_dir)/model.py',
-      '<(api_gen_dir)/util_cc_helper.py',
-    ],
-  },
-  'actions': [
-    {
-      # GN version: json_schema_api.gni
-      'action_name': 'genapi_bundle_registration',
-      'inputs': [
-        '<@(generator_files)',
-        '<@(schema_files)',
-        '<@(non_compiled_schema_files)',
-      ],
-      'outputs': [
-        '<(SHARED_INTERMEDIATE_DIR)/<(impl_dir_)/generated_api_registration.h',
-        '<(SHARED_INTERMEDIATE_DIR)/<(impl_dir_)/generated_api_registration.cc',
-      ],
-      'action': [
-        'python',
-        '<(api_gen)',
-        '--root=<(DEPTH)',
-        '--destdir=<(SHARED_INTERMEDIATE_DIR)',
-        '--namespace=<(root_namespace)',
-        '--generator=cpp-bundle-registration',
-        '--impl-dir=<(impl_dir_)',
-        '<@(schema_files)',
-        '<@(non_compiled_schema_files)',
-      ],
-      'message': 'Generating C++ API bundle code for function registration',
-      'process_outputs_as_sources': 1,
-      # Avoid running MIDL compiler on IDL input files.
-      'explicit_idl_action': 1,
-    },
-  ],
-  'include_dirs': [
-    '<(SHARED_INTERMEDIATE_DIR)',
-    '<(DEPTH)',
-  ],
-  'direct_dependent_settings': {
-    'include_dirs': [
-      '<(SHARED_INTERMEDIATE_DIR)',
-    ]
-  },
-  # This target exports a hard dependency because it generates header
-  # files.
-  'hard_dependency': 1,
-}
diff --git a/build/json_schema_compile.gypi b/build/json_schema_compile.gypi
deleted file mode 100644
index 6e5727a..0000000
--- a/build/json_schema_compile.gypi
+++ /dev/null
@@ -1,123 +0,0 @@
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-{
-  'variables': {
-    # When including this gypi, the following variables must be set:
-    #   schema_files:
-    #     An array of json or idl files that comprise the api model.
-    #   schema_include_rules (optional):
-    #     An array of paths to include when searching for referenced objects,
-    #     with the namespace separated by a :.
-    #     Example:
-    #       [ '/foo/bar:Foo::Bar::%(namespace)s' ]
-    #   cc_dir:
-    #     The directory to put the generated code in.
-    #   root_namespace:
-    #     A Python string substituion pattern used to generate the C++
-    #     namespace for each API. Use %(namespace)s to replace with the API
-    #     namespace, like "toplevel::%(namespace)s_api".
-    #
-    # Functions and namespaces can be excluded by setting "nocompile" to true.
-    'api_gen_dir': '<(DEPTH)/tools/json_schema_compiler',
-    'api_gen': '<(api_gen_dir)/compiler.py',
-    'schema_include_rules': [],
-  },
-  'rules': [
-    {
-      # GN version: json_schema_api.gni
-      'rule_name': 'genapi',
-      'msvs_external_rule': 1,
-      'extension': 'json',
-      'inputs': [
-        '<(api_gen_dir)/cc_generator.py',
-        '<(api_gen_dir)/code.py',
-        '<(api_gen_dir)/compiler.py',
-        '<(api_gen_dir)/cpp_generator.py',
-        '<(api_gen_dir)/cpp_type_generator.py',
-        '<(api_gen_dir)/cpp_util.py',
-        '<(api_gen_dir)/h_generator.py',
-        '<(api_gen_dir)/json_schema.py',
-        '<(api_gen_dir)/model.py',
-        '<(api_gen_dir)/util.cc',
-        '<(api_gen_dir)/util.h',
-        '<(api_gen_dir)/util_cc_helper.py',
-        # TODO(calamity): uncomment this when gyp on windows behaves like other
-        # platforms. List expansions of filepaths in inputs expand to different
-        # things.
-        # '<@(schema_files)',
-      ],
-      'outputs': [
-        '<(SHARED_INTERMEDIATE_DIR)/<(cc_dir)/<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).cc',
-        '<(SHARED_INTERMEDIATE_DIR)/<(cc_dir)/<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).h',
-      ],
-      'action': [
-        'python',
-        '<(api_gen)',
-        '<(RULE_INPUT_PATH)',
-        '--root=<(DEPTH)',
-        '--destdir=<(SHARED_INTERMEDIATE_DIR)',
-        '--namespace=<(root_namespace)',
-        '--generator=cpp',
-        '--include-rules=<(schema_include_rules)'
-      ],
-      'message': 'Generating C++ code from <(RULE_INPUT_PATH) json files',
-      'process_outputs_as_sources': 1,
-    },
-    {
-      'rule_name': 'genapi_idl',
-      'msvs_external_rule': 1,
-      'extension': 'idl',
-      'inputs': [
-        '<(api_gen_dir)/cc_generator.py',
-        '<(api_gen_dir)/code.py',
-        '<(api_gen_dir)/compiler.py',
-        '<(api_gen_dir)/cpp_generator.py',
-        '<(api_gen_dir)/cpp_type_generator.py',
-        '<(api_gen_dir)/cpp_util.py',
-        '<(api_gen_dir)/h_generator.py',
-        '<(api_gen_dir)/idl_schema.py',
-        '<(api_gen_dir)/model.py',
-        '<(api_gen_dir)/util.cc',
-        '<(api_gen_dir)/util.h',
-        '<(api_gen_dir)/util_cc_helper.py',
-        # TODO(calamity): uncomment this when gyp on windows behaves like other
-        # platforms. List expansions of filepaths in inputs expand to different
-        # things.
-        # '<@(schema_files)',
-      ],
-      'outputs': [
-        '<(SHARED_INTERMEDIATE_DIR)/<(cc_dir)/<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).cc',
-        '<(SHARED_INTERMEDIATE_DIR)/<(cc_dir)/<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).h',
-      ],
-      'action': [
-        'python',
-        '<(api_gen)',
-        '<(RULE_INPUT_PATH)',
-        '--root=<(DEPTH)',
-        '--destdir=<(SHARED_INTERMEDIATE_DIR)',
-        '--namespace=<(root_namespace)',
-        '--generator=cpp',
-        '--include-rules=<(schema_include_rules)'
-      ],
-      'message': 'Generating C++ code from <(RULE_INPUT_PATH) IDL files',
-      'process_outputs_as_sources': 1,
-    },
-  ],
-  'include_dirs': [
-    '<(SHARED_INTERMEDIATE_DIR)',
-    '<(DEPTH)',
-  ],
-  'dependencies':[
-    '<(DEPTH)/tools/json_schema_compiler/api_gen_util.gyp:api_gen_util',
-  ],
-  'direct_dependent_settings': {
-    'include_dirs': [
-      '<(SHARED_INTERMEDIATE_DIR)',
-    ]
-  },
-  # This target exports a hard dependency because it generates header
-  # files.
-  'hard_dependency': 1,
-}
diff --git a/build/json_to_struct.gypi b/build/json_to_struct.gypi
deleted file mode 100644
index 09c8e3e..0000000
--- a/build/json_to_struct.gypi
+++ /dev/null
@@ -1,53 +0,0 @@
-# Copyright 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-{
-  'variables': {
-    # When including this gypi, the following variables must be set:
-    #   schema_file: a json file that comprise the structure model.
-    #   namespace: the C++ namespace that all generated files go under
-    #   cc_dir: path to generated files
-    # Functions and namespaces can be excluded by setting "nocompile" to true.
-    'struct_gen_dir': '<(DEPTH)/tools/json_to_struct',
-    'struct_gen%': '<(struct_gen_dir)/json_to_struct.py',
-    'output_filename%': '<(RULE_INPUT_ROOT)',
-  },
-  'rules': [
-    {
-      # GN version: //tools/json_to_struct/json_to_struct.gni
-      'rule_name': 'genstaticinit',
-      'extension': 'json',
-      'inputs': [
-        '<(struct_gen)',
-        '<(struct_gen_dir)/element_generator.py',
-        '<(struct_gen_dir)/json_to_struct.py',
-        '<(struct_gen_dir)/struct_generator.py',
-        '<(schema_file)',
-      ],
-      'outputs': [
-        '<(SHARED_INTERMEDIATE_DIR)/<(cc_dir)/<(output_filename).cc',
-        '<(SHARED_INTERMEDIATE_DIR)/<(cc_dir)/<(output_filename).h',
-      ],
-      'action': [
-        'python',
-        '<(struct_gen)',
-        '<(RULE_INPUT_PATH)',
-        '--destbase=<(SHARED_INTERMEDIATE_DIR)',
-        '--destdir=<(cc_dir)',
-        '--namespace=<(namespace)',
-        '--schema=<(schema_file)',
-        '--output=<(output_filename)',
-      ],
-      'message': 'Generating C++ static initializers from <(RULE_INPUT_PATH)',
-      'process_outputs_as_sources': 1,
-    },
-  ],
-  'include_dirs': [
-    '<(SHARED_INTERMEDIATE_DIR)',
-    '<(DEPTH)',
-  ],
-  # This target exports a hard dependency because it generates header
-  # files.
-  'hard_dependency': 1,
-}
diff --git a/build/module_args/dart.gni b/build/module_args/dart.gni
deleted file mode 100644
index ee6b038..0000000
--- a/build/module_args/dart.gni
+++ /dev/null
@@ -1,6 +0,0 @@
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This variable should point to the Dart SDK.
-dart_sdk_root = "//third_party/dart-sdk/dart-sdk"
diff --git a/build/module_args/mojo.gni b/build/module_args/mojo.gni
deleted file mode 100644
index fee9114..0000000
--- a/build/module_args/mojo.gni
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This variable should point to the parent directory of the Mojo SDK.
-mojo_sdk_root = "//"
-
-# To build the Mojo shell from source, set this variable to true. To use the
-# prebuilt shell, omit this variable or set it to false. Note that the prebuilt
-# shell will be used only on platforms for which it is published (currently
-# Linux and Android).
-mojo_build_mojo_shell_from_source = true
-
-# To build the network service from source, set this variable to true. To use
-# the prebuilt network service, omit this variable or set it to false.
-mojo_build_network_service_from_source = true
diff --git a/build/module_args/nacl.gni b/build/module_args/nacl.gni
deleted file mode 100644
index 61e0768..0000000
--- a/build/module_args/nacl.gni
+++ /dev/null
@@ -1,6 +0,0 @@
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# Override nacl's build directory.
-nacl_shared_build_dir = "//build"
diff --git a/build/module_args/v8.gni b/build/module_args/v8.gni
deleted file mode 100644
index 8b5204c..0000000
--- a/build/module_args/v8.gni
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-if (is_android) {
-  import("//build/config/android/config.gni")
-}
-
-# TODO(sky): nuke this. Temporary while sorting out http://crbug.com/465456.
-enable_correct_v8_arch = false
-
-v8_use_external_startup_data = !(is_chromeos || is_win)
-v8_extra_library_files = []
diff --git a/build/secondary/testing/gmock/BUILD.gn b/build/secondary/testing/gmock/BUILD.gn
deleted file mode 100644
index 4ec6224..0000000
--- a/build/secondary/testing/gmock/BUILD.gn
+++ /dev/null
@@ -1,54 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-config("gmock_config") {
-  # Gmock headers need to be able to find themselves.
-  include_dirs = [ "include" ]
-}
-
-static_library("gmock") {
-  # TODO http://crbug.com/412064 enable this flag all the time.
-  testonly = !is_component_build
-  sources = [
-    # Sources based on files in r173 of gmock.
-    "include/gmock/gmock-actions.h",
-    "include/gmock/gmock-cardinalities.h",
-    "include/gmock/gmock-generated-actions.h",
-    "include/gmock/gmock-generated-function-mockers.h",
-    "include/gmock/gmock-generated-matchers.h",
-    "include/gmock/gmock-generated-nice-strict.h",
-    "include/gmock/gmock-matchers.h",
-    "include/gmock/gmock-spec-builders.h",
-    "include/gmock/gmock.h",
-    "include/gmock/internal/gmock-generated-internal-utils.h",
-    "include/gmock/internal/gmock-internal-utils.h",
-    "include/gmock/internal/gmock-port.h",
-
-    #"src/gmock-all.cc",  # Not needed by our build.
-    "src/gmock-cardinalities.cc",
-    "src/gmock-internal-utils.cc",
-    "src/gmock-matchers.cc",
-    "src/gmock-spec-builders.cc",
-    "src/gmock.cc",
-  ]
-
-  # This project includes some stuff form gtest's guts.
-  include_dirs = [ "../gtest/include" ]
-
-  public_configs = [
-    ":gmock_config",
-    "//testing/gtest:gtest_config",
-  ]
-}
-
-static_library("gmock_main") {
-  # TODO http://crbug.com/412064 enable this flag all the time.
-  testonly = !is_component_build
-  sources = [
-    "src/gmock_main.cc",
-  ]
-  deps = [
-    ":gmock",
-  ]
-}
diff --git a/build/secondary/testing/gtest/BUILD.gn b/build/secondary/testing/gtest/BUILD.gn
deleted file mode 100644
index 073faec..0000000
--- a/build/secondary/testing/gtest/BUILD.gn
+++ /dev/null
@@ -1,135 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-config("gtest_config") {
-  visibility = [
-    ":*",
-    "//testing/gmock:*",  # gmock also shares this config.
-  ]
-
-  defines = [
-    # In order to allow regex matches in gtest to be shared between Windows
-    # and other systems, we tell gtest to always use it's internal engine.
-    "GTEST_HAS_POSIX_RE=0",
-
-    # Chrome doesn't support / require C++11, yet.
-    "GTEST_LANG_CXX11=0",
-  ]
-
-  # Gtest headers need to be able to find themselves.
-  include_dirs = [ "include" ]
-
-  if (is_win) {
-    cflags = [ "/wd4800" ]  # Unused variable warning.
-  }
-
-  if (is_posix) {
-    defines += [
-      # gtest isn't able to figure out when RTTI is disabled for gcc
-      # versions older than 4.3.2, and assumes it's enabled.  Our Mac
-      # and Linux builds disable RTTI, and cannot guarantee that the
-      # compiler will be 4.3.2. or newer.  The Mac, for example, uses
-      # 4.2.1 as that is the latest available on that platform.  gtest
-      # must be instructed that RTTI is disabled here, and for any
-      # direct dependents that might include gtest headers.
-      "GTEST_HAS_RTTI=0",
-    ]
-  }
-
-  if (is_android) {
-    defines += [
-      # We want gtest features that use tr1::tuple, but we currently
-      # don't support the variadic templates used by libstdc++'s
-      # implementation. gtest supports this scenario by providing its
-      # own implementation but we must opt in to it.
-      "GTEST_USE_OWN_TR1_TUPLE=1",
-
-      # GTEST_USE_OWN_TR1_TUPLE only works if GTEST_HAS_TR1_TUPLE is set.
-      # gtest r625 made it so that GTEST_HAS_TR1_TUPLE is set to 0
-      # automatically on android, so it has to be set explicitly here.
-      "GTEST_HAS_TR1_TUPLE=1",
-    ]
-  }
-}
-
-config("gtest_direct_config") {
-  visibility = [ ":*" ]
-  defines = [ "UNIT_TEST" ]
-}
-
-static_library("gtest") {
-  # TODO http://crbug.com/412064 enable this flag all the time.
-  testonly = !is_component_build
-  sources = [
-    "include/gtest/gtest-death-test.h",
-    "include/gtest/gtest-message.h",
-    "include/gtest/gtest-param-test.h",
-    "include/gtest/gtest-printers.h",
-    "include/gtest/gtest-spi.h",
-    "include/gtest/gtest-test-part.h",
-    "include/gtest/gtest-typed-test.h",
-    "include/gtest/gtest.h",
-    "include/gtest/gtest_pred_impl.h",
-    "include/gtest/internal/gtest-death-test-internal.h",
-    "include/gtest/internal/gtest-filepath.h",
-    "include/gtest/internal/gtest-internal.h",
-    "include/gtest/internal/gtest-linked_ptr.h",
-    "include/gtest/internal/gtest-param-util-generated.h",
-    "include/gtest/internal/gtest-param-util.h",
-    "include/gtest/internal/gtest-port.h",
-    "include/gtest/internal/gtest-string.h",
-    "include/gtest/internal/gtest-tuple.h",
-    "include/gtest/internal/gtest-type-util.h",
-
-    #"gtest/src/gtest-all.cc",  # Not needed by our build.
-    "../multiprocess_func_list.cc",
-    "../multiprocess_func_list.h",
-    "../platform_test.h",
-    "src/gtest-death-test.cc",
-    "src/gtest-filepath.cc",
-    "src/gtest-internal-inl.h",
-    "src/gtest-port.cc",
-    "src/gtest-printers.cc",
-    "src/gtest-test-part.cc",
-    "src/gtest-typed-test.cc",
-    "src/gtest.cc",
-  ]
-
-  if (is_mac) {
-    sources += [
-      "../gtest_mac.h",
-      "../gtest_mac.mm",
-      "../platform_test_mac.mm",
-    ]
-  }
-
-  include_dirs = [ "." ]
-
-  all_dependent_configs = [ ":gtest_config" ]
-  public_configs = [ ":gtest_direct_config" ]
-
-  configs -= [ "//build/config/compiler:chromium_code" ]
-  configs += [ "//build/config/compiler:no_chromium_code" ]
-
-  config("gtest_warnings") {
-    if (is_win && is_clang) {
-      # The Mutex constructor initializer list in gtest-port.cc is incorrectly
-      # ordered. See
-      # https://groups.google.com/d/msg/googletestframework/S5uSV8L2TX8/U1FaTDa6J6sJ.
-      cflags = [ "-Wno-reorder" ]
-    }
-  }
-  configs += [ ":gtest_warnings" ]
-}
-
-source_set("gtest_main") {
-  # TODO http://crbug.com/412064 enable this flag all the time.
-  testonly = !is_component_build
-  sources = [
-    "src/gtest_main.cc",
-  ]
-  deps = [
-    ":gtest",
-  ]
-}
diff --git a/build/secondary/third_party/libjpeg_turbo/BUILD.gn b/build/secondary/third_party/libjpeg_turbo/BUILD.gn
deleted file mode 100644
index 62e60ae..0000000
--- a/build/secondary/third_party/libjpeg_turbo/BUILD.gn
+++ /dev/null
@@ -1,221 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# Do not use the targets in this file unless you need a certain libjpeg
-# implementation. Use the meta target //third_party:jpeg instead.
-
-import("//build/config/sanitizers/sanitizers.gni")
-
-if (current_cpu == "arm") {
-  import("//build/config/arm.gni")
-}
-
-if (current_cpu == "x86" || current_cpu == "x64") {
-  import("//third_party/yasm/yasm_assemble.gni")
-
-  yasm_assemble("simd_asm") {
-    defines = []
-
-    if (current_cpu == "x86") {
-      sources = [
-        "simd/jccolor-mmx.asm",
-        "simd/jccolor-sse2.asm",
-        "simd/jcgray-mmx.asm",
-        "simd/jcgray-sse2.asm",
-        "simd/jchuff-sse2.asm",
-        "simd/jcsample-mmx.asm",
-        "simd/jcsample-sse2.asm",
-        "simd/jdcolor-mmx.asm",
-        "simd/jdcolor-sse2.asm",
-        "simd/jdmerge-mmx.asm",
-        "simd/jdmerge-sse2.asm",
-        "simd/jdsample-mmx.asm",
-        "simd/jdsample-sse2.asm",
-        "simd/jfdctflt-3dn.asm",
-        "simd/jfdctflt-sse.asm",
-        "simd/jfdctfst-mmx.asm",
-        "simd/jfdctfst-sse2.asm",
-        "simd/jfdctint-mmx.asm",
-        "simd/jfdctint-sse2.asm",
-        "simd/jidctflt-3dn.asm",
-        "simd/jidctflt-sse.asm",
-        "simd/jidctflt-sse2.asm",
-        "simd/jidctfst-mmx.asm",
-        "simd/jidctfst-sse2.asm",
-        "simd/jidctint-mmx.asm",
-        "simd/jidctint-sse2.asm",
-        "simd/jidctred-mmx.asm",
-        "simd/jidctred-sse2.asm",
-        "simd/jquant-3dn.asm",
-        "simd/jquant-mmx.asm",
-        "simd/jquant-sse.asm",
-        "simd/jquantf-sse2.asm",
-        "simd/jquanti-sse2.asm",
-        "simd/jsimdcpu.asm",
-      ]
-      defines += [
-        "__x86__",
-        "PIC",
-      ]
-    } else if (current_cpu == "x64") {
-      sources = [
-        "simd/jccolor-sse2-64.asm",
-        "simd/jcgray-sse2-64.asm",
-        "simd/jchuff-sse2-64.asm",
-        "simd/jcsample-sse2-64.asm",
-        "simd/jdcolor-sse2-64.asm",
-        "simd/jdmerge-sse2-64.asm",
-        "simd/jdsample-sse2-64.asm",
-        "simd/jfdctflt-sse-64.asm",
-        "simd/jfdctfst-sse2-64.asm",
-        "simd/jfdctint-sse2-64.asm",
-        "simd/jidctflt-sse2-64.asm",
-        "simd/jidctfst-sse2-64.asm",
-        "simd/jidctint-sse2-64.asm",
-        "simd/jidctred-sse2-64.asm",
-        "simd/jquantf-sse2-64.asm",
-        "simd/jquanti-sse2-64.asm",
-      ]
-      defines += [
-        "__x86_64__",
-        "PIC",
-      ]
-    }
-
-    if (is_win) {
-      defines += [ "MSVC" ]
-      include_dirs = [ "win" ]
-      if (current_cpu == "x86") {
-        defines += [ "WIN32" ]
-      } else {
-        defines += [ "WIN64" ]
-      }
-    } else if (is_mac) {
-      defines += [ "MACHO" ]
-      include_dirs = [ "mac" ]
-    } else if (is_linux || is_android) {
-      defines += [ "ELF" ]
-      include_dirs = [ "linux" ]
-    }
-  }
-}
-
-source_set("simd") {
-  if (current_cpu == "x86") {
-    deps = [
-      ":simd_asm",
-    ]
-    sources = [
-      "simd/jsimd_i386.c",
-    ]
-    if (is_win) {
-      cflags = [ "/wd4245" ]
-    }
-  } else if (current_cpu == "x64") {
-    deps = [
-      ":simd_asm",
-    ]
-    sources = [
-      "simd/jsimd_x86_64.c",
-    ]
-  } else if (current_cpu == "arm" && arm_version >= 7 &&
-             (arm_use_neon || arm_optionally_use_neon)) {
-    sources = [
-      "simd/jsimd_arm.c",
-      "simd/jsimd_arm_neon.S",
-    ]
-  } else {
-    sources = [
-      "jsimd_none.c",
-    ]
-  }
-  if (is_win) {
-    cflags = [ "/wd4245" ]
-  }
-}
-
-config("libjpeg_config") {
-  include_dirs = [ "." ]
-}
-
-source_set("libjpeg") {
-  sources = [
-    "jcapimin.c",
-    "jcapistd.c",
-    "jccoefct.c",
-    "jccolor.c",
-    "jcdctmgr.c",
-    "jchuff.c",
-    "jchuff.h",
-    "jcinit.c",
-    "jcmainct.c",
-    "jcmarker.c",
-    "jcmaster.c",
-    "jcomapi.c",
-    "jconfig.h",
-    "jcparam.c",
-    "jcphuff.c",
-    "jcprepct.c",
-    "jcsample.c",
-    "jdapimin.c",
-    "jdapistd.c",
-    "jdatadst.c",
-    "jdatasrc.c",
-    "jdcoefct.c",
-    "jdcolor.c",
-    "jdct.h",
-    "jddctmgr.c",
-    "jdhuff.c",
-    "jdhuff.h",
-    "jdinput.c",
-    "jdmainct.c",
-    "jdmarker.c",
-    "jdmaster.c",
-    "jdmerge.c",
-    "jdphuff.c",
-    "jdpostct.c",
-    "jdsample.c",
-    "jerror.c",
-    "jerror.h",
-    "jfdctflt.c",
-    "jfdctfst.c",
-    "jfdctint.c",
-    "jidctflt.c",
-    "jidctfst.c",
-    "jidctint.c",
-    "jidctred.c",
-    "jinclude.h",
-    "jmemmgr.c",
-    "jmemnobs.c",
-    "jmemsys.h",
-    "jmorecfg.h",
-    "jpegint.h",
-    "jpeglib.h",
-    "jpeglibmangler.h",
-    "jquant1.c",
-    "jquant2.c",
-    "jutils.c",
-    "jversion.h",
-  ]
-
-  defines = [
-    "WITH_SIMD",
-    "NO_GETENV",
-  ]
-
-  configs -= [ "//build/config/compiler:chromium_code" ]
-  configs += [ "//build/config/compiler:no_chromium_code" ]
-
-  public_configs = [ ":libjpeg_config" ]
-
-  # MemorySanitizer doesn't support assembly code, so keep it disabled in
-  # MSan builds for now.
-  if (is_msan) {
-    sources += [ "jsimd_none.c" ]
-  } else {
-    deps = [
-      ":simd",
-    ]
-  }
-}
diff --git a/build/secondary/third_party/libsrtp/BUILD.gn b/build/secondary/third_party/libsrtp/BUILD.gn
deleted file mode 100644
index 7601bea..0000000
--- a/build/secondary/third_party/libsrtp/BUILD.gn
+++ /dev/null
@@ -1,391 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-declare_args() {
-  use_system_libsrtp = false
-  use_srtp_boringssl = true
-}
-
-config("libsrtp_config") {
-  defines = [
-    "HAVE_CONFIG_H",
-    "HAVE_STDLIB_H",
-    "HAVE_STRING_H",
-    "TESTAPP_SOURCE",
-  ]
-
-  include_dirs = [
-    "config",
-    "srtp/include",
-    "srtp/crypto/include",
-  ]
-
-  if (use_srtp_boringssl) {
-    defines += [ "OPENSSL" ]
-  }
-
-  if (is_posix) {
-    defines += [
-      "HAVE_INT16_T",
-      "HAVE_INT32_T",
-      "HAVE_INT8_T",
-      "HAVE_UINT16_T",
-      "HAVE_UINT32_T",
-      "HAVE_UINT64_T",
-      "HAVE_UINT8_T",
-      "HAVE_STDINT_H",
-      "HAVE_INTTYPES_H",
-      "HAVE_NETINET_IN_H",
-      "HAVE_ARPA_INET_H",
-      "HAVE_UNISTD_H",
-    ]
-    cflags = [ "-Wno-unused-variable" ]
-  }
-
-  if (is_win) {
-    defines += [
-      "HAVE_BYTESWAP_METHODS_H",
-
-      # All Windows architectures are this way.
-      "SIZEOF_UNSIGNED_LONG=4",
-      "SIZEOF_UNSIGNED_LONG_LONG=8",
-    ]
-  }
-
-  if (current_cpu == "x64" || current_cpu == "x86" || current_cpu == "arm") {
-    defines += [
-      # TODO(leozwang): CPU_RISC doesn"t work properly on android/arm
-      # platform for unknown reasons, need to investigate the root cause
-      # of it. CPU_RISC is used for optimization only, and CPU_CISC should
-      # just work just fine, it has been tested on android/arm with srtp
-      # test applications and libjingle.
-      "CPU_CISC",
-    ]
-  }
-
-  if (current_cpu == "mipsel") {
-    defines += [ "CPU_RISC" ]
-  }
-}
-
-config("system_libsrtp_config") {
-  defines = [ "USE_SYSTEM_LIBSRTP" ]
-  include_dirs = [ "/usr/include/srtp" ]
-}
-
-if (use_system_libsrtp) {
-  group("libsrtp") {
-    public_configs = [
-      ":libsrtp_config",
-      ":system_libsrtp_config",
-    ]
-    libs = [ "-lsrtp" ]
-  }
-} else {
-  static_library("libsrtp") {
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    public_configs = [ ":libsrtp_config" ]
-
-    sources = [
-      # includes
-      "srtp/include/ekt.h",
-      "srtp/include/getopt_s.h",
-      "srtp/include/rtp.h",
-      "srtp/include/rtp_priv.h",
-      "srtp/include/srtp.h",
-      "srtp/include/srtp_priv.h",
-      "srtp/include/ut_sim.h",
-
-      # headers
-      "srtp/crypto/include/aes.h",
-      "srtp/crypto/include/aes_cbc.h",
-      "srtp/crypto/include/aes_icm.h",
-      "srtp/crypto/include/alloc.h",
-      "srtp/crypto/include/auth.h",
-      "srtp/crypto/include/cipher.h",
-      "srtp/crypto/include/crypto.h",
-      "srtp/crypto/include/crypto_kernel.h",
-      "srtp/crypto/include/crypto_math.h",
-      "srtp/crypto/include/crypto_types.h",
-      "srtp/crypto/include/cryptoalg.h",
-      "srtp/crypto/include/datatypes.h",
-      "srtp/crypto/include/err.h",
-      "srtp/crypto/include/gf2_8.h",
-      "srtp/crypto/include/hmac.h",
-      "srtp/crypto/include/integers.h",
-      "srtp/crypto/include/kernel_compat.h",
-      "srtp/crypto/include/key.h",
-      "srtp/crypto/include/null_auth.h",
-      "srtp/crypto/include/null_cipher.h",
-      "srtp/crypto/include/prng.h",
-      "srtp/crypto/include/rand_source.h",
-      "srtp/crypto/include/rdb.h",
-      "srtp/crypto/include/rdbx.h",
-      "srtp/crypto/include/sha1.h",
-      "srtp/crypto/include/stat.h",
-      "srtp/crypto/include/xfm.h",
-
-      # sources
-      "srtp/crypto/cipher/aes.c",
-      "srtp/crypto/cipher/aes_cbc.c",
-      "srtp/crypto/cipher/aes_icm.c",
-      "srtp/crypto/cipher/cipher.c",
-      "srtp/crypto/cipher/null_cipher.c",
-      "srtp/crypto/hash/auth.c",
-      "srtp/crypto/hash/hmac.c",
-      "srtp/crypto/hash/null_auth.c",
-      "srtp/crypto/hash/sha1.c",
-      "srtp/crypto/kernel/alloc.c",
-      "srtp/crypto/kernel/crypto_kernel.c",
-      "srtp/crypto/kernel/err.c",
-      "srtp/crypto/kernel/key.c",
-      "srtp/crypto/math/datatypes.c",
-      "srtp/crypto/math/gf2_8.c",
-      "srtp/crypto/math/stat.c",
-      "srtp/crypto/replay/rdb.c",
-      "srtp/crypto/replay/rdbx.c",
-      "srtp/crypto/replay/ut_sim.c",
-      "srtp/crypto/rng/ctr_prng.c",
-      "srtp/crypto/rng/prng.c",
-      "srtp/crypto/rng/rand_source.c",
-      "srtp/srtp/ekt.c",
-      "srtp/srtp/srtp.c",
-    ]
-
-    if (is_clang) {
-      cflags = [ "-Wno-implicit-function-declaration" ]
-    }
-
-    if (use_srtp_boringssl) {
-      deps = [
-        "//third_party/boringssl:boringssl",
-      ]
-      public_deps = [
-        "//third_party/boringssl:boringssl",
-      ]
-      sources -= [
-        "srtp/crypto/cipher/aes_cbc.c",
-        "srtp/crypto/cipher/aes_icm.c",
-        "srtp/crypto/hash/hmac.c",
-        "srtp/crypto/hash/sha1.c",
-        "srtp/crypto/rng/ctr_prng.c",
-        "srtp/crypto/rng/prng.c",
-      ]
-      sources += [
-        "srtp/crypto/cipher/aes_gcm_ossl.c",
-        "srtp/crypto/cipher/aes_icm_ossl.c",
-        "srtp/crypto/hash/hmac_ossl.c",
-        "srtp/crypto/include/aes_gcm_ossl.h",
-        "srtp/crypto/include/aes_icm_ossl.h",
-      ]
-    }
-  }
-
-  # TODO(GYP): A bunch of these tests don't compile (in gyp either). They're
-  # not very broken, so could probably be made to work if it's useful.
-  if (!is_win) {
-    executable("rdbx_driver") {
-      configs -= [ "//build/config/compiler:chromium_code" ]
-      configs += [ "//build/config/compiler:no_chromium_code" ]
-      deps = [
-        ":libsrtp",
-      ]
-      sources = [
-        "srtp/include/getopt_s.h",
-        "srtp/test/getopt_s.c",
-        "srtp/test/rdbx_driver.c",
-      ]
-    }
-
-    executable("srtp_driver") {
-      configs -= [ "//build/config/compiler:chromium_code" ]
-      configs += [ "//build/config/compiler:no_chromium_code" ]
-      deps = [
-        ":libsrtp",
-      ]
-      sources = [
-        "srtp/include/getopt_s.h",
-        "srtp/include/srtp_priv.h",
-        "srtp/test/getopt_s.c",
-        "srtp/test/srtp_driver.c",
-      ]
-    }
-
-    executable("roc_driver") {
-      configs -= [ "//build/config/compiler:chromium_code" ]
-      configs += [ "//build/config/compiler:no_chromium_code" ]
-      deps = [
-        ":libsrtp",
-      ]
-      sources = [
-        "srtp/crypto/include/rdbx.h",
-        "srtp/include/ut_sim.h",
-        "srtp/test/roc_driver.c",
-      ]
-    }
-
-    executable("replay_driver") {
-      configs -= [ "//build/config/compiler:chromium_code" ]
-      configs += [ "//build/config/compiler:no_chromium_code" ]
-      deps = [
-        ":libsrtp",
-      ]
-      sources = [
-        "srtp/crypto/include/rdbx.h",
-        "srtp/include/ut_sim.h",
-        "srtp/test/replay_driver.c",
-      ]
-    }
-
-    executable("rtpw") {
-      configs -= [ "//build/config/compiler:chromium_code" ]
-      configs += [ "//build/config/compiler:no_chromium_code" ]
-      deps = [
-        ":libsrtp",
-      ]
-      sources = [
-        "srtp/crypto/include/datatypes.h",
-        "srtp/include/getopt_s.h",
-        "srtp/include/rtp.h",
-        "srtp/include/srtp.h",
-        "srtp/test/getopt_s.c",
-        "srtp/test/rtp.c",
-        "srtp/test/rtpw.c",
-      ]
-      if (is_android) {
-        defines = [ "HAVE_SYS_SOCKET_H" ]
-      }
-      if (is_clang) {
-        cflags = [ "-Wno-implicit-function-declaration" ]
-      }
-    }
-
-    executable("srtp_test_cipher_driver") {
-      configs -= [ "//build/config/compiler:chromium_code" ]
-      configs += [ "//build/config/compiler:no_chromium_code" ]
-      deps = [
-        ":libsrtp",
-      ]
-      sources = [
-        "srtp/crypto/test/cipher_driver.c",
-        "srtp/include/getopt_s.h",
-        "srtp/test/getopt_s.c",
-      ]
-    }
-
-    executable("srtp_test_datatypes_driver") {
-      configs -= [ "//build/config/compiler:chromium_code" ]
-      configs += [ "//build/config/compiler:no_chromium_code" ]
-      deps = [
-        ":libsrtp",
-      ]
-      sources = [
-        "srtp/crypto/test/datatypes_driver.c",
-      ]
-    }
-
-    executable("srtp_test_stat_driver") {
-      configs -= [ "//build/config/compiler:chromium_code" ]
-      configs += [ "//build/config/compiler:no_chromium_code" ]
-      deps = [
-        ":libsrtp",
-      ]
-      sources = [
-        "srtp/crypto/test/stat_driver.c",
-      ]
-    }
-
-    executable("srtp_test_sha1_driver") {
-      configs -= [ "//build/config/compiler:chromium_code" ]
-      configs += [ "//build/config/compiler:no_chromium_code" ]
-      deps = [
-        ":libsrtp",
-      ]
-      sources = [
-        "srtp/crypto/test/sha1_driver.c",
-      ]
-    }
-
-    executable("srtp_test_kernel_driver") {
-      configs -= [ "//build/config/compiler:chromium_code" ]
-      configs += [ "//build/config/compiler:no_chromium_code" ]
-      deps = [
-        ":libsrtp",
-      ]
-      sources = [
-        "srtp/crypto/test/kernel_driver.c",
-        "srtp/include/getopt_s.h",
-        "srtp/test/getopt_s.c",
-      ]
-    }
-
-    executable("srtp_test_aes_calc") {
-      configs -= [ "//build/config/compiler:chromium_code" ]
-      configs += [ "//build/config/compiler:no_chromium_code" ]
-      deps = [
-        ":libsrtp",
-      ]
-      sources = [
-        "srtp/crypto/test/aes_calc.c",
-      ]
-    }
-
-    executable("srtp_test_rand_gen") {
-      configs -= [ "//build/config/compiler:chromium_code" ]
-      configs += [ "//build/config/compiler:no_chromium_code" ]
-      deps = [
-        ":libsrtp",
-      ]
-      sources = [
-        "srtp/crypto/test/rand_gen.c",
-        "srtp/include/getopt_s.h",
-        "srtp/test/getopt_s.c",
-      ]
-    }
-
-    executable("srtp_test_rand_gen_soak") {
-      configs -= [ "//build/config/compiler:chromium_code" ]
-      configs += [ "//build/config/compiler:no_chromium_code" ]
-      deps = [
-        ":libsrtp",
-      ]
-      sources = [
-        "srtp/crypto/test/rand_gen_soak.c",
-        "srtp/include/getopt_s.h",
-        "srtp/test/getopt_s.c",
-      ]
-    }
-
-    executable("srtp_test_env") {
-      configs -= [ "//build/config/compiler:chromium_code" ]
-      configs += [ "//build/config/compiler:no_chromium_code" ]
-      deps = [
-        ":libsrtp",
-      ]
-      sources = [
-        "srtp/crypto/test/env.c",
-      ]
-    }
-
-    group("srtp_runtest") {
-      deps = [
-        ":rdbx_driver",
-        ":srtp_driver",
-        ":roc_driver",
-        ":replay_driver",
-        ":rtpw",
-        ":srtp_test_cipher_driver",
-        ":srtp_test_datatypes_driver",
-        ":srtp_test_stat_driver",
-        ":srtp_test_sha1_driver",
-        ":srtp_test_kernel_driver",
-        ":srtp_test_aes_calc",
-        ":srtp_test_rand_gen",
-        ":srtp_test_rand_gen_soak",
-        ":srtp_test_env",
-      ]
-    }
-  }
-}
diff --git a/build/secondary/third_party/nss/BUILD.gn b/build/secondary/third_party/nss/BUILD.gn
deleted file mode 100644
index 25d449e..0000000
--- a/build/secondary/third_party/nss/BUILD.gn
+++ /dev/null
@@ -1,1211 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//build/config/linux/pkg_config.gni")
-
-if (is_linux) {
-  # This is a dependency on NSS with no libssl. On Linux we use a built-in SSL
-  # library but the system NSS libraries. Non-Linux platforms using NSS use the
-  # hermetic one in //third_party/nss.
-  #
-  # Generally you should depend on //crypto:platform instead of using this
-  # config since that will properly pick up NSS or OpenSSL depending on
-  # platform and build config.
-  pkg_config("system_nss_no_ssl_config") {
-    packages = [ "nss" ]
-    extra_args = [
-      "-v",
-      "-lssl3",
-    ]
-  }
-} else {
-  include_nss_root_certs = is_ios
-  include_nss_libpkix = is_ios
-
-  config("nspr_config") {
-    defines = [ "NO_NSPR_10_SUPPORT" ]
-    include_dirs = [
-      "nspr/pr/include",
-      "nspr/lib/ds",
-      "nspr/lib/libc/include",
-    ]
-
-    if (component_mode != "shared_library") {
-      defines += [ "NSPR_STATIC" ]
-    }
-  }
-
-  component("nspr") {
-    output_name = "crnspr"
-    sources = [
-      "nspr/lib/ds/plarena.c",
-      "nspr/lib/ds/plarena.h",
-      "nspr/lib/ds/plarenas.h",
-      "nspr/lib/ds/plhash.c",
-      "nspr/lib/ds/plhash.h",
-      "nspr/lib/libc/include/plbase64.h",
-      "nspr/lib/libc/include/plerror.h",
-      "nspr/lib/libc/include/plgetopt.h",
-      "nspr/lib/libc/include/plstr.h",
-      "nspr/lib/libc/src/base64.c",
-      "nspr/lib/libc/src/plerror.c",
-      "nspr/lib/libc/src/plgetopt.c",
-      "nspr/lib/libc/src/strcase.c",
-      "nspr/lib/libc/src/strcat.c",
-      "nspr/lib/libc/src/strchr.c",
-      "nspr/lib/libc/src/strcmp.c",
-      "nspr/lib/libc/src/strcpy.c",
-      "nspr/lib/libc/src/strdup.c",
-      "nspr/lib/libc/src/strlen.c",
-      "nspr/lib/libc/src/strpbrk.c",
-      "nspr/lib/libc/src/strstr.c",
-      "nspr/lib/libc/src/strtok.c",
-      "nspr/pr/include/md/_darwin.cfg",
-      "nspr/pr/include/md/_darwin.h",
-      "nspr/pr/include/md/_pcos.h",
-      "nspr/pr/include/md/_pth.h",
-      "nspr/pr/include/md/_unix_errors.h",
-      "nspr/pr/include/md/_unixos.h",
-      "nspr/pr/include/md/_win32_errors.h",
-      "nspr/pr/include/md/_win95.cfg",
-      "nspr/pr/include/md/_win95.h",
-      "nspr/pr/include/md/prosdep.h",
-      "nspr/pr/include/nspr.h",
-      "nspr/pr/include/obsolete/pralarm.h",
-      "nspr/pr/include/obsolete/probslet.h",
-      "nspr/pr/include/obsolete/protypes.h",
-      "nspr/pr/include/obsolete/prsem.h",
-      "nspr/pr/include/pratom.h",
-      "nspr/pr/include/prbit.h",
-      "nspr/pr/include/prclist.h",
-      "nspr/pr/include/prcmon.h",
-      "nspr/pr/include/prcountr.h",
-      "nspr/pr/include/prcpucfg.h",
-      "nspr/pr/include/prcvar.h",
-      "nspr/pr/include/prdtoa.h",
-      "nspr/pr/include/prenv.h",
-      "nspr/pr/include/prerr.h",
-      "nspr/pr/include/prerror.h",
-      "nspr/pr/include/prinet.h",
-      "nspr/pr/include/prinit.h",
-      "nspr/pr/include/prinrval.h",
-      "nspr/pr/include/prio.h",
-      "nspr/pr/include/pripcsem.h",
-      "nspr/pr/include/private/pprio.h",
-      "nspr/pr/include/private/pprmwait.h",
-      "nspr/pr/include/private/pprthred.h",
-      "nspr/pr/include/private/primpl.h",
-      "nspr/pr/include/private/prpriv.h",
-      "nspr/pr/include/prlink.h",
-      "nspr/pr/include/prlock.h",
-      "nspr/pr/include/prlog.h",
-      "nspr/pr/include/prlong.h",
-      "nspr/pr/include/prmem.h",
-      "nspr/pr/include/prmon.h",
-      "nspr/pr/include/prmwait.h",
-      "nspr/pr/include/prnetdb.h",
-      "nspr/pr/include/prolock.h",
-      "nspr/pr/include/prpdce.h",
-      "nspr/pr/include/prprf.h",
-      "nspr/pr/include/prproces.h",
-      "nspr/pr/include/prrng.h",
-      "nspr/pr/include/prrwlock.h",
-      "nspr/pr/include/prshm.h",
-      "nspr/pr/include/prshma.h",
-      "nspr/pr/include/prsystem.h",
-      "nspr/pr/include/prthread.h",
-      "nspr/pr/include/prtime.h",
-      "nspr/pr/include/prtpool.h",
-      "nspr/pr/include/prtrace.h",
-      "nspr/pr/include/prtypes.h",
-      "nspr/pr/include/prvrsion.h",
-      "nspr/pr/include/prwin16.h",
-      "nspr/pr/src/io/prdir.c",
-      "nspr/pr/src/io/prfdcach.c",
-      "nspr/pr/src/io/prfile.c",
-      "nspr/pr/src/io/prio.c",
-      "nspr/pr/src/io/priometh.c",
-      "nspr/pr/src/io/pripv6.c",
-      "nspr/pr/src/io/prlayer.c",
-      "nspr/pr/src/io/prlog.c",
-      "nspr/pr/src/io/prmapopt.c",
-      "nspr/pr/src/io/prmmap.c",
-      "nspr/pr/src/io/prmwait.c",
-      "nspr/pr/src/io/prpolevt.c",
-      "nspr/pr/src/io/prprf.c",
-      "nspr/pr/src/io/prscanf.c",
-      "nspr/pr/src/io/prsocket.c",
-      "nspr/pr/src/io/prstdio.c",
-      "nspr/pr/src/linking/prlink.c",
-      "nspr/pr/src/malloc/prmalloc.c",
-      "nspr/pr/src/malloc/prmem.c",
-      "nspr/pr/src/md/prosdep.c",
-      "nspr/pr/src/md/unix/darwin.c",
-      "nspr/pr/src/md/unix/os_Darwin.s",
-      "nspr/pr/src/md/unix/unix.c",
-      "nspr/pr/src/md/unix/unix_errors.c",
-      "nspr/pr/src/md/unix/uxproces.c",
-      "nspr/pr/src/md/unix/uxrng.c",
-      "nspr/pr/src/md/unix/uxshm.c",
-      "nspr/pr/src/md/unix/uxwrap.c",
-      "nspr/pr/src/md/windows/ntgc.c",
-      "nspr/pr/src/md/windows/ntinrval.c",
-      "nspr/pr/src/md/windows/ntmisc.c",
-      "nspr/pr/src/md/windows/ntsec.c",
-      "nspr/pr/src/md/windows/ntsem.c",
-      "nspr/pr/src/md/windows/w32ipcsem.c",
-      "nspr/pr/src/md/windows/w32poll.c",
-      "nspr/pr/src/md/windows/w32rng.c",
-      "nspr/pr/src/md/windows/w32shm.c",
-      "nspr/pr/src/md/windows/w95cv.c",
-      "nspr/pr/src/md/windows/w95dllmain.c",
-      "nspr/pr/src/md/windows/w95io.c",
-      "nspr/pr/src/md/windows/w95sock.c",
-      "nspr/pr/src/md/windows/w95thred.c",
-      "nspr/pr/src/md/windows/win32_errors.c",
-      "nspr/pr/src/memory/prseg.c",
-      "nspr/pr/src/memory/prshm.c",
-      "nspr/pr/src/memory/prshma.c",
-      "nspr/pr/src/misc/pralarm.c",
-      "nspr/pr/src/misc/pratom.c",
-      "nspr/pr/src/misc/praton.c",
-      "nspr/pr/src/misc/prcountr.c",
-      "nspr/pr/src/misc/prdtoa.c",
-      "nspr/pr/src/misc/prenv.c",
-      "nspr/pr/src/misc/prerr.c",
-      "nspr/pr/src/misc/prerror.c",
-      "nspr/pr/src/misc/prerrortable.c",
-      "nspr/pr/src/misc/prinit.c",
-      "nspr/pr/src/misc/prinrval.c",
-      "nspr/pr/src/misc/pripc.c",
-      "nspr/pr/src/misc/pripcsem.c",
-      "nspr/pr/src/misc/prlog2.c",
-      "nspr/pr/src/misc/prlong.c",
-      "nspr/pr/src/misc/prnetdb.c",
-      "nspr/pr/src/misc/prolock.c",
-      "nspr/pr/src/misc/prrng.c",
-      "nspr/pr/src/misc/prsystem.c",
-      "nspr/pr/src/misc/prthinfo.c",
-      "nspr/pr/src/misc/prtime.c",
-      "nspr/pr/src/misc/prtpool.c",
-      "nspr/pr/src/misc/prtrace.c",
-      "nspr/pr/src/pthreads/ptio.c",
-      "nspr/pr/src/pthreads/ptmisc.c",
-      "nspr/pr/src/pthreads/ptsynch.c",
-      "nspr/pr/src/pthreads/ptthread.c",
-      "nspr/pr/src/threads/combined/prucpu.c",
-      "nspr/pr/src/threads/combined/prucv.c",
-      "nspr/pr/src/threads/combined/prulock.c",
-      "nspr/pr/src/threads/combined/prustack.c",
-      "nspr/pr/src/threads/combined/pruthr.c",
-      "nspr/pr/src/threads/prcmon.c",
-      "nspr/pr/src/threads/prcthr.c",
-      "nspr/pr/src/threads/prdump.c",
-      "nspr/pr/src/threads/prmon.c",
-      "nspr/pr/src/threads/prrwlock.c",
-      "nspr/pr/src/threads/prsem.c",
-      "nspr/pr/src/threads/prtpd.c",
-    ]
-
-    public_configs = [ ":nspr_config" ]
-
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    if (is_win) {
-      configs -= [
-        "//build/config/win:unicode",  # Requires 8-bit mode.
-        "//build/config/win:lean_and_mean",  # Won"t compile with lean and mean.
-      ]
-    }
-    configs += [
-      "//build/config/compiler:no_chromium_code",
-      "//build/config/compiler:no_size_t_to_int_warning",
-    ]
-
-    cflags = []
-    defines = [
-      "_NSPR_BUILD_",
-      "FORCE_PR_LOG",
-    ]
-
-    include_dirs = [ "nspr/pr/include/private" ]
-
-    if (is_win) {
-      cflags = [ "/wd4554" ]  # Check precidence.
-      defines += [
-        "XP_PC",
-        "WIN32",
-        "WIN95",
-        "_PR_GLOBAL_THREADS_ONLY",
-        "_CRT_SECURE_NO_WARNINGS",
-      ]
-    } else {
-      sources -= [
-        "nspr/pr/src/md/windows/ntgc.c",
-        "nspr/pr/src/md/windows/ntinrval.c",
-        "nspr/pr/src/md/windows/ntmisc.c",
-        "nspr/pr/src/md/windows/ntsec.c",
-        "nspr/pr/src/md/windows/ntsem.c",
-        "nspr/pr/src/md/windows/w32ipcsem.c",
-        "nspr/pr/src/md/windows/w32poll.c",
-        "nspr/pr/src/md/windows/w32rng.c",
-        "nspr/pr/src/md/windows/w32shm.c",
-        "nspr/pr/src/md/windows/w95cv.c",
-        "nspr/pr/src/md/windows/w95dllmain.c",
-        "nspr/pr/src/md/windows/w95io.c",
-        "nspr/pr/src/md/windows/w95sock.c",
-        "nspr/pr/src/md/windows/w95thred.c",
-        "nspr/pr/src/md/windows/win32_errors.c",
-        "nspr/pr/src/threads/combined/prucpu.c",
-        "nspr/pr/src/threads/combined/prucv.c",
-        "nspr/pr/src/threads/combined/prulock.c",
-        "nspr/pr/src/threads/combined/prustack.c",
-        "nspr/pr/src/threads/combined/pruthr.c",
-      ]
-    }
-
-    if (!is_posix) {
-      sources -= [
-        "nspr/pr/src/md/unix/darwin.c",
-        "nspr/pr/src/md/unix/os_Darwin.s",
-        "nspr/pr/src/md/unix/unix.c",
-        "nspr/pr/src/md/unix/unix_errors.c",
-        "nspr/pr/src/md/unix/uxproces.c",
-        "nspr/pr/src/md/unix/uxrng.c",
-        "nspr/pr/src/md/unix/uxshm.c",
-        "nspr/pr/src/md/unix/uxwrap.c",
-        "nspr/pr/src/pthreads/ptio.c",
-        "nspr/pr/src/pthreads/ptmisc.c",
-        "nspr/pr/src/pthreads/ptsynch.c",
-        "nspr/pr/src/pthreads/ptthread.c",
-      ]
-    }
-
-    if (current_cpu == "x86") {
-      defines += [ "_X86_" ]
-    } else if (current_cpu == "x64") {
-      defines += [ "_AMD64_" ]
-    }
-
-    if (is_mac || is_ios) {
-      sources -= [
-        "nspr/pr/src/io/prdir.c",
-        "nspr/pr/src/io/prfile.c",
-        "nspr/pr/src/io/prio.c",
-        "nspr/pr/src/io/prsocket.c",
-        "nspr/pr/src/misc/pripcsem.c",
-        "nspr/pr/src/threads/prcthr.c",
-        "nspr/pr/src/threads/prdump.c",
-        "nspr/pr/src/threads/prmon.c",
-        "nspr/pr/src/threads/prsem.c",
-      ]
-      defines += [
-        "XP_UNIX",
-        "DARWIN",
-        "XP_MACOSX",
-        "_PR_PTHREADS",
-        "HAVE_BSD_FLOCK",
-        "HAVE_DLADDR",
-        "HAVE_LCHOWN",
-        "HAVE_SOCKLEN_T",
-        "HAVE_STRERROR",
-      ]
-    }
-
-    if (is_mac) {
-      defines += [ "HAVE_CRT_EXTERNS_H" ]
-      libs = [
-        "CoreFoundation.framework",
-        "CoreServices.framework",
-      ]
-    }
-
-    if (is_clang) {
-      cflags += [
-        # nspr uses a bunch of deprecated functions (NSLinkModule etc) in
-        # prlink.c on mac.
-        "-Wno-deprecated-declarations",
-
-        # nspr passes "const char*" through "void*".
-        "-Wno-incompatible-pointer-types",
-
-        # nspr passes "int*" through "unsigned int*".
-        "-Wno-pointer-sign",
-      ]
-
-      # nspr uses assert(!"foo") instead of assert(false && "foo").
-      configs -= [ "//build/config/clang:extra_warnings" ]
-    }
-  }
-
-  component("nss") {
-    output_name = "crnss"
-    sources = [
-      # Ensure at least one object file is produced, so that MSVC does not
-      # warn when creating the static/shared library. See the note for
-      # the "nssckbi" target for why the "nss" target was split as such.
-      "nss/lib/nss/nssver.c",
-    ]
-
-    public_deps = [
-      ":nss_static",
-    ]
-
-    if (include_nss_root_certs) {
-      public_deps += [ ":nssckbi" ]
-    }
-
-    if (component_mode == "shared_library") {
-      if (is_mac) {
-        ldflags = [ "-all_load" ]
-      } else if (is_win) {
-        # Pass the def file to the linker.
-        ldflags =
-            [ "/DEF:" + rebase_path("nss/exports_win.def", root_build_dir) ]
-      }
-    }
-  }
-
-  config("nssckbi_config") {
-    include_dirs = [ "nss/lib/ckfw/builtins" ]
-  }
-
-  # This is really more of a pseudo-target to work around the fact that
-  # a single static_library target cannot contain two object files of the
-  # same name (hash.o / hash.obj). Logically, this is part of the
-  # "nss_static" target. By separating it out, it creates a possible
-  # circular dependency between "nss_static" and "nssckbi" when
-  # "exclude_nss_root_certs" is not specified, as "nss_static" depends on
-  # the "builtinsC_GetFunctionList" exported by this target. This is an
-  # artifact of how NSS is being statically built, which is not an
-  # officially supported configuration - normally, "nssckbi.dll/so" would
-  # depend on libnss3.dll/so, and the higher layer caller would instruct
-  # libnss3.dll to dynamically load nssckbi.dll, breaking the circle.
-  #
-  # TODO(rsleevi): http://crbug.com/128134 - Break the circular dependency
-  # without requiring nssckbi to be built as a shared library.
-  source_set("nssckbi") {
-    visibility = [ ":nss" ]  # This target is internal implementation detail.
-
-    sources = [
-      "nss/lib/ckfw/builtins/anchor.c",
-      "nss/lib/ckfw/builtins/bfind.c",
-      "nss/lib/ckfw/builtins/binst.c",
-      "nss/lib/ckfw/builtins/bobject.c",
-      "nss/lib/ckfw/builtins/bsession.c",
-      "nss/lib/ckfw/builtins/bslot.c",
-      "nss/lib/ckfw/builtins/btoken.c",
-      "nss/lib/ckfw/builtins/builtins.h",
-      "nss/lib/ckfw/builtins/certdata.c",
-      "nss/lib/ckfw/builtins/ckbiver.c",
-      "nss/lib/ckfw/builtins/constants.c",
-      "nss/lib/ckfw/builtins/nssckbi.h",
-      "nss/lib/ckfw/ck.h",
-      "nss/lib/ckfw/ckfw.h",
-      "nss/lib/ckfw/ckfwm.h",
-      "nss/lib/ckfw/ckfwtm.h",
-      "nss/lib/ckfw/ckmd.h",
-      "nss/lib/ckfw/ckt.h",
-      "nss/lib/ckfw/crypto.c",
-      "nss/lib/ckfw/find.c",
-      "nss/lib/ckfw/hash.c",
-      "nss/lib/ckfw/instance.c",
-      "nss/lib/ckfw/mechanism.c",
-      "nss/lib/ckfw/mutex.c",
-      "nss/lib/ckfw/nssck.api",
-      "nss/lib/ckfw/nssckepv.h",
-      "nss/lib/ckfw/nssckft.h",
-      "nss/lib/ckfw/nssckfw.h",
-      "nss/lib/ckfw/nssckfwc.h",
-      "nss/lib/ckfw/nssckfwt.h",
-      "nss/lib/ckfw/nssckg.h",
-      "nss/lib/ckfw/nssckmdt.h",
-      "nss/lib/ckfw/nssckt.h",
-      "nss/lib/ckfw/object.c",
-      "nss/lib/ckfw/session.c",
-      "nss/lib/ckfw/sessobj.c",
-      "nss/lib/ckfw/slot.c",
-      "nss/lib/ckfw/token.c",
-      "nss/lib/ckfw/wrap.c",
-    ]
-
-    configs -= [ "//build/config/compiler:chromium_code" ]
-
-    if (is_win) {
-      configs -= [ "//build/config/win:unicode" ]  # Requires 8-bit mode.
-    }
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-
-    include_dirs = [ "nss/lib/ckfw" ]
-    public_configs = [ ":nssckbi_config" ]
-
-    public_deps = [
-      ":nss_static",
-    ]
-  }
-
-  config("nss_static_config") {
-    defines = [
-      "NSS_STATIC",
-      "NSS_USE_STATIC_LIBS",
-      "USE_UTIL_DIRECTLY",
-    ]
-    if (is_win) {
-      defines += [ "_WINDOWS" ]
-    }
-    include_dirs = [
-      "nspr/pr/include",
-      "nspr/lib/ds",
-      "nspr/lib/libc/include",
-      "nss/lib/base",
-      "nss/lib/certdb",
-      "nss/lib/certhigh",
-      "nss/lib/cryptohi",
-      "nss/lib/dev",
-      "nss/lib/freebl",
-      "nss/lib/freebl/ecl",
-      "nss/lib/nss",
-      "nss/lib/pk11wrap",
-      "nss/lib/pkcs7",
-      "nss/lib/pki",
-      "nss/lib/smime",
-      "nss/lib/softoken",
-      "nss/lib/util",
-    ]
-  }
-
-  if (is_win && current_cpu == "x86") {
-    source_set("nss_static_avx") {
-      sources = [
-        "nss/lib/freebl/intel-gcm-wrap.c",
-        "nss/lib/freebl/intel-gcm-x86-masm.asm",
-        "nss/lib/freebl/intel-gcm.h",
-      ]
-      defines = [
-        "_WINDOWS",
-        "_X86_",
-        "INTEL_GCM",
-        "MP_API_COMPATIBLE",
-        "MP_ASSEMBLY_DIV_2DX1D",
-        "MP_ASSEMBLY_MULTIPLY",
-        "MP_ASSEMBLY_SQUARE",
-        "MP_NO_MP_WORD",
-        "MP_USE_UINT_DIGIT",
-        "NSS_DISABLE_DBM",
-        "NSS_STATIC",
-        "NSS_USE_STATIC_LIBS",
-        "NSS_X86",
-        "NSS_X86_OR_X64",
-        "RIJNDAEL_INCLUDE_TABLES",
-        "SHLIB_PREFIX=\"\"",
-        "SHLIB_SUFFIX=\"dll\"",
-        "SHLIB_VERSION=\"3\"",
-        "SOFTOKEN_LIB_NAME=\"softokn3.dll\"",
-        "SOFTOKEN_SHLIB_VERSION=\"3\"",
-        "USE_HW_AES",
-        "USE_UTIL_DIRECTLY",
-        "WIN32",
-        "WIN95",
-        "XP_PC",
-      ]
-      include_dirs = [
-        "nspr/pr/include",
-        "nspr/lib/ds",
-        "nspr/lib/libc/include",
-        "nss/lib/freebl/ecl",
-        "nss/lib/util",
-      ]
-    }
-  }
-
-  source_set("nss_static") {
-    visibility = [ ":*" ]  # Internal implementation detail.
-
-    sources = [
-      "nss/lib/base/arena.c",
-      "nss/lib/base/base.h",
-      "nss/lib/base/baset.h",
-      "nss/lib/base/error.c",
-      "nss/lib/base/errorval.c",
-      "nss/lib/base/hash.c",
-      "nss/lib/base/hashops.c",
-      "nss/lib/base/item.c",
-      "nss/lib/base/libc.c",
-      "nss/lib/base/list.c",
-      "nss/lib/base/nssbase.h",
-      "nss/lib/base/nssbaset.h",
-      "nss/lib/base/nssutf8.c",
-      "nss/lib/base/tracker.c",
-      "nss/lib/certdb/alg1485.c",
-      "nss/lib/certdb/cert.h",
-      "nss/lib/certdb/certdb.c",
-      "nss/lib/certdb/certdb.h",
-      "nss/lib/certdb/certi.h",
-      "nss/lib/certdb/certt.h",
-      "nss/lib/certdb/certv3.c",
-      "nss/lib/certdb/certxutl.c",
-      "nss/lib/certdb/certxutl.h",
-      "nss/lib/certdb/crl.c",
-      "nss/lib/certdb/genname.c",
-      "nss/lib/certdb/genname.h",
-      "nss/lib/certdb/polcyxtn.c",
-      "nss/lib/certdb/secname.c",
-      "nss/lib/certdb/stanpcertdb.c",
-      "nss/lib/certdb/xauthkid.c",
-      "nss/lib/certdb/xbsconst.c",
-      "nss/lib/certdb/xconst.c",
-      "nss/lib/certdb/xconst.h",
-      "nss/lib/certhigh/certhigh.c",
-      "nss/lib/certhigh/certhtml.c",
-      "nss/lib/certhigh/certreq.c",
-      "nss/lib/certhigh/certvfy.c",
-      "nss/lib/certhigh/crlv2.c",
-      "nss/lib/certhigh/ocsp.c",
-      "nss/lib/certhigh/ocsp.h",
-      "nss/lib/certhigh/ocspi.h",
-      "nss/lib/certhigh/ocspsig.c",
-      "nss/lib/certhigh/ocspt.h",
-      "nss/lib/certhigh/ocspti.h",
-      "nss/lib/certhigh/xcrldist.c",
-      "nss/lib/cryptohi/cryptohi.h",
-      "nss/lib/cryptohi/cryptoht.h",
-      "nss/lib/cryptohi/dsautil.c",
-      "nss/lib/cryptohi/key.h",
-      "nss/lib/cryptohi/keyhi.h",
-      "nss/lib/cryptohi/keyi.h",
-      "nss/lib/cryptohi/keyt.h",
-      "nss/lib/cryptohi/keythi.h",
-      "nss/lib/cryptohi/sechash.c",
-      "nss/lib/cryptohi/sechash.h",
-      "nss/lib/cryptohi/seckey.c",
-      "nss/lib/cryptohi/secsign.c",
-      "nss/lib/cryptohi/secvfy.c",
-      "nss/lib/dev/ckhelper.c",
-      "nss/lib/dev/ckhelper.h",
-      "nss/lib/dev/dev.h",
-      "nss/lib/dev/devm.h",
-      "nss/lib/dev/devslot.c",
-      "nss/lib/dev/devt.h",
-      "nss/lib/dev/devtm.h",
-      "nss/lib/dev/devtoken.c",
-      "nss/lib/dev/devutil.c",
-      "nss/lib/dev/nssdev.h",
-      "nss/lib/dev/nssdevt.h",
-      "nss/lib/freebl/aeskeywrap.c",
-      "nss/lib/freebl/alg2268.c",
-      "nss/lib/freebl/alghmac.c",
-      "nss/lib/freebl/alghmac.h",
-      "nss/lib/freebl/arcfive.c",
-      "nss/lib/freebl/arcfour.c",
-      "nss/lib/freebl/blapi.h",
-      "nss/lib/freebl/blapii.h",
-      "nss/lib/freebl/blapit.h",
-      "nss/lib/freebl/camellia.c",
-      "nss/lib/freebl/camellia.h",
-      "nss/lib/freebl/chacha20/chacha20.c",
-      "nss/lib/freebl/chacha20/chacha20.h",
-      "nss/lib/freebl/chacha20/chacha20_vec.c",
-      "nss/lib/freebl/chacha20poly1305.c",
-      "nss/lib/freebl/chacha20poly1305.h",
-      "nss/lib/freebl/ctr.c",
-      "nss/lib/freebl/ctr.h",
-      "nss/lib/freebl/cts.c",
-      "nss/lib/freebl/cts.h",
-      "nss/lib/freebl/des.c",
-      "nss/lib/freebl/des.h",
-      "nss/lib/freebl/desblapi.c",
-      "nss/lib/freebl/dh.c",
-      "nss/lib/freebl/drbg.c",
-      "nss/lib/freebl/dsa.c",
-      "nss/lib/freebl/ec.c",
-      "nss/lib/freebl/ec.h",
-      "nss/lib/freebl/ecdecode.c",
-      "nss/lib/freebl/ecl/ec2.h",
-      "nss/lib/freebl/ecl/ec_naf.c",
-      "nss/lib/freebl/ecl/ecl-curve.h",
-      "nss/lib/freebl/ecl/ecl-exp.h",
-      "nss/lib/freebl/ecl/ecl-priv.h",
-      "nss/lib/freebl/ecl/ecl.c",
-      "nss/lib/freebl/ecl/ecl.h",
-      "nss/lib/freebl/ecl/ecl_curve.c",
-      "nss/lib/freebl/ecl/ecl_gf.c",
-      "nss/lib/freebl/ecl/ecl_mult.c",
-      "nss/lib/freebl/ecl/ecp.h",
-      "nss/lib/freebl/ecl/ecp_256.c",
-      "nss/lib/freebl/ecl/ecp_256_32.c",
-      "nss/lib/freebl/ecl/ecp_384.c",
-      "nss/lib/freebl/ecl/ecp_521.c",
-      "nss/lib/freebl/ecl/ecp_aff.c",
-      "nss/lib/freebl/ecl/ecp_jac.c",
-      "nss/lib/freebl/ecl/ecp_jm.c",
-      "nss/lib/freebl/ecl/ecp_mont.c",
-      "nss/lib/freebl/gcm.c",
-      "nss/lib/freebl/gcm.h",
-      "nss/lib/freebl/hmacct.c",
-      "nss/lib/freebl/hmacct.h",
-      "nss/lib/freebl/intel-aes-x86-masm.asm",
-      "nss/lib/freebl/intel-aes.h",
-      "nss/lib/freebl/jpake.c",
-      "nss/lib/freebl/md2.c",
-      "nss/lib/freebl/md5.c",
-      "nss/lib/freebl/mpi/logtab.h",
-      "nss/lib/freebl/mpi/mp_gf2m-priv.h",
-      "nss/lib/freebl/mpi/mp_gf2m.c",
-      "nss/lib/freebl/mpi/mp_gf2m.h",
-      "nss/lib/freebl/mpi/mpcpucache.c",
-      "nss/lib/freebl/mpi/mpi-config.h",
-      "nss/lib/freebl/mpi/mpi-priv.h",
-      "nss/lib/freebl/mpi/mpi.c",
-      "nss/lib/freebl/mpi/mpi.h",
-      "nss/lib/freebl/mpi/mpi_amd64.c",
-      "nss/lib/freebl/mpi/mpi_arm.c",
-      "nss/lib/freebl/mpi/mpi_arm_mac.c",
-      "nss/lib/freebl/mpi/mpi_x86_asm.c",
-      "nss/lib/freebl/mpi/mplogic.c",
-      "nss/lib/freebl/mpi/mplogic.h",
-      "nss/lib/freebl/mpi/mpmontg.c",
-      "nss/lib/freebl/mpi/mpprime.c",
-      "nss/lib/freebl/mpi/mpprime.h",
-      "nss/lib/freebl/mpi/primes.c",
-      "nss/lib/freebl/nss_build_config_mac.h",
-      "nss/lib/freebl/poly1305/poly1305-donna-x64-sse2-incremental-source.c",
-      "nss/lib/freebl/poly1305/poly1305.c",
-      "nss/lib/freebl/poly1305/poly1305.h",
-      "nss/lib/freebl/pqg.c",
-      "nss/lib/freebl/pqg.h",
-      "nss/lib/freebl/rawhash.c",
-      "nss/lib/freebl/rijndael.c",
-      "nss/lib/freebl/rijndael.h",
-      "nss/lib/freebl/rijndael32.tab",
-      "nss/lib/freebl/rsa.c",
-      "nss/lib/freebl/rsapkcs.c",
-      "nss/lib/freebl/secmpi.h",
-      "nss/lib/freebl/secrng.h",
-      "nss/lib/freebl/seed.c",
-      "nss/lib/freebl/seed.h",
-      "nss/lib/freebl/sha256.h",
-      "nss/lib/freebl/sha512.c",
-      "nss/lib/freebl/sha_fast.c",
-      "nss/lib/freebl/sha_fast.h",
-      "nss/lib/freebl/shsign.h",
-      "nss/lib/freebl/shvfy.c",
-      "nss/lib/freebl/sysrand.c",
-      "nss/lib/freebl/tlsprfalg.c",
-      "nss/lib/freebl/unix_rand.c",
-      "nss/lib/freebl/win_rand.c",
-      "nss/lib/nss/nss.h",
-      "nss/lib/nss/nssinit.c",
-      "nss/lib/nss/nssrenam.h",
-      "nss/lib/nss/utilwrap.c",
-      "nss/lib/pk11wrap/debug_module.c",
-      "nss/lib/pk11wrap/dev3hack.c",
-      "nss/lib/pk11wrap/dev3hack.h",
-      "nss/lib/pk11wrap/pk11akey.c",
-      "nss/lib/pk11wrap/pk11auth.c",
-      "nss/lib/pk11wrap/pk11cert.c",
-      "nss/lib/pk11wrap/pk11cxt.c",
-      "nss/lib/pk11wrap/pk11err.c",
-      "nss/lib/pk11wrap/pk11func.h",
-      "nss/lib/pk11wrap/pk11kea.c",
-      "nss/lib/pk11wrap/pk11list.c",
-      "nss/lib/pk11wrap/pk11load.c",
-      "nss/lib/pk11wrap/pk11mech.c",
-      "nss/lib/pk11wrap/pk11merge.c",
-      "nss/lib/pk11wrap/pk11nobj.c",
-      "nss/lib/pk11wrap/pk11obj.c",
-      "nss/lib/pk11wrap/pk11pars.c",
-      "nss/lib/pk11wrap/pk11pbe.c",
-      "nss/lib/pk11wrap/pk11pk12.c",
-      "nss/lib/pk11wrap/pk11pqg.c",
-      "nss/lib/pk11wrap/pk11pqg.h",
-      "nss/lib/pk11wrap/pk11priv.h",
-      "nss/lib/pk11wrap/pk11pub.h",
-      "nss/lib/pk11wrap/pk11sdr.c",
-      "nss/lib/pk11wrap/pk11sdr.h",
-      "nss/lib/pk11wrap/pk11skey.c",
-      "nss/lib/pk11wrap/pk11slot.c",
-      "nss/lib/pk11wrap/pk11util.c",
-      "nss/lib/pk11wrap/secmod.h",
-      "nss/lib/pk11wrap/secmodi.h",
-      "nss/lib/pk11wrap/secmodt.h",
-      "nss/lib/pk11wrap/secmodti.h",
-      "nss/lib/pk11wrap/secpkcs5.h",
-      "nss/lib/pkcs7/certread.c",
-      "nss/lib/pkcs7/p7common.c",
-      "nss/lib/pkcs7/p7create.c",
-      "nss/lib/pkcs7/p7decode.c",
-      "nss/lib/pkcs7/p7encode.c",
-      "nss/lib/pkcs7/p7local.c",
-      "nss/lib/pkcs7/p7local.h",
-      "nss/lib/pkcs7/pkcs7t.h",
-      "nss/lib/pkcs7/secmime.c",
-      "nss/lib/pkcs7/secmime.h",
-      "nss/lib/pkcs7/secpkcs7.h",
-      "nss/lib/pki/asymmkey.c",
-      "nss/lib/pki/certdecode.c",
-      "nss/lib/pki/certificate.c",
-      "nss/lib/pki/cryptocontext.c",
-      "nss/lib/pki/nsspki.h",
-      "nss/lib/pki/nsspkit.h",
-      "nss/lib/pki/pki.h",
-      "nss/lib/pki/pki3hack.c",
-      "nss/lib/pki/pki3hack.h",
-      "nss/lib/pki/pkibase.c",
-      "nss/lib/pki/pkim.h",
-      "nss/lib/pki/pkistore.c",
-      "nss/lib/pki/pkistore.h",
-      "nss/lib/pki/pkit.h",
-      "nss/lib/pki/pkitm.h",
-      "nss/lib/pki/symmkey.c",
-      "nss/lib/pki/tdcache.c",
-      "nss/lib/pki/trustdomain.c",
-      "nss/lib/smime/cms.h",
-      "nss/lib/smime/cmslocal.h",
-      "nss/lib/smime/cmsreclist.h",
-      "nss/lib/smime/cmst.h",
-      "nss/lib/smime/smime.h",
-      "nss/lib/softoken/fipsaudt.c",
-      "nss/lib/softoken/fipstest.c",
-      "nss/lib/softoken/fipstokn.c",
-      "nss/lib/softoken/jpakesftk.c",
-      "nss/lib/softoken/lgglue.c",
-      "nss/lib/softoken/lgglue.h",
-      "nss/lib/softoken/lowkey.c",
-      "nss/lib/softoken/lowkeyi.h",
-      "nss/lib/softoken/lowkeyti.h",
-      "nss/lib/softoken/lowpbe.c",
-      "nss/lib/softoken/lowpbe.h",
-      "nss/lib/softoken/padbuf.c",
-      "nss/lib/softoken/pkcs11.c",
-      "nss/lib/softoken/pkcs11c.c",
-      "nss/lib/softoken/pkcs11i.h",
-      "nss/lib/softoken/pkcs11ni.h",
-      "nss/lib/softoken/pkcs11u.c",
-      "nss/lib/softoken/sdb.c",
-      "nss/lib/softoken/sdb.h",
-      "nss/lib/softoken/sftkdb.c",
-      "nss/lib/softoken/sftkdb.h",
-      "nss/lib/softoken/sftkdbt.h",
-      "nss/lib/softoken/sftkdbti.h",
-      "nss/lib/softoken/sftkhmac.c",
-      "nss/lib/softoken/sftkpars.c",
-      "nss/lib/softoken/sftkpars.h",
-      "nss/lib/softoken/sftkpwd.c",
-      "nss/lib/softoken/softkver.c",
-      "nss/lib/softoken/softkver.h",
-      "nss/lib/softoken/softoken.h",
-      "nss/lib/softoken/softoknt.h",
-      "nss/lib/softoken/tlsprf.c",
-      "nss/lib/ssl/sslerr.h",
-      "nss/lib/util/SECerrs.h",
-      "nss/lib/util/base64.h",
-      "nss/lib/util/ciferfam.h",
-      "nss/lib/util/derdec.c",
-      "nss/lib/util/derenc.c",
-      "nss/lib/util/dersubr.c",
-      "nss/lib/util/dertime.c",
-      "nss/lib/util/errstrs.c",
-      "nss/lib/util/hasht.h",
-      "nss/lib/util/nssb64.h",
-      "nss/lib/util/nssb64d.c",
-      "nss/lib/util/nssb64e.c",
-      "nss/lib/util/nssb64t.h",
-      "nss/lib/util/nssilckt.h",
-      "nss/lib/util/nssilock.c",
-      "nss/lib/util/nssilock.h",
-      "nss/lib/util/nsslocks.h",
-      "nss/lib/util/nssrwlk.c",
-      "nss/lib/util/nssrwlk.h",
-      "nss/lib/util/nssrwlkt.h",
-      "nss/lib/util/nssutil.h",
-      "nss/lib/util/oidstring.c",
-      "nss/lib/util/pkcs11.h",
-      "nss/lib/util/pkcs11f.h",
-      "nss/lib/util/pkcs11n.h",
-      "nss/lib/util/pkcs11p.h",
-      "nss/lib/util/pkcs11t.h",
-      "nss/lib/util/pkcs11u.h",
-      "nss/lib/util/pkcs1sig.c",
-      "nss/lib/util/pkcs1sig.h",
-      "nss/lib/util/portreg.c",
-      "nss/lib/util/portreg.h",
-      "nss/lib/util/quickder.c",
-      "nss/lib/util/secalgid.c",
-      "nss/lib/util/secasn1.h",
-      "nss/lib/util/secasn1d.c",
-      "nss/lib/util/secasn1e.c",
-      "nss/lib/util/secasn1t.h",
-      "nss/lib/util/secasn1u.c",
-      "nss/lib/util/seccomon.h",
-      "nss/lib/util/secder.h",
-      "nss/lib/util/secdert.h",
-      "nss/lib/util/secdig.c",
-      "nss/lib/util/secdig.h",
-      "nss/lib/util/secdigt.h",
-      "nss/lib/util/secerr.h",
-      "nss/lib/util/secitem.c",
-      "nss/lib/util/secitem.h",
-      "nss/lib/util/secoid.c",
-      "nss/lib/util/secoid.h",
-      "nss/lib/util/secoidt.h",
-      "nss/lib/util/secport.c",
-      "nss/lib/util/secport.h",
-      "nss/lib/util/sectime.c",
-      "nss/lib/util/templates.c",
-      "nss/lib/util/utf8.c",
-      "nss/lib/util/utilmod.c",
-      "nss/lib/util/utilmodt.h",
-      "nss/lib/util/utilpars.c",
-      "nss/lib/util/utilpars.h",
-      "nss/lib/util/utilparst.h",
-      "nss/lib/util/utilrename.h",
-    ]
-
-    sources -= [
-      # mpi_arm.c is included by mpi_arm_mac.c.
-      # NOTE: mpi_arm.c can be used directly on Linux. mpi_arm.c will need
-      # to be excluded conditionally if we start to build NSS on Linux.
-      "nss/lib/freebl/mpi/mpi_arm.c",
-
-      # primes.c is included by mpprime.c.
-      "nss/lib/freebl/mpi/primes.c",
-
-      # unix_rand.c and win_rand.c are included by sysrand.c.
-      "nss/lib/freebl/unix_rand.c",
-      "nss/lib/freebl/win_rand.c",
-
-      # debug_module.c is included by pk11load.c.
-      "nss/lib/pk11wrap/debug_module.c",
-    ]
-
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    if (is_win) {
-      configs -= [ "//build/config/win:unicode" ]  # Requires 8-bit mode.
-    }
-    configs += [
-      "//build/config/compiler:no_chromium_code",
-      "//build/config/compiler:no_size_t_to_int_warning",
-    ]
-    public_configs = [ ":nss_static_config" ]
-
-    cflags = []
-
-    # Only need the defines and includes not in nss_static_config.
-    defines = [
-      "MP_API_COMPATIBLE",
-      "NSS_DISABLE_DBM",
-      "RIJNDAEL_INCLUDE_TABLES",
-      "SHLIB_VERSION=\"3\"",
-      "SOFTOKEN_SHLIB_VERSION=\"3\"",
-    ]
-    include_dirs = [
-      "nss/lib/freebl/mpi",
-      "nss/lib/ssl",
-    ]
-
-    if (is_win) {
-      cflags += [ "/wd4101" ]  # Unreferenced local variable.
-    }
-
-    if (include_nss_libpkix) {
-      sources += [
-        "nss/lib/certhigh/certvfypkix.c",
-        "nss/lib/certhigh/certvfypkixprint.c",
-        "nss/lib/libpkix/include/pkix.h",
-        "nss/lib/libpkix/include/pkix_certsel.h",
-        "nss/lib/libpkix/include/pkix_certstore.h",
-        "nss/lib/libpkix/include/pkix_checker.h",
-        "nss/lib/libpkix/include/pkix_crlsel.h",
-        "nss/lib/libpkix/include/pkix_errorstrings.h",
-        "nss/lib/libpkix/include/pkix_params.h",
-        "nss/lib/libpkix/include/pkix_pl_pki.h",
-        "nss/lib/libpkix/include/pkix_pl_system.h",
-        "nss/lib/libpkix/include/pkix_results.h",
-        "nss/lib/libpkix/include/pkix_revchecker.h",
-        "nss/lib/libpkix/include/pkix_sample_modules.h",
-        "nss/lib/libpkix/include/pkix_util.h",
-        "nss/lib/libpkix/include/pkixt.h",
-        "nss/lib/libpkix/pkix/certsel/pkix_certselector.c",
-        "nss/lib/libpkix/pkix/certsel/pkix_certselector.h",
-        "nss/lib/libpkix/pkix/certsel/pkix_comcertselparams.c",
-        "nss/lib/libpkix/pkix/certsel/pkix_comcertselparams.h",
-        "nss/lib/libpkix/pkix/checker/pkix_basicconstraintschecker.c",
-        "nss/lib/libpkix/pkix/checker/pkix_basicconstraintschecker.h",
-        "nss/lib/libpkix/pkix/checker/pkix_certchainchecker.c",
-        "nss/lib/libpkix/pkix/checker/pkix_certchainchecker.h",
-        "nss/lib/libpkix/pkix/checker/pkix_crlchecker.c",
-        "nss/lib/libpkix/pkix/checker/pkix_crlchecker.h",
-        "nss/lib/libpkix/pkix/checker/pkix_ekuchecker.c",
-        "nss/lib/libpkix/pkix/checker/pkix_ekuchecker.h",
-        "nss/lib/libpkix/pkix/checker/pkix_expirationchecker.c",
-        "nss/lib/libpkix/pkix/checker/pkix_expirationchecker.h",
-        "nss/lib/libpkix/pkix/checker/pkix_namechainingchecker.c",
-        "nss/lib/libpkix/pkix/checker/pkix_namechainingchecker.h",
-        "nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.c",
-        "nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.h",
-        "nss/lib/libpkix/pkix/checker/pkix_ocspchecker.c",
-        "nss/lib/libpkix/pkix/checker/pkix_ocspchecker.h",
-        "nss/lib/libpkix/pkix/checker/pkix_policychecker.c",
-        "nss/lib/libpkix/pkix/checker/pkix_policychecker.h",
-        "nss/lib/libpkix/pkix/checker/pkix_revocationchecker.c",
-        "nss/lib/libpkix/pkix/checker/pkix_revocationchecker.h",
-        "nss/lib/libpkix/pkix/checker/pkix_revocationmethod.c",
-        "nss/lib/libpkix/pkix/checker/pkix_revocationmethod.h",
-        "nss/lib/libpkix/pkix/checker/pkix_signaturechecker.c",
-        "nss/lib/libpkix/pkix/checker/pkix_signaturechecker.h",
-        "nss/lib/libpkix/pkix/checker/pkix_targetcertchecker.c",
-        "nss/lib/libpkix/pkix/checker/pkix_targetcertchecker.h",
-        "nss/lib/libpkix/pkix/crlsel/pkix_comcrlselparams.c",
-        "nss/lib/libpkix/pkix/crlsel/pkix_comcrlselparams.h",
-        "nss/lib/libpkix/pkix/crlsel/pkix_crlselector.c",
-        "nss/lib/libpkix/pkix/crlsel/pkix_crlselector.h",
-        "nss/lib/libpkix/pkix/params/pkix_procparams.c",
-        "nss/lib/libpkix/pkix/params/pkix_procparams.h",
-        "nss/lib/libpkix/pkix/params/pkix_resourcelimits.c",
-        "nss/lib/libpkix/pkix/params/pkix_resourcelimits.h",
-        "nss/lib/libpkix/pkix/params/pkix_trustanchor.c",
-        "nss/lib/libpkix/pkix/params/pkix_trustanchor.h",
-        "nss/lib/libpkix/pkix/params/pkix_valparams.c",
-        "nss/lib/libpkix/pkix/params/pkix_valparams.h",
-        "nss/lib/libpkix/pkix/results/pkix_buildresult.c",
-        "nss/lib/libpkix/pkix/results/pkix_buildresult.h",
-        "nss/lib/libpkix/pkix/results/pkix_policynode.c",
-        "nss/lib/libpkix/pkix/results/pkix_policynode.h",
-        "nss/lib/libpkix/pkix/results/pkix_valresult.c",
-        "nss/lib/libpkix/pkix/results/pkix_valresult.h",
-        "nss/lib/libpkix/pkix/results/pkix_verifynode.c",
-        "nss/lib/libpkix/pkix/results/pkix_verifynode.h",
-        "nss/lib/libpkix/pkix/store/pkix_store.c",
-        "nss/lib/libpkix/pkix/store/pkix_store.h",
-        "nss/lib/libpkix/pkix/top/pkix_build.c",
-        "nss/lib/libpkix/pkix/top/pkix_build.h",
-        "nss/lib/libpkix/pkix/top/pkix_lifecycle.c",
-        "nss/lib/libpkix/pkix/top/pkix_lifecycle.h",
-        "nss/lib/libpkix/pkix/top/pkix_validate.c",
-        "nss/lib/libpkix/pkix/top/pkix_validate.h",
-        "nss/lib/libpkix/pkix/util/pkix_error.c",
-        "nss/lib/libpkix/pkix/util/pkix_error.h",
-        "nss/lib/libpkix/pkix/util/pkix_errpaths.c",
-        "nss/lib/libpkix/pkix/util/pkix_list.c",
-        "nss/lib/libpkix/pkix/util/pkix_list.h",
-        "nss/lib/libpkix/pkix/util/pkix_logger.c",
-        "nss/lib/libpkix/pkix/util/pkix_logger.h",
-        "nss/lib/libpkix/pkix/util/pkix_tools.c",
-        "nss/lib/libpkix/pkix/util/pkix_tools.h",
-        "nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_aiamgr.c",
-        "nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_aiamgr.h",
-        "nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_colcertstore.c",
-        "nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_colcertstore.h",
-        "nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpcertstore.c",
-        "nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpcertstore.h",
-        "nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.c",
-        "nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.h",
-        "nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_nsscontext.c",
-        "nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_nsscontext.h",
-        "nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_pk11certstore.c",
-        "nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_pk11certstore.h",
-        "nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.c",
-        "nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.h",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_basicconstraints.c",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_basicconstraints.h",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_cert.c",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_cert.h",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyinfo.c",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyinfo.h",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicymap.c",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicymap.h",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyqualifier.c",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyqualifier.h",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crl.c",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crl.h",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crldp.c",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crldp.h",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crlentry.c",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crlentry.h",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_date.c",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_date.h",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_generalname.c",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_generalname.h",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_infoaccess.c",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_infoaccess.h",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_nameconstraints.c",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_nameconstraints.h",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspcertid.c",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspcertid.h",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocsprequest.c",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocsprequest.h",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspresponse.c",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspresponse.h",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_publickey.c",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_publickey.h",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_x500name.c",
-        "nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_x500name.h",
-        "nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bigint.c",
-        "nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bigint.h",
-        "nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bytearray.c",
-        "nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bytearray.h",
-        "nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_common.c",
-        "nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_common.h",
-        "nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_error.c",
-        "nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_hashtable.c",
-        "nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_hashtable.h",
-        "nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.c",
-        "nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.h",
-        "nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mem.c",
-        "nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mem.h",
-        "nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_monitorlock.c",
-        "nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_monitorlock.h",
-        "nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mutex.c",
-        "nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mutex.h",
-        "nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.c",
-        "nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.h",
-        "nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_oid.c",
-        "nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_oid.h",
-        "nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_primhash.c",
-        "nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_primhash.h",
-        "nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_rwlock.c",
-        "nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_rwlock.h",
-        "nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_string.c",
-        "nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_string.h",
-      ]
-
-      # Disable the LDAP code in libpkix.
-      defines += [ "NSS_PKIX_NO_LDAP" ]
-
-      include_dirs += [
-        "nss/lib/libpkix/include",
-        "nss/lib/libpkix/pkix/certsel",
-        "nss/lib/libpkix/pkix/checker",
-        "nss/lib/libpkix/pkix/crlsel",
-        "nss/lib/libpkix/pkix/params",
-        "nss/lib/libpkix/pkix/results",
-        "nss/lib/libpkix/pkix/store",
-        "nss/lib/libpkix/pkix/top",
-        "nss/lib/libpkix/pkix/util",
-        "nss/lib/libpkix/pkix_pl_nss/module",
-        "nss/lib/libpkix/pkix_pl_nss/pki",
-        "nss/lib/libpkix/pkix_pl_nss/system",
-      ]
-    } else {
-      defines += [ "NSS_DISABLE_LIBPKIX" ]
-    }
-
-    if (!include_nss_root_certs) {
-      defines += [ "NSS_DISABLE_ROOT_CERTS" ]
-    }
-
-    if (current_cpu == "x64" && !is_win) {
-      sources -= [
-        "nss/lib/freebl/chacha20/chacha20.c",
-        "nss/lib/freebl/poly1305/poly1305.c",
-      ]
-    } else {
-      sources -= [
-        "nss/lib/freebl/chacha20/chacha20_vec.c",
-        "nss/lib/freebl/poly1305/poly1305-donna-x64-sse2-incremental-source.c",
-      ]
-    }
-
-    if (is_mac || is_ios) {
-      sources -= [ "nss/lib/freebl/mpi/mpi_amd64.c" ]
-      cflags += [
-        "-include",
-        rebase_path("//third_party/nss/nss/lib/freebl/nss_build_config_mac.h",
-                    root_build_dir),
-      ]
-      defines += [
-        "XP_UNIX",
-        "DARWIN",
-        "HAVE_STRERROR",
-        "HAVE_BSD_FLOCK",
-        "SHLIB_SUFFIX=\"dylib\"",
-        "SHLIB_PREFIX=\"lib\"",
-        "SOFTOKEN_LIB_NAME=\"libsoftokn3.dylib\"",
-      ]
-
-      configs -= [ "//build/config/gcc:symbol_visibility_hidden" ]
-    } else {
-      # Not Mac/iOS.
-      sources -= [ "nss/lib/freebl/mpi/mpi_arm_mac.c" ]
-    }
-
-    if (is_win) {
-      defines += [
-        "SHLIB_SUFFIX=\"dll\"",
-        "SHLIB_PREFIX=\"\"",
-        "SOFTOKEN_LIB_NAME=\"softokn3.dll\"",
-        "XP_PC",
-        "WIN32",
-        "WIN95",
-      ]
-
-      if (current_cpu == "x86") {
-        defines += [
-          "NSS_X86_OR_X64",
-          "NSS_X86",
-          "_X86_",
-          "MP_ASSEMBLY_MULTIPLY",
-          "MP_ASSEMBLY_SQUARE",
-          "MP_ASSEMBLY_DIV_2DX1D",
-          "MP_USE_UINT_DIGIT",
-          "MP_NO_MP_WORD",
-          "USE_HW_AES",
-          "INTEL_GCM",
-        ]
-        sources -= [ "nss/lib/freebl/mpi/mpi_amd64.c" ]
-      } else if (current_cpu == "x64") {
-        sources -= [
-          "nss/lib/freebl/intel-aes-x86-masm.asm",
-          "nss/lib/freebl/mpi/mpi_amd64.c",
-          "nss/lib/freebl/mpi/mpi_x86_asm.c",
-        ]
-        defines += [
-          "NSS_USE_64",
-          "NSS_X86_OR_X64",
-          "NSS_X64",
-          "_AMD64_",
-          "MP_CHAR_STORE_SLOW",
-          "MP_IS_LITTLE_ENDIAN",
-          "WIN64",
-        ]
-      }
-    } else {
-      # Not Windows.
-      sources -= [
-        # mpi_x86_asm.c contains MSVC inline assembly code.
-        "nss/lib/freebl/mpi/mpi_x86_asm.c",
-      ]
-    }
-
-    if (is_clang) {
-      cflags += [
-        # nss doesn"t explicitly cast between different enum types.
-        "-Wno-conversion",
-
-        # nss passes "const char*" through "void*".
-        "-Wno-incompatible-pointer-types",
-
-        # nss prefers `a && b || c` over `(a && b) || c`.
-        "-Wno-logical-op-parentheses",
-
-        # nss doesn"t use exhaustive switches on enums
-        "-Wno-switch",
-
-        # nss has some `unsigned < 0` checks.
-        "-Wno-tautological-compare",
-      ]
-    }
-
-    public_deps = [
-      ":nspr",
-    ]
-    deps = [
-      ":nspr",
-      "//third_party/sqlite",
-    ]
-
-    if (is_win && current_cpu == "x86") {
-      deps += [ ":nss_static_avx" ]
-    }
-  }
-}  # Windows/Mac/iOS.
diff --git a/build/secondary/tools/grit/BUILD.gn b/build/secondary/tools/grit/BUILD.gn
deleted file mode 100644
index 660bf1b..0000000
--- a/build/secondary/tools/grit/BUILD.gn
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This target creates a stamp file that depends on all the sources in the grit
-# directory. By depending on this, a target can force itself to be rebuilt if
-# grit itself changes.
-action("grit_sources") {
-  depfile = "$target_out_dir/grit_sources.d"
-  script = "//build/secondary/tools/grit/stamp_grit_sources.py"
-
-  inputs = [
-    "grit.py",
-  ]
-
-  # Note that we can't call this "grit_sources.stamp" because that file is
-  # implicitly created by GN for script actions.
-  outputs = [
-    "$target_out_dir/grit_sources.script.stamp",
-  ]
-
-  args = [
-    rebase_path("//tools/grit", root_build_dir),
-    rebase_path(outputs[0], root_build_dir),
-    rebase_path(depfile, root_build_dir),
-  ]
-}
diff --git a/build/secondary/tools/grit/grit_rule.gni b/build/secondary/tools/grit/grit_rule.gni
deleted file mode 100644
index bdf812f..0000000
--- a/build/secondary/tools/grit/grit_rule.gni
+++ /dev/null
@@ -1,483 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# Instantiate grit. This will produce a script target to run grit, and a
-# static library that compiles the .cc files.
-#
-# Parameters
-#
-#   source (required)
-#       Path to .grd file.
-#
-#   outputs (required)
-#       List of outputs from grit, relative to the target_gen_dir. Grit will
-#       verify at build time that this list is correct and will fail if there
-#       is a mismatch between the outputs specified by the .grd file and the
-#       outputs list here.
-#
-#       To get this list, you can look in the .grd file for
-#       <output filename="..." and put those filename here. The base directory
-#       of the list in Grit and the output list specified in the GN grit target
-#       are the same (the target_gen_dir) so you can generally copy the names
-#       exactly.
-#
-#       To get the list of outputs programatically, run:
-#           python tools/grit/grit_info.py --outputs . path/to/your.grd
-#       And strip the leading "./" from the output files.
-#
-#   defines (optional)
-#       Extra defines to pass to grit (on top of the global grit_defines list).
-#
-#   grit_flags (optional)
-#       List of strings containing extra command-line flags to pass to Grit.
-#
-#   resource_ids (optional)
-#       Path to a grit "firstidsfile". Default is
-#       //tools/gritsettings/resource_ids. Set to "" to use the value specified
-#       in the <grit> nodes of the processed files.
-#
-#   output_dir (optional)
-#       Directory for generated files. If you specify this, you will often
-#       want to specify output_name if the target name is not particularly
-#       unique, since this can cause files from multiple grit targets to
-#       overwrite each other.
-#
-#   output_name (optiona)
-#       Provide an alternate base name for the generated files, like the .d
-#       files. Normally these are based on the target name and go in the
-#       output_dir, but if multiple targets with the same name end up in
-#       the same output_dir, they can collide.
-#
-#   depfile_dir (optional)
-#       If set, used to store the depfile and corresponding stamp file.
-#       Defaults to output_dir
-#
-#   use_qualified_include (optional)
-#       If set, output_dir is not added to include_dirs.
-#
-#   configs (optional)
-#       List of additional configs to be applied to the generated target.
-#   deps  (optional)
-#   inputs  (optional)
-#       List of additional files, required for grit to process source file.
-#   visibility  (optional)
-#       Normal meaning.
-#
-# Example
-#
-#   grit("my_resources") {
-#     # Source and outputs are required.
-#     source = "myfile.grd"
-#     outputs = [
-#       "foo_strings.h",
-#       "foo_strings.pak",
-#     ]
-#
-#     grit_flags = [ "-E", "foo=bar" ]  # Optional extra flags.
-#     # You can also put deps here if the grit source depends on generated
-#     # files.
-#   }
-import("//build/config/chrome_build.gni")
-import("//build/config/crypto.gni")
-import("//build/config/features.gni")
-import("//build/config/ui.gni")
-
-grit_defines = []
-
-# Mac and iOS want Title Case strings.
-use_titlecase_in_grd_files = is_mac || is_ios
-if (use_titlecase_in_grd_files) {
-  grit_defines += [
-    "-D",
-    "use_titlecase",
-  ]
-}
-
-if (is_chrome_branded) {
-  grit_defines += [
-    "-D",
-    "_google_chrome",
-    "-E",
-    "CHROMIUM_BUILD=google_chrome",
-  ]
-} else {
-  grit_defines += [
-    "-D",
-    "_chromium",
-    "-E",
-    "CHROMIUM_BUILD=chromium",
-  ]
-}
-
-if (is_chromeos) {
-  grit_defines += [
-    "-D",
-    "chromeos",
-    "-D",
-    "scale_factors=2x",
-  ]
-}
-
-if (is_desktop_linux) {
-  grit_defines += [
-    "-D",
-    "desktop_linux",
-  ]
-}
-
-if (toolkit_views) {
-  grit_defines += [
-    "-D",
-    "toolkit_views",
-  ]
-}
-
-if (use_aura) {
-  grit_defines += [
-    "-D",
-    "use_aura",
-  ]
-}
-
-if (use_ash) {
-  grit_defines += [
-    "-D",
-    "use_ash",
-  ]
-}
-
-if (use_nss_certs) {
-  grit_defines += [
-    "-D",
-    "use_nss_certs",
-  ]
-}
-
-if (use_ozone) {
-  grit_defines += [
-    "-D",
-    "use_ozone",
-  ]
-}
-
-if (enable_image_loader_extension) {
-  grit_defines += [
-    "-D",
-    "image_loader_extension",
-  ]
-}
-
-if (enable_remoting) {
-  grit_defines += [
-    "-D",
-    "remoting",
-  ]
-}
-
-if (is_android) {
-  grit_defines += [
-    "-t",
-    "android",
-    "-E",
-    "ANDROID_JAVA_TAGGED_ONLY=true",
-  ]
-}
-
-if (is_mac || is_ios) {
-  grit_defines += [
-    "-D",
-    "scale_factors=2x",
-  ]
-}
-
-if (is_ios) {
-  grit_defines += [
-    "-t",
-    "ios",
-
-    # iOS uses a whitelist to filter resources.
-    "-w",
-    rebase_path("//build/ios/grit_whitelist.txt", root_build_dir),
-  ]
-}
-
-if (enable_extensions) {
-  grit_defines += [
-    "-D",
-    "enable_extensions",
-  ]
-}
-if (enable_media_router) {
-  grit_defines += [
-    "-D",
-    "enable_media_router",
-  ]
-}
-if (enable_plugins) {
-  grit_defines += [
-    "-D",
-    "enable_plugins",
-  ]
-}
-if (enable_basic_printing || enable_print_preview) {
-  grit_defines += [
-    "-D",
-    "enable_printing",
-  ]
-  if (enable_print_preview) {
-    grit_defines += [
-      "-D",
-      "enable_print_preview",
-    ]
-  }
-}
-if (enable_themes) {
-  grit_defines += [
-    "-D",
-    "enable_themes",
-  ]
-}
-if (enable_app_list) {
-  grit_defines += [
-    "-D",
-    "enable_app_list",
-  ]
-}
-if (enable_settings_app) {
-  grit_defines += [
-    "-D",
-    "enable_settings_app",
-  ]
-}
-if (enable_google_now) {
-  grit_defines += [
-    "-D",
-    "enable_google_now",
-  ]
-}
-
-# Note: use_concatenated_impulse_responses is omitted. It is never used and
-# should probably be removed from GYP build.
-if (enable_webrtc) {
-  grit_defines += [
-    "-D",
-    "enable_webrtc",
-  ]
-}
-if (enable_hangout_services_extension) {
-  grit_defines += [
-    "-D",
-    "enable_hangout_services_extension",
-  ]
-}
-if (enable_task_manager) {
-  grit_defines += [
-    "-D",
-    "enable_task_manager",
-  ]
-}
-if (enable_notifications) {
-  grit_defines += [
-    "-D",
-    "enable_notifications",
-  ]
-}
-if (enable_wifi_bootstrapping) {
-  grit_defines += [
-    "-D",
-    "enable_wifi_bootstrapping",
-  ]
-}
-if (enable_service_discovery) {
-  grit_defines += [
-    "-D",
-    "enable_service_discovery",
-  ]
-}
-if (mac_views_browser) {
-  grit_defines += [
-    "-D",
-    "mac_views_browser",
-  ]
-}
-
-grit_resource_id_file = "//tools/gritsettings/resource_ids"
-grit_info_script = "//tools/grit/grit_info.py"
-
-template("grit") {
-  assert(defined(invoker.source),
-         "\"source\" must be defined for the grit template $target_name")
-
-  grit_inputs = [ invoker.source ]
-
-  if (defined(invoker.resource_ids)) {
-    resource_ids = invoker.resource_ids
-  } else {
-    resource_ids = grit_resource_id_file
-  }
-  if (resource_ids != "") {
-    # The script depends on the ID file. Only add this dependency if the ID
-    # file is specified.
-    grit_inputs += [ resource_ids ]
-  }
-
-  if (defined(invoker.output_dir)) {
-    output_dir = invoker.output_dir
-  } else {
-    output_dir = target_gen_dir
-  }
-
-  if (defined(invoker.output_name)) {
-    grit_output_name = invoker.output_name
-  } else {
-    grit_output_name = target_name
-  }
-
-  if (defined(invoker.depfile_dir)) {
-    depfile_dir = invoker.depfile_dir
-  } else {
-    depfile_dir = output_dir
-  }
-
-  # These are all passed as arguments to the script so have to be relative to
-  # the build directory.
-  if (resource_ids != "") {
-    resource_ids = rebase_path(resource_ids, root_build_dir)
-  }
-  rebased_output_dir = rebase_path(output_dir, root_build_dir)
-  source_path = rebase_path(invoker.source, root_build_dir)
-
-  if (defined(invoker.grit_flags)) {
-    grit_flags = invoker.grit_flags
-  } else {
-    grit_flags = []  # These are optional so default to empty list.
-  }
-
-  assert_files_flags = []
-
-  # We want to make sure the declared outputs actually match what Grit is
-  # writing. We write the list to a file (some of the output lists are long
-  # enough to not fit on a Windows command line) and ask Grit to verify those
-  # are the actual outputs at runtime.
-  asserted_list_file =
-      "$target_out_dir/${grit_output_name}_expected_outputs.txt"
-  write_file(asserted_list_file,
-             rebase_path(invoker.outputs, root_build_dir, output_dir))
-  assert_files_flags += [ "--assert-file-list=" +
-                          rebase_path(asserted_list_file, root_build_dir) ]
-  grit_outputs =
-      get_path_info(rebase_path(invoker.outputs, ".", output_dir), "abspath")
-
-  # The config and the action below get this visibility son only the generated
-  # source set can depend on them. The variable "target_name" will get
-  # overwritten inside the inner classes so we need to compute it here.
-  target_visibility = [ ":$target_name" ]
-
-  # The current grit setup makes an file in $output_dir/grit/foo.h that
-  # the source code expects to include via "grit/foo.h". It would be nice to
-  # change this to including absolute paths relative to the root gen directory
-  # (like "mycomponent/foo.h"). This config sets up the include path.
-  grit_config = target_name + "_grit_config"
-  config(grit_config) {
-    if (!defined(invoker.use_qualified_include) ||
-        !invoker.use_qualified_include) {
-      include_dirs = [ output_dir ]
-    }
-    visibility = target_visibility
-  }
-
-  grit_custom_target = target_name + "_grit"
-  action(grit_custom_target) {
-    script = "//tools/grit/grit.py"
-    inputs = grit_inputs
-
-    depfile = "$depfile_dir/${grit_output_name}_stamp.d"
-    outputs = [ "${depfile}.stamp" ] + grit_outputs
-
-    args = [
-      "-i",
-      source_path,
-      "build",
-    ]
-    if (resource_ids != "") {
-      args += [
-        "-f",
-        resource_ids,
-      ]
-    }
-    args += [
-              "-o",
-              rebased_output_dir,
-              "--depdir",
-              ".",
-              "--depfile",
-              rebase_path(depfile, root_build_dir),
-              "--write-only-new=1",
-              "--depend-on-stamp",
-            ] + grit_defines
-
-    # Add extra defines with -D flags.
-    if (defined(invoker.defines)) {
-      foreach(i, invoker.defines) {
-        args += [
-          "-D",
-          i,
-        ]
-      }
-    }
-
-    args += grit_flags + assert_files_flags
-
-    if (defined(invoker.visibility)) {
-      # This needs to include both what the invoker specified (since they
-      # probably include generated headers from this target), as well as the
-      # generated source set (since there's no guarantee that the visibility
-      # specified by the invoker includes our target).
-      #
-      # Only define visibility at all if the invoker specified it. Otherwise,
-      # we want to keep the public "no visibility specified" default.
-      visibility = target_visibility + invoker.visibility
-    }
-
-    deps = [
-      "//tools/grit:grit_sources",
-    ]
-    if (defined(invoker.deps)) {
-      deps += invoker.deps
-    }
-    if (defined(invoker.inputs)) {
-      inputs += invoker.inputs
-    }
-  }
-
-  # This is the thing that people actually link with, it must be named the
-  # same as the argument the template was invoked with.
-  source_set(target_name) {
-    # Since we generate a file, we need to be run before the targets that
-    # depend on us.
-    sources = grit_outputs
-
-    # Deps set on the template invocation will go on the action that runs
-    # grit above rather than this library. This target needs to depend on the
-    # action publicly so other scripts can take the outputs from the grit
-    # script as inputs.
-    public_deps = [
-      ":$grit_custom_target",
-    ]
-    public_configs = [ ":$grit_config" ]
-
-    if (defined(invoker.public_configs)) {
-      public_configs += invoker.public_configs
-    }
-
-    if (defined(invoker.configs)) {
-      configs += invoker.configs
-    }
-
-    if (defined(invoker.visibility)) {
-      visibility = invoker.visibility
-    }
-    output_name = grit_output_name
-  }
-}
diff --git a/build/secondary/tools/grit/repack.gni b/build/secondary/tools/grit/repack.gni
deleted file mode 100644
index 1030674..0000000
--- a/build/secondary/tools/grit/repack.gni
+++ /dev/null
@@ -1,47 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This file defines a template to invoke grit repack in a consistent manner.
-#
-# Parameters:
-#   sources  [required]
-#       List of pak files that need to be combined.
-#
-#   output  [required]
-#       File name (single string) of the output file.
-#
-#   repack_options  [optional]
-#       List of extra arguments to pass.
-#
-#   deps  [optional]
-#   visibility  [optional]
-#       Normal meaning.
-template("repack") {
-  action(target_name) {
-    assert(defined(invoker.sources), "Need sources for $target_name")
-    assert(defined(invoker.output), "Need output for $target_name")
-
-    if (defined(invoker.visibility)) {
-      visibility = invoker.visibility
-    }
-
-    script = "//tools/grit/grit/format/repack.py"
-
-    inputs = invoker.sources
-    outputs = [
-      invoker.output,
-    ]
-
-    args = []
-    if (defined(invoker.repack_options)) {
-      args += invoker.repack_options
-    }
-    args += [ rebase_path(invoker.output, root_build_dir) ]
-    args += rebase_path(invoker.sources, root_build_dir)
-
-    if (defined(invoker.deps)) {
-      deps = invoker.deps
-    }
-  }
-}
diff --git a/build/secondary/tools/grit/stamp_grit_sources.py b/build/secondary/tools/grit/stamp_grit_sources.py
deleted file mode 100644
index d43d4b8..0000000
--- a/build/secondary/tools/grit/stamp_grit_sources.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This script enumerates the files in the given directory, writing an empty
-# stamp file and a .d file listing the inputs required to make the stamp. This
-# allows us to dynamically depend on the grit sources without enumerating the
-# grit directory for every invocation of grit (which is what adding the source
-# files to every .grd file's .d file would entail) or shelling out to grit
-# synchronously during GN execution to get the list (which would be slow).
-#
-# Usage:
-#    stamp_grit_sources.py <directory> <stamp-file> <.d-file>
-
-import os
-import sys
-
-def GritSourceFiles(grit_root_dir):
-  files = []
-  for root, _, filenames in os.walk(grit_root_dir):
-    grit_src = [os.path.join(root, f) for f in filenames
-                if f.endswith('.py') and not f.endswith('_unittest.py')]
-    files.extend(grit_src)
-  files = [f.replace('\\', '/') for f in files]
-  return sorted(files)
-
-
-def WriteDepFile(dep_file, stamp_file, source_files):
-  with open(dep_file, "w") as f:
-    f.write(stamp_file)
-    f.write(": ")
-    f.write(' '.join(source_files))
-
-
-def WriteStampFile(stamp_file):
-  with open(stamp_file, "w"):
-    pass
-
-
-def main(argv):
-  if len(argv) != 4:
-    print "Error: expecting 3 args."
-    return 1
-
-  grit_root_dir = sys.argv[1]
-  stamp_file = sys.argv[2]
-  dep_file = sys.argv[3]
-
-  WriteStampFile(stamp_file)
-  WriteDepFile(dep_file, stamp_file, GritSourceFiles(grit_root_dir))
-  return 0
-
-
-if __name__ == '__main__':
-  sys.exit(main(sys.argv))
diff --git a/build/toolchain/fnl/BUILD.gn b/build/toolchain/fnl/BUILD.gn
deleted file mode 100644
index 1e4a075..0000000
--- a/build/toolchain/fnl/BUILD.gn
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//build/toolchain/gcc_toolchain.gni")
-
-declare_args() {
-  toolchain_prefix = ""
-}
-
-gcc_toolchain("target") {
-  assert(toolchain_prefix != "", "Must provide toolchain_prefix")
-
-  cc = "${toolchain_prefix}gcc"
-  cxx = "${toolchain_prefix}g++"
-  ar = "${toolchain_prefix}ar"
-  ld = cxx
-  readelf = "${toolchain_prefix}readelf"
-  nm = "${toolchain_prefix}nm"
-
-  toolchain_cpu = "${target_cpu}"
-  toolchain_os = "linux"
-  is_clang = is_clang
-}
diff --git a/build/toolchain/linux/BUILD.gn b/build/toolchain/linux/BUILD.gn
index c16e31c..ae090b0 100644
--- a/build/toolchain/linux/BUILD.gn
+++ b/build/toolchain/linux/BUILD.gn
@@ -8,6 +8,10 @@
 import("//build/toolchain/gcc_toolchain.gni")
 import("//build/toolchain/goma.gni")
 
+declare_args() {
+  toolchain_prefix = ""
+}
+
 if (use_goma) {
   assert(!use_ccache, "Goma and ccache can't be used together.")
   compiler_prefix = "$goma_dir/gomacc "
@@ -31,14 +35,23 @@
   is_clang = false
 }
 
+gcc_toolchain("arm64") {
+  cc = "${compiler_prefix}aarch64-linux-gnu-gcc"
+  cxx = "${compiler_prefix}aarch64-linux-gnu-g++"
+
+  ar = "aarch64-linux-gnu-ar"
+  ld = cxx
+  readelf = "aarch64-linux-gnu-readelf"
+  nm = "aarch64-linux-gnu-nm"
+
+  toolchain_cpu = "arm64"
+  toolchain_os = "linux"
+  is_clang = false
+}
+
 gcc_toolchain("clang_x86") {
-  if (use_clang_type_profiler) {
-    prefix = rebase_path("//third_party/llvm-allocated-type/Linux_ia32/bin",
-                         root_build_dir)
-  } else {
-    prefix = rebase_path("//third_party/llvm-build/Release+Asserts/bin",
-                         root_build_dir)
-  }
+  prefix = rebase_path("//third_party/llvm-build/Release+Asserts/bin",
+                       root_build_dir)
   cc = "${compiler_prefix}$prefix/clang"
   cxx = "${compiler_prefix}$prefix/clang++"
   readelf = "readelf"
@@ -53,7 +66,7 @@
 
 gcc_toolchain("x86") {
   cc = "${compiler_prefix}gcc"
-  cxx = "$compiler_prefix}g++"
+  cxx = "${compiler_prefix}g++"
 
   readelf = "readelf"
   nm = "nm"
@@ -66,13 +79,8 @@
 }
 
 gcc_toolchain("clang_x64") {
-  if (use_clang_type_profiler) {
-    prefix = rebase_path("//third_party/llvm-allocated-type/Linux_x64/bin",
-                         root_build_dir)
-  } else {
-    prefix = rebase_path("//third_party/llvm-build/Release+Asserts/bin",
-                         root_build_dir)
-  }
+  prefix = rebase_path("//third_party/llvm-build/Release+Asserts/bin",
+                       root_build_dir)
   cc = "${compiler_prefix}$prefix/clang"
   cxx = "${compiler_prefix}$prefix/clang++"
 
@@ -102,14 +110,14 @@
 }
 
 gcc_toolchain("mipsel") {
-  cc = "mipsel-linux-gnu-gcc"
-  cxx = "mipsel-linux-gnu-g++"
-  ar = "mipsel-linux-gnu-ar"
+  cc = "${toolchain_prefix}gcc"
+  cxx = "${toolchain_prefix}g++"
+  ar = "${toolchain_prefix}ar"
   ld = cxx
-  readelf = "mipsel-linux-gnu-readelf"
-  nm = "mipsel-linux-gnu-nm"
+  readelf = "${toolchain_prefix}readelf"
+  nm = "${toolchain_prefix}nm"
 
-  toolchain_cpu = "mipsel"
+  toolchain_cpu = "${target_cpu}"
   toolchain_os = "linux"
-  is_clang = false
+  is_clang = is_clang
 }
diff --git a/docs/language/dartLangSpec.tex b/docs/language/dartLangSpec.tex
index c1d9e6b..cfd1536 100644
--- a/docs/language/dartLangSpec.tex
+++ b/docs/language/dartLangSpec.tex
@@ -2790,7 +2790,7 @@
 
 $\backslash$u\{$HEX\_DIGIT_1$ $HEX\_DIGIT_2$\}.
 \item $\backslash$u $HEX\_DIGIT_1$ $HEX\_DIGIT_2$ $HEX\_DIGIT_3$ $HEX\_DIGIT_4$, equivalent to $\backslash$u\{$HEX\_DIGIT_1$ $HEX\_DIGIT_2$ $HEX\_DIGIT_3$ $HEX\_DIGIT_4$\}.
-\item $\backslash$u\{$HEX\_DIGIT\_SEQUENCE$\} is the unicode scalar value represented by the $HEX\_DIGIT\_SEQUENCE$. It is a compile-time error if the value of the $HEX\_DIGIT\_SEQUENCE$ is not a valid unicode scalar value.
+\item $\backslash$u\{$HEX\_DIGIT\_SEQUENCE$\} is the Unicode code point represented by the $HEX\_DIGIT\_SEQUENCE$. It is a compile-time error if the value of the $HEX\_DIGIT\_SEQUENCE$ is not a valid Unicode code point.
 \item \$ indicating the beginning of an interpolated expression.
 \item Otherwise, $\backslash k$ indicates the character $k$ for any $k$ not in $\{n, r, f, b, t, v, x, u\}$.
  \end{itemize}
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index 6637ad7..9228c47 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -356,6 +356,7 @@
   "params": {
     "<b>version</b>": String
     "<b>pid</b>": int
+    "<b>sessionId</b>": <span style="color:#999999">optional</span> String
   }
 }</pre></div>
         <p>
@@ -375,6 +376,9 @@
           </dd><dt class="field"><b>pid (int)</b></dt><dd>
            
            <p>The process id of the analysis server process.</p>
+         </dd><dt class="field"><b>sessionId (<span style="color:#999999">optional</span> String)</b></dt><dd>
+           
+           <p>The session id for this session.</p>
          </dd></dl></dd><dt class="notification"><a name="notification_server.error">server.error</a> (<a href="#notification_server.error">#</a>)</dt><dd><div class="box"><pre>notification: {
   "event": "server.error"
   "params": {
diff --git a/pkg/analysis_server/lib/plugin/protocol/generated_protocol.dart b/pkg/analysis_server/lib/plugin/protocol/generated_protocol.dart
index ce67998..f3c2d98 100644
--- a/pkg/analysis_server/lib/plugin/protocol/generated_protocol.dart
+++ b/pkg/analysis_server/lib/plugin/protocol/generated_protocol.dart
@@ -267,6 +267,7 @@
  * {
  *   "version": String
  *   "pid": int
+ *   "sessionId": optional String
  * }
  *
  * Clients may not extend, implement or mix-in this class.
@@ -276,6 +277,8 @@
 
   int _pid;
 
+  String _sessionId;
+
   /**
    * The version number of the analysis server.
    */
@@ -302,9 +305,22 @@
     this._pid = value;
   }
 
-  ServerConnectedParams(String version, int pid) {
+  /**
+   * The session id for this session.
+   */
+  String get sessionId => _sessionId;
+
+  /**
+   * The session id for this session.
+   */
+  void set sessionId(String value) {
+    this._sessionId = value;
+  }
+
+  ServerConnectedParams(String version, int pid, {String sessionId}) {
     this.version = version;
     this.pid = pid;
+    this.sessionId = sessionId;
   }
 
   factory ServerConnectedParams.fromJson(JsonDecoder jsonDecoder, String jsonPath, Object json) {
@@ -324,7 +340,11 @@
       } else {
         throw jsonDecoder.missingKey(jsonPath, "pid");
       }
-      return new ServerConnectedParams(version, pid);
+      String sessionId;
+      if (json.containsKey("sessionId")) {
+        sessionId = jsonDecoder.decodeString(jsonPath + ".sessionId", json["sessionId"]);
+      }
+      return new ServerConnectedParams(version, pid, sessionId: sessionId);
     } else {
       throw jsonDecoder.mismatch(jsonPath, "server.connected params", json);
     }
@@ -339,6 +359,9 @@
     Map<String, dynamic> result = {};
     result["version"] = version;
     result["pid"] = pid;
+    if (sessionId != null) {
+      result["sessionId"] = sessionId;
+    }
     return result;
   }
 
@@ -353,7 +376,8 @@
   bool operator==(other) {
     if (other is ServerConnectedParams) {
       return version == other.version &&
-          pid == other.pid;
+          pid == other.pid &&
+          sessionId == other.sessionId;
     }
     return false;
   }
@@ -363,6 +387,7 @@
     int hash = 0;
     hash = JenkinsSmiHash.combine(hash, version.hashCode);
     hash = JenkinsSmiHash.combine(hash, pid.hashCode);
+    hash = JenkinsSmiHash.combine(hash, sessionId.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 }
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index aa20e42..d53d90b 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -376,8 +376,9 @@
     _setupIndexInvalidation();
     pubSummaryManager =
         new PubSummaryManager(resourceProvider, '${io.pid}.temp');
-    Notification notification =
-        new ServerConnectedParams(VERSION, io.pid).toNotification();
+    Notification notification = new ServerConnectedParams(VERSION, io.pid,
+            sessionId: instrumentationService.sessionId)
+        .toNotification();
     channel.sendNotification(notification);
     channel.listen(handleRequest, onDone: done, onError: error);
     handlers = serverPlugin.createDomains(this);
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index 7d567a9..66977c4 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -885,13 +885,11 @@
     if (AnalysisEngine.isAnalysisOptionsFileName(path, pathContext)) {
       var analysisContext = info.context;
       if (analysisContext is context.AnalysisContextImpl) {
-        // TODO(brianwilkerson) This doesn't correctly update the source factory
-        // if the changes necessitate it (such as by changing the setting of the
-        // strong-mode option).
         Map<String, Object> options = readOptions(info.folder);
         processOptionsForContext(info, options,
             optionsRemoved: changeType == ChangeType.REMOVE);
-        analysisContext.invalidateCachedResults();
+        analysisContext.sourceFactory = _createSourceFactory(
+            analysisContext, analysisContext.analysisOptions, info.folder);
         callbacks.applyChangesToContext(info.folder, new ChangeSet());
       }
     }
diff --git a/pkg/analysis_server/lib/src/operation/operation_analysis.dart b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
index 634ae54..dd72b49 100644
--- a/pkg/analysis_server/lib/src/operation/operation_analysis.dart
+++ b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
@@ -48,12 +48,19 @@
   for (String file in files) {
     CompilationUnitElement unitElement = server.getCompilationUnitElement(file);
     if (unitElement != null) {
-      ImplementedComputer computer =
-          new ImplementedComputer(searchEngine, unitElement);
-      await computer.compute();
-      var params = new protocol.AnalysisImplementedParams(
-          file, computer.classes, computer.members);
-      server.sendNotification(params.toNotification());
+      try {
+        ImplementedComputer computer =
+            new ImplementedComputer(searchEngine, unitElement);
+        await computer.compute();
+        var params = new protocol.AnalysisImplementedParams(
+            file, computer.classes, computer.members);
+        server.sendNotification(params.toNotification());
+      } catch (exception, stackTrace) {
+        server.sendServerErrorNotification(
+            'Failed to send analysis.implemented notification.',
+            exception,
+            stackTrace);
+      }
     }
   }
 }
diff --git a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_target.dart b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_target.dart
index 7e7ae5c..9e998e0 100644
--- a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_target.dart
+++ b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_target.dart
@@ -199,14 +199,14 @@
             Token commentToken =
                 _getContainingCommentToken(entity.beginToken, offset);
             if (commentToken != null) {
-              entity = commentToken;
               // If the preceding comment is dartdoc token, then update
               // the containing node to be the dartdoc comment.
               // Otherwise completion is not required.
               Comment docComment =
                   _getContainingDocComment(containingNode, commentToken);
               if (docComment != null) {
-                containingNode = docComment;
+                return new CompletionTarget._(
+                    compilationUnit, offset, docComment, commentToken, false);
               } else {
                 return new CompletionTarget._(compilationUnit, offset,
                     compilationUnit, commentToken, true);
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 ceadf3c..a894518 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -1808,31 +1808,44 @@
   }
 
   void _addFix_undefinedClass_useSimilar() {
+    AstNode node = this.node;
+    // Prepare the optional import prefix name.
+    String prefixName = null;
+    if (node is SimpleIdentifier && node.staticElement is PrefixElement) {
+      AstNode parent = node.parent;
+      if (parent is PrefixedIdentifier &&
+          parent.prefix == node &&
+          parent.parent is TypeName) {
+        prefixName = (node as SimpleIdentifier).name;
+        node = parent.identifier;
+      }
+    }
+    // Process if looks like a type.
     if (_mayBeTypeIdentifier(node)) {
+      // Prepare for selecting the closest element.
       String name = (node as SimpleIdentifier).name;
       _ClosestElementFinder finder = new _ClosestElementFinder(
           name,
           (Element element) => element is ClassElement,
           MAX_LEVENSHTEIN_DISTANCE);
-      // find closest element
-      {
-        // elements of this library
+      // Check elements of this library.
+      if (prefixName == null) {
         for (CompilationUnitElement unit in unitLibraryElement.units) {
           finder._updateList(unit.types);
         }
-        // elements from imports
-        for (ImportElement importElement in unitLibraryElement.imports) {
-          if (importElement.prefix == null) {
-            Map<String, Element> namespace = getImportNamespace(importElement);
-            finder._updateList(namespace.values);
-          }
+      }
+      // Check elements from imports.
+      for (ImportElement importElement in unitLibraryElement.imports) {
+        if (importElement.prefix?.name == prefixName) {
+          Map<String, Element> namespace = getImportNamespace(importElement);
+          finder._updateList(namespace.values);
         }
       }
-      // if we have close enough element, suggest to use it
+      // If we have a close enough element, suggest to use it.
       if (finder._element != null) {
         String closestName = finder._element.name;
         _addReplaceEdit(rf.rangeNode(node), closestName);
-        // add proposal
+        // Add proposal.
         if (closestName != null) {
           _addFix(DartFixKind.CHANGE_TO, [closestName]);
         }
@@ -1942,24 +1955,39 @@
   }
 
   void _addFix_undefinedFunction_useSimilar() {
+    AstNode node = this.node;
     if (node is SimpleIdentifier) {
-      String name = (node as SimpleIdentifier).name;
+      // Prepare the optional import prefix name.
+      String prefixName = null;
+      {
+        AstNode invocation = node.parent;
+        if (invocation is MethodInvocation && invocation.methodName == node) {
+          Expression target = invocation.target;
+          if (target is SimpleIdentifier &&
+              target.staticElement is PrefixElement) {
+            prefixName = target.name;
+          }
+        }
+      }
+      // Prepare for selecting the closest element.
       _ClosestElementFinder finder = new _ClosestElementFinder(
-          name,
+          node.name,
           (Element element) => element is FunctionElement,
           MAX_LEVENSHTEIN_DISTANCE);
-      // this library
-      for (CompilationUnitElement unit in unitLibraryElement.units) {
-        finder._updateList(unit.functions);
+      // Check to this library units.
+      if (prefixName == null) {
+        for (CompilationUnitElement unit in unitLibraryElement.units) {
+          finder._updateList(unit.functions);
+        }
       }
-      // imports
+      // Check unprefixed imports.
       for (ImportElement importElement in unitLibraryElement.imports) {
-        if (importElement.prefix == null) {
+        if (importElement.prefix?.name == prefixName) {
           Map<String, Element> namespace = getImportNamespace(importElement);
           finder._updateList(namespace.values);
         }
       }
-      // if we have close enough element, suggest to use it
+      // If we have a close enough element, suggest to use it.
       if (finder._element != null) {
         String closestName = finder._element.name;
         _addReplaceEdit(rf.rangeNode(node), closestName);
diff --git a/pkg/analysis_server/lib/src/services/index/index.dart b/pkg/analysis_server/lib/src/services/index/index.dart
index aa06637..dcf8ea3 100644
--- a/pkg/analysis_server/lib/src/services/index/index.dart
+++ b/pkg/analysis_server/lib/src/services/index/index.dart
@@ -4,13 +4,13 @@
 
 import 'dart:async';
 
+import 'package:analysis_server/src/services/index/index_unit.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary/index_unit.dart';
 import 'package:collection/collection.dart';
 
 /**
diff --git a/pkg/analyzer/lib/src/summary/index_unit.dart b/pkg/analysis_server/lib/src/services/index/index_unit.dart
similarity index 100%
rename from pkg/analyzer/lib/src/summary/index_unit.dart
rename to pkg/analysis_server/lib/src/services/index/index_unit.dart
diff --git a/pkg/analysis_server/lib/src/status/get_handler.dart b/pkg/analysis_server/lib/src/status/get_handler.dart
index 99f88b3..b87a33e 100644
--- a/pkg/analysis_server/lib/src/status/get_handler.dart
+++ b/pkg/analysis_server/lib/src/status/get_handler.dart
@@ -46,7 +46,8 @@
 import 'package:analyzer/src/task/driver.dart';
 import 'package:analyzer/src/task/html.dart';
 import 'package:analyzer/src/task/options.dart';
-import 'package:analyzer/src/task/options.dart' show CONFIGURED_ERROR_PROCESSORS;
+import 'package:analyzer/src/task/options.dart'
+    show CONFIGURED_ERROR_PROCESSORS;
 import 'package:analyzer/task/dart.dart';
 import 'package:analyzer/task/general.dart';
 import 'package:analyzer/task/html.dart';
@@ -1407,7 +1408,6 @@
       _writeOption(
           buffer, 'Analyze functon bodies', options.analyzeFunctionBodies);
       _writeOption(buffer, 'Cache size', options.cacheSize);
-      _writeOption(buffer, 'Enable async support', options.enableAsync);
       _writeOption(
           buffer, 'Enable generic methods', options.enableGenericMethods);
       _writeOption(
@@ -2180,8 +2180,8 @@
           }
         }
         buffer.write('<p>element count: ');
-        buffer.write(
-            counter.counts.values.fold(0, (prev, element) => prev + element));
+        buffer.write(counter.counts.values
+            .fold(0, (int prev, int element) => prev + element));
         buffer.write('</p>');
         buffer.write('<p>  (w/docs): ');
         buffer.write(counter.elementsWithDocs);
@@ -2196,8 +2196,8 @@
     buffer.write('SDK');
     buffer.write('</h3></p>');
     buffer.write('<p>element count: ');
-    buffer.write(
-        sdkCounter.counts.values.fold(0, (prev, element) => prev + element));
+    buffer.write(sdkCounter.counts.values
+        .fold(0, (int prev, int element) => prev + element));
     buffer.write('</p>');
     buffer.write('<p>  (w/docs): ');
     buffer.write(sdkCounter.elementsWithDocs);
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index 314b76f..87f62fd 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -1999,7 +1999,6 @@
     - 'test/**'
   language:
     enableGenericMethods: true
-    enableAsync: false
   errors:
     unused_local_variable: false
 linter:
@@ -2023,7 +2022,6 @@
     // * from `config.yaml`:
     expect(context.analysisOptions.strongMode, isTrue);
     expect(context.analysisOptions.enableSuperMixins, isTrue);
-    expect(context.analysisOptions.enableAsync, isFalse);
     // * from analysis options:
     expect(context.analysisOptions.enableGenericMethods, isTrue);
 
@@ -2097,7 +2095,6 @@
     - 'test/**'
   language:
     enableGenericMethods: true
-    enableAsync: false
   errors:
     unused_local_variable: false
 linter:
@@ -2132,7 +2129,6 @@
     // * from `_embedder.yaml`:
     expect(context.analysisOptions.strongMode, isTrue);
     expect(context.analysisOptions.enableSuperMixins, isTrue);
-    expect(context.analysisOptions.enableAsync, isFalse);
     // * from analysis options:
     expect(context.analysisOptions.enableGenericMethods, isTrue);
 
@@ -2211,7 +2207,6 @@
     - 'test/**'
   language:
     enableGenericMethods: true
-    enableAsync: false
   errors:
     unused_local_variable: false
 linter:
@@ -2234,7 +2229,6 @@
     // * from `_embedder.yaml`:
     expect(context.analysisOptions.strongMode, isTrue);
     expect(context.analysisOptions.enableSuperMixins, isTrue);
-    expect(context.analysisOptions.enableAsync, isFalse);
     // * from analysis options:
     expect(context.analysisOptions.enableGenericMethods, isTrue);
 
@@ -2341,6 +2335,58 @@
     expect(errorProcessors, isEmpty);
   }
 
+  test_optionsFile_update_strongMode() async {
+    var file = resourceProvider.newFile(
+        '$projPath/bin/test.dart',
+        r'''
+main() {
+  var paths = <int>[];
+  var names = <String>[];
+  paths.addAll(names.map((s) => s.length));
+}
+''');
+    resourceProvider.newFile(
+        '$projPath/$optionsFileName',
+        r'''
+analyzer:
+  strong-mode: false
+''');
+    // Create the context.
+    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
+    await pumpEventQueue();
+
+    AnalysisContext context = manager.getContextFor(projPath);
+    Source testSource = context.getSourcesWithFullName(file.path).single;
+
+    // Not strong mode - both in the context and the SDK context.
+    {
+      AnalysisContext sdkContext = context.sourceFactory.dartSdk.context;
+      expect(context.analysisOptions.strongMode, isFalse);
+      expect(sdkContext.analysisOptions.strongMode, isFalse);
+      expect(context.computeErrors(testSource), isEmpty);
+    }
+
+    // Update the options file - turn on 'strong-mode'.
+    resourceProvider.updateFile(
+        '$projPath/$optionsFileName',
+        r'''
+analyzer:
+  strong-mode: true
+''');
+    await pumpEventQueue();
+
+    // Strong mode - both in the context and the SDK context.
+    {
+      AnalysisContext context = manager.getContextFor(projPath);
+      AnalysisContext sdkContext = context.sourceFactory.dartSdk.context;
+      expect(context.analysisOptions.strongMode, isTrue);
+      expect(sdkContext.analysisOptions.strongMode, isTrue);
+      // The code is strong-mode clean.
+      // Verify that TypeSystem was reset.
+      expect(context.computeErrors(testSource), isEmpty);
+    }
+  }
+
   test_path_filter_analysis_option() async {
     // Create files.
     String libPath = newFolder([projPath, ContextManagerTest.LIB_NAME]);
diff --git a/pkg/analysis_server/test/domain_analysis_test.dart b/pkg/analysis_server/test/domain_analysis_test.dart
index 35e9537..485227d 100644
--- a/pkg/analysis_server/test/domain_analysis_test.dart
+++ b/pkg/analysis_server/test/domain_analysis_test.dart
@@ -9,14 +9,11 @@
 import 'package:analysis_server/plugin/protocol/protocol.dart';
 import 'package:analysis_server/src/analysis_server.dart';
 import 'package:analysis_server/src/constants.dart';
-import 'package:analysis_server/src/context_manager.dart';
 import 'package:analysis_server/src/domain_analysis.dart';
 import 'package:analysis_server/src/plugin/server_plugin.dart';
-import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
 import 'package:analyzer/src/generated/sdk.dart';
-import 'package:path/path.dart';
 import 'package:plugin/manager.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 import 'package:unittest/unittest.dart';
diff --git a/pkg/analysis_server/test/integration/analysis/error_test.dart b/pkg/analysis_server/test/integration/analysis/error_test.dart
index cd490fa..b01f1d8 100644
--- a/pkg/analysis_server/test/integration/analysis/error_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/error_test.dart
@@ -45,7 +45,7 @@
   void foo() {}
 }
 abstract class B {
-  void foo();
+  void foo() {}
 }
 abstract class C extends B {
   void bar() {
@@ -79,7 +79,7 @@
   void foo() {}
 }
 abstract class B {
-  void foo();
+  void foo() {}
 }
 abstract class C extends B {
   void bar() {
diff --git a/pkg/analysis_server/test/integration/integration_test_methods.dart b/pkg/analysis_server/test/integration/integration_test_methods.dart
index 580499d..9e4a5ee 100644
--- a/pkg/analysis_server/test/integration/integration_test_methods.dart
+++ b/pkg/analysis_server/test/integration/integration_test_methods.dart
@@ -92,6 +92,10 @@
    * pid (int)
    *
    *   The process id of the analysis server process.
+   *
+   * sessionId (optional String)
+   *
+   *   The session id for this session.
    */
   Stream<ServerConnectedParams> onServerConnected;
 
diff --git a/pkg/analysis_server/test/integration/integration_tests.dart b/pkg/analysis_server/test/integration/integration_tests.dart
index 1893c18..f6748ed 100644
--- a/pkg/analysis_server/test/integration/integration_tests.dart
+++ b/pkg/analysis_server/test/integration/integration_tests.dart
@@ -636,6 +636,9 @@
     if (Platform.packageRoot != null) {
       arguments.add('--package-root=${Platform.packageRoot}');
     }
+    if (Platform.packageConfig != null) {
+      arguments.add('--packages=${Platform.packageConfig}');
+    }
     if (checked) {
       arguments.add('--checked');
     }
diff --git a/pkg/analysis_server/test/integration/protocol_matchers.dart b/pkg/analysis_server/test/integration/protocol_matchers.dart
index 5c8e84a..fef9ef3 100644
--- a/pkg/analysis_server/test/integration/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/protocol_matchers.dart
@@ -66,12 +66,15 @@
  * {
  *   "version": String
  *   "pid": int
+ *   "sessionId": optional String
  * }
  */
 final Matcher isServerConnectedParams = new LazyMatcher(() => new MatchesJsonObject(
   "server.connected params", {
     "version": isString,
     "pid": isInt
+  }, optionalFields: {
+    "sessionId": isString
   }));
 
 /**
diff --git a/pkg/analysis_server/test/mock_sdk.dart b/pkg/analysis_server/test/mock_sdk.dart
index 0d39a19..94d1208 100644
--- a/pkg/analysis_server/test/mock_sdk.dart
+++ b/pkg/analysis_server/test/mock_sdk.dart
@@ -126,10 +126,12 @@
 abstract class Iterable<E> {
   Iterator<E> get iterator;
   bool get isEmpty;
+  Iterable/*<R>*/ map/*<R>*/(/*=R*/ f(E e));
 }
 
 abstract class List<E> implements Iterable<E> {
   void add(E value);
+  void addAll(Iterable<E> iterable) {}
   E operator [](int index);
   void operator []=(int index, E value);
   Iterator<E> get iterator => null;
diff --git a/pkg/analysis_server/test/services/correction/fix_test.dart b/pkg/analysis_server/test/services/correction/fix_test.dart
index 60897d9..9bc4a4f 100644
--- a/pkg/analysis_server/test/services/correction/fix_test.dart
+++ b/pkg/analysis_server/test/services/correction/fix_test.dart
@@ -3971,6 +3971,23 @@
 ''');
   }
 
+  test_undefinedClass_useSimilar_BAD_prefixed() async {
+    resolveTestUnit('''
+import 'dart:async' as c;
+main() {
+  c.Fture v = null;
+}
+''');
+    await assertHasFix(
+        DartFixKind.CHANGE_TO,
+        '''
+import 'dart:async' as c;
+main() {
+  c.Future v = null;
+}
+''');
+  }
+
   test_undefinedClass_useSimilar_fromImport() async {
     resolveTestUnit('''
 main() {
@@ -4370,6 +4387,33 @@
 ''');
   }
 
+  test_undefinedFunction_useSimilar_prefixed_fromImport() async {
+    resolveTestUnit('''
+import 'dart:core' as c;
+main() {
+  c.prnt(42);
+}
+''');
+    await assertHasFix(
+        DartFixKind.CHANGE_TO,
+        '''
+import 'dart:core' as c;
+main() {
+  c.print(42);
+}
+''');
+  }
+
+  test_undefinedFunction_useSimilar_prefixed_ignoreLocal() async {
+    resolveTestUnit('''
+import 'dart:async' as c;
+main() {
+  c.main();
+}
+''');
+    await assertNoFix(DartFixKind.CHANGE_TO);
+  }
+
   test_undefinedFunction_useSimilar_thisLibrary() async {
     resolveTestUnit('''
 myFunction() {}
diff --git a/pkg/analyzer/test/src/summary/index_unit_test.dart b/pkg/analysis_server/test/services/index/index_unit_test.dart
similarity index 99%
rename from pkg/analyzer/test/src/summary/index_unit_test.dart
rename to pkg/analysis_server/test/services/index/index_unit_test.dart
index 06f6efb..87388fd 100644
--- a/pkg/analyzer/test/src/summary/index_unit_test.dart
+++ b/pkg/analysis_server/test/services/index/index_unit_test.dart
@@ -4,15 +4,15 @@
 
 import 'dart:convert';
 
+import 'package:analysis_server/src/services/index/index_unit.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary/index_unit.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 import 'package:unittest/unittest.dart';
 
-import '../abstract_single_unit.dart';
+import '../../abstract_single_unit.dart';
 
 main() {
   groupSep = ' | ';
diff --git a/pkg/analysis_server/test/services/index/test_all.dart b/pkg/analysis_server/test/services/index/test_all.dart
index 27a2cd2..5c45ec5 100644
--- a/pkg/analysis_server/test/services/index/test_all.dart
+++ b/pkg/analysis_server/test/services/index/test_all.dart
@@ -6,6 +6,7 @@
 
 import '../../utils.dart';
 import 'index_test.dart' as index_test;
+import 'index_unit_test.dart' as index_unit_test;
 
 /**
  * Utility for manually running all tests.
@@ -14,5 +15,6 @@
   initializeTestEnvironment();
   group('index', () {
     index_test.main();
+    index_unit_test.main();
   });
 }
diff --git a/pkg/analysis_server/tool/spec/generate_files b/pkg/analysis_server/tool/spec/generate_files
index 85092ea..ee9e970 100755
--- a/pkg/analysis_server/tool/spec/generate_files
+++ b/pkg/analysis_server/tool/spec/generate_files
@@ -32,27 +32,31 @@
 
 ROOT_DIR="$(cd "${SCRIPT_DIR}/../../../.." ; pwd -P)"
 
-BIN_DIR="${ROOT_DIR}/sdk/bin"
-
-if [ -z "$DART_CONFIGURATION" ];
+if [[ $1 == '--arch' && $2 == 'x64' ]];
+then
+  DART_CONFIGURATION="ReleaseX64"
+elif [ -z "$DART_CONFIGURATION" ];
 then
   DART_CONFIGURATION="ReleaseIA32"
 fi
 
 if [[ `uname` == 'Darwin' ]];
 then
-  BUILD_DIR="${ROOT_DIR}/xcodebuild/$DART_CONFIGURATION"
-else
-  BUILD_DIR="${ROOT_DIR}/out/$DART_CONFIGURATION"
+  if [[ $GYP_GENERATORS == 'ninja' ]];
+  then
+    BUILD_DIR="${ROOT_DIR}/out/$DART_CONFIGURATION"
+  else
+    BUILD_DIR="${ROOT_DIR}/xcodebuild/$DART_CONFIGURATION"
+  fi
 fi
 
-PKG_DIR="${BUILD_DIR}/packages"
+PKG_FILE="${ROOT_DIR}/pkg/analysis_server/.packages"
 
-DART="${BIN_DIR}/dart"
+DART="${BUILD_DIR}/dart-sdk/bin/dart"
 
 declare -a VM_OPTIONS
 VM_OPTIONS+=("--checked")
-VM_OPTIONS+=("--package-root=${PKG_DIR}")
+VM_OPTIONS+=("--packages=${PKG_FILE}")
 
 cd "${SCRIPT_DIR}"
 "${DART}" "${VM_OPTIONS[@]}" "generate_all.dart"
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index cadad70..5290921 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -243,6 +243,10 @@
            <ref>int</ref>
            <p>The process id of the analysis server process.</p>
          </field>
+         <field name="sessionId" optional="true">
+           <ref>String</ref>
+           <p>The session id for this session.</p>
+         </field>
         </params>
       </notification>
       <notification event="error">
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index da18224..7ec7be4 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -36,6 +36,7 @@
  */
 library analyzer.dart.ast.ast;
 
+import 'package:analyzer/dart/ast/syntactic_entity.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
@@ -510,7 +511,7 @@
  *
  * Clients may not extend, implement or mix-in this class.
  */
-abstract class AstNode {
+abstract class AstNode implements SyntacticEntity {
   /**
    * An empty list of AST nodes.
    */
@@ -536,7 +537,7 @@
    * (either AST nodes or tokens) that make up the contents of this node,
    * including doc comments but excluding other comments.
    */
-  Iterable /* AstNode | Token */ get childEntities;
+  Iterable<SyntacticEntity> get childEntities;
 
   /**
    * Return the offset of the character immediately following the last character
@@ -546,6 +547,7 @@
    * equivalent to the node's offset (because the length is zero (0) by
    * definition).
    */
+  @override
   int get end;
 
   /**
@@ -560,15 +562,10 @@
    */
   bool get isSynthetic;
 
-  /**
-   * Return the number of characters in the node's source range.
-   */
+  @override
   int get length;
 
-  /**
-   * Return the offset from the beginning of the file to the first character in
-   * the node's source range.
-   */
+  @override
   int get offset;
 
   /**
diff --git a/pkg/analyzer/lib/dart/ast/syntactic_entity.dart b/pkg/analyzer/lib/dart/ast/syntactic_entity.dart
new file mode 100644
index 0000000..bc8271a
--- /dev/null
+++ b/pkg/analyzer/lib/dart/ast/syntactic_entity.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library analyzer.dart.ast.syntactic_entity;
+
+/**
+ * Interface representing a syntactic entity (either a token or an AST node)
+ * which has a location and extent in the source file.
+ */
+abstract class SyntacticEntity {
+  /**
+   * Return the offset from the beginning of the file to the character after the
+   * last character of the syntactic entity.
+   */
+  int get end;
+
+  /**
+   * Return the number of characters in the syntactic entity's source range.
+   */
+  int get length;
+
+  /**
+   * Return the offset from the beginning of the file to the first character in
+   * the syntactic entity.
+   */
+  int get offset;
+}
diff --git a/pkg/analyzer/lib/dart/ast/token.dart b/pkg/analyzer/lib/dart/ast/token.dart
index 687111a..fce7f24 100644
--- a/pkg/analyzer/lib/dart/ast/token.dart
+++ b/pkg/analyzer/lib/dart/ast/token.dart
@@ -10,6 +10,7 @@
 
 import 'dart:collection';
 
+import 'package:analyzer/dart/ast/syntactic_entity.dart';
 import 'package:analyzer/src/dart/ast/token.dart' show SimpleToken, TokenClass;
 
 /**
@@ -219,16 +220,13 @@
  *
  * Clients may not extend, implement or mix-in this class.
  */
-abstract class Token {
+abstract class Token implements SyntacticEntity {
   /**
    * Initialize a newly created token to have the given [type] and [offset].
    */
   factory Token(TokenType type, int offset) = SimpleToken;
 
-  /**
-   * Return the offset from the beginning of the file to the character after the
-   * last character of the token.
-   */
+  @override
   int get end;
 
   /**
@@ -254,9 +252,7 @@
    */
   Keyword get keyword;
 
-  /**
-   * Return the number of characters in the node's source range.
-   */
+  @override
   int get length;
 
   /**
@@ -269,10 +265,7 @@
    */
   Token get next;
 
-  /**
-   * Return the offset from the beginning of the file to the first character in
-   * the token.
-   */
+  @override
   int get offset;
 
   /**
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index df7db66..cee76da 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -40,7 +40,6 @@
 import 'package:analyzer/dart/constant/value.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
-import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -864,12 +863,11 @@
 }
 
 /**
- * The enumeration `ElementKind` defines the various kinds of elements in the
- * element model.
+ * The kind of elements in the element model.
  *
  * Clients may not extend, implement or mix-in this class.
  */
-class ElementKind extends Enum<ElementKind> {
+class ElementKind implements Comparable<ElementKind> {
   static const ElementKind CLASS = const ElementKind('CLASS', 0, "class");
 
   static const ElementKind COMPILATION_UNIT =
@@ -954,6 +952,16 @@
   ];
 
   /**
+   * The name of this element kind.
+   */
+  final String name;
+
+  /**
+   * The ordinal value of the element kind.
+   */
+  final int ordinal;
+
+  /**
    * The name displayed in the UI for this kind of element.
    */
   final String displayName;
@@ -961,8 +969,16 @@
   /**
    * Initialize a newly created element kind to have the given [displayName].
    */
-  const ElementKind(String name, int ordinal, this.displayName)
-      : super(name, ordinal);
+  const ElementKind(this.name, this.ordinal, this.displayName);
+
+  @override
+  int get hashCode => ordinal;
+
+  @override
+  int compareTo(ElementKind other) => ordinal - other.ordinal;
+
+  @override
+  String toString() => name;
 
   /**
    * Return the kind of the given [element], or [ERROR] if the element is
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 622fe9e..53a6565 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -892,7 +892,7 @@
 /**
  * The properties that can be associated with an [AnalysisError].
  */
-class ErrorProperty<V> extends Enum<ErrorProperty> {
+class ErrorProperty<V> implements Comparable<ErrorProperty> {
   /**
    * A property whose value is a list of [FieldElement]s that are final, but
    * not initialized by a constructor.
@@ -921,13 +921,32 @@
     UNIMPLEMENTED_METHODS
   ];
 
-  const ErrorProperty(String name, int ordinal) : super(name, ordinal);
+  /**
+   * The name of this property.
+   */
+  final String name;
+
+  /**
+   * The ordinal value of the property.
+   */
+  final int ordinal;
+
+  const ErrorProperty(this.name, this.ordinal);
+
+  @override
+  int get hashCode => ordinal;
+
+  @override
+  int compareTo(ErrorProperty other) => ordinal - other.ordinal;
+
+  @override
+  String toString() => name;
 }
 
 /**
  * The severity of an [ErrorCode].
  */
-class ErrorSeverity extends Enum<ErrorSeverity> {
+class ErrorSeverity implements Comparable<ErrorSeverity> {
   /**
    * The severity representing a non-error. This is never used for any error
    * code, but is useful for clients.
@@ -955,6 +974,16 @@
   static const List<ErrorSeverity> values = const [NONE, INFO, WARNING, ERROR];
 
   /**
+   * The name of this error code.
+   */
+  final String name;
+
+  /**
+   * The ordinal value of the error code.
+   */
+  final int ordinal;
+
+  /**
    * The name of the severity used when producing machine output.
    */
   final String machineCode;
@@ -966,26 +995,30 @@
 
   /**
    * Initialize a newly created severity with the given names.
-   *
-   * Parameters:
-   * 0: the name of the severity used when producing machine output
-   * 1: the name of the severity used when producing readable output
    */
   const ErrorSeverity(
-      String name, int ordinal, this.machineCode, this.displayName)
-      : super(name, ordinal);
+      this.name, this.ordinal, this.machineCode, this.displayName);
+
+  @override
+  int get hashCode => ordinal;
+
+  @override
+  int compareTo(ErrorSeverity other) => ordinal - other.ordinal;
 
   /**
    * Return the severity constant that represents the greatest severity.
    */
   ErrorSeverity max(ErrorSeverity severity) =>
       this.ordinal >= severity.ordinal ? this : severity;
+
+  @override
+  String toString() => name;
 }
 
 /**
  * The type of an [ErrorCode].
  */
-class ErrorType extends Enum<ErrorType> {
+class ErrorType implements Comparable<ErrorType> {
   /**
    * Task (todo) comments in user code.
    */
@@ -1052,6 +1085,16 @@
   ];
 
   /**
+   * The name of this error type.
+   */
+  final String name;
+
+  /**
+   * The ordinal value of the error type.
+   */
+  final int ordinal;
+
+  /**
    * The severity of this type of error.
    */
   final ErrorSeverity severity;
@@ -1060,8 +1103,16 @@
    * Initialize a newly created error type to have the given [name] and
    * [severity].
    */
-  const ErrorType(String name, int ordinal, this.severity)
-      : super(name, ordinal);
+  const ErrorType(this.name, this.ordinal, this.severity);
 
   String get displayName => name.toLowerCase().replaceAll('_', ' ');
+
+  @override
+  int get hashCode => ordinal;
+
+  @override
+  int compareTo(ErrorType other) => ordinal - other.ordinal;
+
+  @override
+  String toString() => name;
 }
diff --git a/pkg/analyzer/lib/instrumentation/file_instrumentation.dart b/pkg/analyzer/lib/instrumentation/file_instrumentation.dart
index fe36a9e..d4088f8 100644
--- a/pkg/analyzer/lib/instrumentation/file_instrumentation.dart
+++ b/pkg/analyzer/lib/instrumentation/file_instrumentation.dart
@@ -21,6 +21,9 @@
   }
 
   @override
+  String get sessionId => '';
+
+  @override
   void log(String message) {
     _sink.writeln(message);
   }
diff --git a/pkg/analyzer/lib/instrumentation/instrumentation.dart b/pkg/analyzer/lib/instrumentation/instrumentation.dart
index eaf95ba..abc2799 100644
--- a/pkg/analyzer/lib/instrumentation/instrumentation.dart
+++ b/pkg/analyzer/lib/instrumentation/instrumentation.dart
@@ -23,6 +23,11 @@
  */
 abstract class InstrumentationServer {
   /**
+   * Return the identifier used to identify the current session.
+   */
+  String get sessionId;
+
+  /**
    * Pass the given [message] to the instrumentation server so that it will be
    * logged with other messages.
    *
@@ -96,6 +101,11 @@
   bool get isActive => _instrumentationServer != null;
 
   /**
+   * Return the identifier used to identify the current session.
+   */
+  String get sessionId => _instrumentationServer?.sessionId ?? '';
+
+  /**
    * The current time, expressed as a decimal encoded number of milliseconds.
    */
   String get _timestamp => new DateTime.now().millisecondsSinceEpoch.toString();
@@ -357,6 +367,9 @@
   MulticastInstrumentationServer(this._servers);
 
   @override
+  String get sessionId => _servers[0].sessionId;
+
+  @override
   void log(String message) {
     for (InstrumentationServer server in _servers) {
       server.log(message);
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index 7e8b4d3..f56c12c 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -9,7 +9,6 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
@@ -19,14 +18,12 @@
 import 'package:analyzer/src/context/builder.dart' show EmbedderYamlLocator;
 import 'package:analyzer/src/context/cache.dart';
 import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/incremental_resolver.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
 import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/testing/ast_factory.dart';
 import 'package:analyzer/src/generated/utilities_collection.dart';
 import 'package:analyzer/src/task/dart.dart';
 import 'package:analyzer/src/task/dart_work_manager.dart';
@@ -308,7 +305,6 @@
         this._options.enableStrictCallChecks !=
             options.enableStrictCallChecks ||
         this._options.enableGenericMethods != options.enableGenericMethods ||
-        this._options.enableAsync != options.enableAsync ||
         this._options.enableSuperMixins != options.enableSuperMixins;
     int cacheSize = options.cacheSize;
     if (this._options.cacheSize != cacheSize) {
@@ -323,7 +319,6 @@
     this._options.enableAssertInitializer = options.enableAssertInitializer;
     this._options.enableAssertMessage = options.enableAssertMessage;
     this._options.enableStrictCallChecks = options.enableStrictCallChecks;
-    this._options.enableAsync = options.enableAsync;
     this._options.enableInitializingFormalAccess =
         options.enableInitializingFormalAccess;
     this._options.enableSuperMixins = options.enableSuperMixins;
@@ -334,6 +329,9 @@
     this._options.incrementalValidation = options.incrementalValidation;
     this._options.lint = options.lint;
     this._options.preserveComments = options.preserveComments;
+    if (this._options.strongMode != options.strongMode) {
+      _typeSystem = null;
+    }
     this._options.strongMode = options.strongMode;
     this._options.trackCacheDependencies = options.trackCacheDependencies;
     this._options.finerGrainedInvalidation = options.finerGrainedInvalidation;
@@ -545,22 +543,14 @@
       throw new AnalysisException("Could not create an element for dart:core");
     }
 
-    LibraryElement asyncElement;
-    if (analysisOptions.enableAsync) {
-      Source asyncSource = sourceFactory.forUri(DartSdk.DART_ASYNC);
-      if (asyncSource == null) {
-        throw new AnalysisException("Could not create a source for dart:async");
-      }
-      asyncElement = computeLibraryElement(asyncSource);
-      if (asyncElement == null) {
-        throw new AnalysisException(
-            "Could not create an element for dart:async");
-      }
-    } else {
-      Source asyncSource = sourceFactory.forUri(DartSdk.DART_ASYNC);
-      asyncElement = createMockAsyncLib(coreElement, asyncSource);
+    Source asyncSource = sourceFactory.forUri(DartSdk.DART_ASYNC);
+    if (asyncSource == null) {
+      throw new AnalysisException("Could not create a source for dart:async");
     }
-
+    LibraryElement asyncElement = computeLibraryElement(asyncSource);
+    if (asyncElement == null) {
+      throw new AnalysisException("Could not create an element for dart:async");
+    }
     _typeProvider = new TypeProviderImpl(coreElement, asyncElement);
     return _typeProvider;
   }
@@ -773,55 +763,6 @@
     return cache;
   }
 
-  /**
-   * Create a minimalistic mock dart:async library
-   * to stand in for a real one if one does not exist
-   * facilitating creation a type provider without dart:async.
-   */
-  LibraryElement createMockAsyncLib(
-      LibraryElement coreLibrary, Source asyncSource) {
-    InterfaceType objType = coreLibrary.getType('Object').type;
-
-    ClassElement _classElement(String typeName, [List<String> parameterNames]) {
-      ClassElementImpl element =
-          new ClassElementImpl.forNode(AstFactory.identifier3(typeName));
-      element.supertype = objType;
-      if (parameterNames != null) {
-        int count = parameterNames.length;
-        if (count > 0) {
-          List<TypeParameterElementImpl> typeParameters =
-              new List<TypeParameterElementImpl>(count);
-          List<TypeParameterTypeImpl> typeArguments =
-              new List<TypeParameterTypeImpl>(count);
-          for (int i = 0; i < count; i++) {
-            TypeParameterElementImpl typeParameter =
-                new TypeParameterElementImpl.forNode(
-                    AstFactory.identifier3(parameterNames[i]));
-            typeParameters[i] = typeParameter;
-            typeArguments[i] = new TypeParameterTypeImpl(typeParameter);
-            typeParameter.type = typeArguments[i];
-          }
-          element.typeParameters = typeParameters;
-        }
-      }
-      return element;
-    }
-
-    InterfaceType futureType = _classElement('Future', ['T']).type;
-    InterfaceType streamType = _classElement('Stream', ['T']).type;
-    CompilationUnitElementImpl asyncUnit =
-        new CompilationUnitElementImpl("mock_async.dart");
-    asyncUnit.types = <ClassElement>[futureType.element, streamType.element];
-    LibraryElementImpl mockLib = new LibraryElementImpl.forNode(
-        this, AstFactory.libraryIdentifier2(["dart.async"]));
-    asyncUnit.librarySource = asyncSource;
-    asyncUnit.source = asyncSource;
-    mockLib.definingCompilationUnit = asyncUnit;
-    mockLib.publicNamespace =
-        new NamespaceBuilder().createPublicNamespaceForLibrary(mockLib);
-    return mockLib;
-  }
-
   @override
   void dispose() {
     _disposed = true;
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index eca142a..4df003d 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -7,6 +7,7 @@
 import 'dart:collection';
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/syntactic_entity.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
@@ -51,7 +52,8 @@
   Token get beginToken => _strings.beginToken;
 
   @override
-  Iterable get childEntities => new ChildEntities()..addAll(_strings);
+  Iterable<SyntacticEntity> get childEntities =>
+      new ChildEntities()..addAll(_strings);
 
   @override
   Token get endToken => _strings.endToken;
@@ -262,7 +264,7 @@
   Token get beginToken => atSign;
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(atSign)
     ..add(_name)
     ..add(period)
@@ -388,7 +390,7 @@
 
   @override
   // TODO(paulberry): Add commas.
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(leftParenthesis)
     ..addAll(_arguments)
     ..add(rightParenthesis);
@@ -520,7 +522,7 @@
   Token get beginToken => _expression.beginToken;
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       new ChildEntities()..add(_expression)..add(asOperator)..add(_type);
 
   @override
@@ -623,7 +625,7 @@
   Token get beginToken => assertKeyword;
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(assertKeyword)
     ..add(leftParenthesis)
     ..add(_condition)
@@ -740,7 +742,7 @@
   }
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(_leftHandSide)
     ..add(operator)
     ..add(_rightHandSide);
@@ -992,7 +994,7 @@
   }
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       new ChildEntities()..add(awaitKeyword)..add(_expression);
 
   @override
@@ -1081,7 +1083,7 @@
   }
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       new ChildEntities()..add(_leftOperand)..add(operator)..add(_rightOperand);
 
   @override
@@ -1205,7 +1207,7 @@
   }
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       new ChildEntities()..add(keyword)..add(star)..add(_block);
 
   @override
@@ -1265,7 +1267,7 @@
   Token get beginToken => leftBracket;
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(leftBracket)
     ..addAll(_statements)
     ..add(rightBracket);
@@ -1314,7 +1316,8 @@
   Token get beginToken => literal;
 
   @override
-  Iterable get childEntities => new ChildEntities()..add(literal);
+  Iterable<SyntacticEntity> get childEntities =>
+      new ChildEntities()..add(literal);
 
   @override
   Token get endToken => literal;
@@ -1381,7 +1384,7 @@
   Token get beginToken => breakKeyword;
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       new ChildEntities()..add(breakKeyword)..add(_label)..add(semicolon);
 
   @override
@@ -1450,7 +1453,7 @@
   NodeList<Expression> get cascadeSections => _cascadeSections;
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(_target)
     ..addAll(_cascadeSections);
 
@@ -1585,7 +1588,7 @@
   }
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(onKeyword)
     ..add(_exceptionType)
     ..add(catchKeyword)
@@ -1639,21 +1642,22 @@
 /**
  * Helper class to allow iteration of child entities of an AST node.
  */
-class ChildEntities extends Object with IterableMixin implements Iterable {
+class ChildEntities extends Object
+    with IterableMixin<SyntacticEntity>
+    implements Iterable<SyntacticEntity> {
   /**
    * The list of child entities to be iterated over.
    */
-  List _entities = [];
+  List<SyntacticEntity> _entities = [];
 
   @override
-  Iterator get iterator => _entities.iterator;
+  Iterator<SyntacticEntity> get iterator => _entities.iterator;
 
   /**
    * Add an AST node or token as the next child entity, if it is not null.
    */
-  void add(entity) {
+  void add(SyntacticEntity entity) {
     if (entity != null) {
-      assert(entity is Token || entity is AstNode);
       _entities.add(entity);
     }
   }
@@ -1661,7 +1665,7 @@
   /**
    * Add the given items as the next child entities, if [items] is not null.
    */
-  void addAll(Iterable items) {
+  void addAll(Iterable<SyntacticEntity> items) {
     if (items != null) {
       _entities.addAll(items);
     }
@@ -1770,7 +1774,7 @@
   }
 
   @override
-  Iterable get childEntities => super._childEntities
+  Iterable<SyntacticEntity> get childEntities => super._childEntities
     ..add(abstractKeyword)
     ..add(classKeyword)
     ..add(_name)
@@ -2003,7 +2007,7 @@
   }
 
   @override
-  Iterable get childEntities => super._childEntities
+  Iterable<SyntacticEntity> get childEntities => super._childEntities
     ..add(typedefKeyword)
     ..add(_name)
     ..add(_typeParameters)
@@ -2150,7 +2154,8 @@
   Token get beginToken => tokens[0];
 
   @override
-  Iterable get childEntities => new ChildEntities()..addAll(tokens);
+  Iterable<SyntacticEntity> get childEntities =>
+      new ChildEntities()..addAll(tokens);
 
   @override
   Token get endToken => tokens[tokens.length - 1];
@@ -2235,7 +2240,7 @@
   Token get beginToken => _identifier.beginToken;
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       new ChildEntities()..add(newKeyword)..add(_identifier);
 
   @override
@@ -2378,7 +2383,7 @@
   }
 
   @override
-  Iterable get childEntities {
+  Iterable<SyntacticEntity> get childEntities {
     ChildEntities result = new ChildEntities()..add(_scriptTag);
     if (_directivesAreBeforeDeclarations) {
       result..addAll(_directives)..addAll(_declarations);
@@ -2531,7 +2536,7 @@
   Token get beginToken => _condition.beginToken;
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(_condition)
     ..add(question)
     ..add(_thenExpression)
@@ -2631,7 +2636,7 @@
   Token get beginToken => ifKeyword;
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(ifKeyword)
     ..add(leftParenthesis)
     ..add(_name)
@@ -2838,7 +2843,7 @@
   }
 
   @override
-  Iterable get childEntities => super._childEntities
+  Iterable<SyntacticEntity> get childEntities => super._childEntities
     ..add(externalKeyword)
     ..add(constKeyword)
     ..add(factoryKeyword)
@@ -2980,7 +2985,7 @@
   }
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(thisKeyword)
     ..add(period)
     ..add(_fieldName)
@@ -3075,7 +3080,7 @@
   Token get beginToken => _type.beginToken;
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       new ChildEntities()..add(_type)..add(period)..add(_name);
 
   @override
@@ -3160,7 +3165,7 @@
   Token get beginToken => continueKeyword;
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       new ChildEntities()..add(continueKeyword)..add(_label)..add(semicolon);
 
   @override
@@ -3239,7 +3244,7 @@
   }
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       super._childEntities..add(keyword)..add(_type)..add(_identifier);
 
   @override
@@ -3366,7 +3371,7 @@
   Token get beginToken => _parameter.beginToken;
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       new ChildEntities()..add(_parameter)..add(separator)..add(_defaultValue);
 
   @override
@@ -3525,7 +3530,7 @@
   }
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(doKeyword)
     ..add(_body)
     ..add(whileKeyword)
@@ -3580,7 +3585,8 @@
 
   @override
   // TODO(paulberry): add "." tokens.
-  Iterable get childEntities => new ChildEntities()..addAll(_components);
+  Iterable<SyntacticEntity> get childEntities =>
+      new ChildEntities()..addAll(_components);
 
   @override
   NodeList<SimpleIdentifier> get components => _components;
@@ -3630,7 +3636,8 @@
   Token get beginToken => literal;
 
   @override
-  Iterable get childEntities => new ChildEntities()..add(literal);
+  Iterable<SyntacticEntity> get childEntities =>
+      new ChildEntities()..add(literal);
 
   @override
   Token get endToken => literal;
@@ -3670,7 +3677,8 @@
   Token get beginToken => semicolon;
 
   @override
-  Iterable get childEntities => new ChildEntities()..add(semicolon);
+  Iterable<SyntacticEntity> get childEntities =>
+      new ChildEntities()..add(semicolon);
 
   @override
   Token get endToken => semicolon;
@@ -3706,7 +3714,8 @@
   Token get beginToken => semicolon;
 
   @override
-  Iterable get childEntities => new ChildEntities()..add(semicolon);
+  Iterable<SyntacticEntity> get childEntities =>
+      new ChildEntities()..add(semicolon);
 
   @override
   Token get endToken => semicolon;
@@ -3744,7 +3753,8 @@
   }
 
   @override
-  Iterable get childEntities => super._childEntities..add(_name);
+  Iterable<SyntacticEntity> get childEntities =>
+      super._childEntities..add(_name);
 
   @override
   FieldElement get element => _name?.staticElement as FieldElement;
@@ -3825,7 +3835,7 @@
 
   @override
   // TODO(brianwilkerson) Add commas?
-  Iterable get childEntities => super._childEntities
+  Iterable<SyntacticEntity> get childEntities => super._childEntities
     ..add(enumKeyword)
     ..add(_name)
     ..add(leftBracket)
@@ -3893,7 +3903,7 @@
             combinators, semicolon);
 
   @override
-  Iterable get childEntities => super._childEntities
+  Iterable<SyntacticEntity> get childEntities => super._childEntities
     ..add(_uri)
     ..addAll(combinators)
     ..add(semicolon);
@@ -3972,7 +3982,7 @@
   }
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(keyword)
     ..add(functionDefinition)
     ..add(_expression)
@@ -4145,7 +4155,7 @@
   Token get beginToken => _expression.beginToken;
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       new ChildEntities()..add(_expression)..add(semicolon);
 
   @override
@@ -4206,7 +4216,7 @@
   Token get beginToken => extendsKeyword;
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       new ChildEntities()..add(extendsKeyword)..add(_superclass);
 
   @override
@@ -4268,7 +4278,7 @@
   }
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       super._childEntities..add(staticKeyword)..add(_fieldList)..add(semicolon);
 
   @override
@@ -4389,7 +4399,7 @@
   }
 
   @override
-  Iterable get childEntities => super._childEntities
+  Iterable<SyntacticEntity> get childEntities => super._childEntities
     ..add(keyword)
     ..add(_type)
     ..add(thisKeyword)
@@ -4559,7 +4569,7 @@
   }
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(awaitKeyword)
     ..add(forKeyword)
     ..add(leftParenthesis)
@@ -4708,7 +4718,7 @@
   Token get beginToken => leftParenthesis;
 
   @override
-  Iterable get childEntities {
+  Iterable<SyntacticEntity> get childEntities {
     // TODO(paulberry): include commas.
     ChildEntities result = new ChildEntities()..add(leftParenthesis);
     bool leftDelimiterNeeded = leftDelimiter != null;
@@ -4860,7 +4870,7 @@
   }
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(forKeyword)
     ..add(leftParenthesis)
     ..add(_variableList)
@@ -5039,7 +5049,7 @@
   }
 
   @override
-  Iterable get childEntities => super._childEntities
+  Iterable<SyntacticEntity> get childEntities => super._childEntities
     ..add(externalKeyword)
     ..add(_returnType)
     ..add(propertyKeyword)
@@ -5122,7 +5132,8 @@
   Token get beginToken => _functionDeclaration.beginToken;
 
   @override
-  Iterable get childEntities => new ChildEntities()..add(_functionDeclaration);
+  Iterable<SyntacticEntity> get childEntities =>
+      new ChildEntities()..add(_functionDeclaration);
 
   @override
   Token get endToken => _functionDeclaration.endToken;
@@ -5209,7 +5220,7 @@
   }
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       new ChildEntities()..add(_parameters)..add(_body);
 
   @override
@@ -5309,7 +5320,7 @@
   }
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       new ChildEntities()..add(_function)..add(_argumentList);
 
   @override
@@ -5388,7 +5399,7 @@
   }
 
   @override
-  Iterable get childEntities => super._childEntities
+  Iterable<SyntacticEntity> get childEntities => super._childEntities
     ..add(typedefKeyword)
     ..add(_returnType)
     ..add(_name)
@@ -5495,7 +5506,7 @@
   }
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       super._childEntities..add(_returnType)..add(identifier)..add(parameters);
 
   @override
@@ -5567,7 +5578,7 @@
   }
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(keyword)
     ..addAll(_hiddenNames);
 
@@ -5677,7 +5688,7 @@
   Token get beginToken => ifKeyword;
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(ifKeyword)
     ..add(leftParenthesis)
     ..add(_condition)
@@ -5760,7 +5771,7 @@
 
   @override
   // TODO(paulberry): add commas.
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(implementsKeyword)
     ..addAll(interfaces);
 
@@ -5833,7 +5844,7 @@
   }
 
   @override
-  Iterable get childEntities => super._childEntities
+  Iterable<SyntacticEntity> get childEntities => super._childEntities
     ..add(_uri)
     ..add(deferredKeyword)
     ..add(asKeyword)
@@ -5970,7 +5981,7 @@
   }
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(_target)
     ..add(period)
     ..add(leftBracket)
@@ -6147,7 +6158,7 @@
   Token get beginToken => keyword;
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(keyword)
     ..add(_constructorName)
     ..add(_argumentList);
@@ -6216,7 +6227,8 @@
   Token get beginToken => literal;
 
   @override
-  Iterable get childEntities => new ChildEntities()..add(literal);
+  Iterable<SyntacticEntity> get childEntities =>
+      new ChildEntities()..add(literal);
 
   @override
   Token get endToken => literal;
@@ -6282,7 +6294,7 @@
   Token get beginToken => leftBracket;
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(leftBracket)
     ..add(_expression)
     ..add(rightBracket);
@@ -6343,7 +6355,8 @@
   Token get beginToken => contents;
 
   @override
-  Iterable get childEntities => new ChildEntities()..add(contents);
+  Iterable<SyntacticEntity> get childEntities =>
+      new ChildEntities()..add(contents);
 
   @override
   int get contentsEnd {
@@ -6459,7 +6472,7 @@
   Token get beginToken => _expression.beginToken;
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(_expression)
     ..add(isOperator)
     ..add(notOperator)
@@ -6532,7 +6545,7 @@
   }
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..addAll(_labels)
     ..add(_statement);
 
@@ -6593,7 +6606,8 @@
   Token get beginToken => _label.beginToken;
 
   @override
-  Iterable get childEntities => new ChildEntities()..add(_label)..add(colon);
+  Iterable<SyntacticEntity> get childEntities =>
+      new ChildEntities()..add(_label)..add(colon);
 
   @override
   Token get endToken => colon;
@@ -6652,7 +6666,7 @@
   }
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       super._childEntities..add(libraryKeyword)..add(_name)..add(semicolon);
 
   @override
@@ -6711,7 +6725,8 @@
 
   @override
   // TODO(paulberry): add "." tokens.
-  Iterable get childEntities => new ChildEntities()..addAll(_components);
+  Iterable<SyntacticEntity> get childEntities =>
+      new ChildEntities()..addAll(_components);
 
   @override
   NodeList<SimpleIdentifier> get components => _components;
@@ -6805,7 +6820,7 @@
 
   @override
   // TODO(paulberry): add commas.
-  Iterable get childEntities => super._childEntities
+  Iterable<SyntacticEntity> get childEntities => super._childEntities
     ..add(leftBracket)
     ..addAll(_elements)
     ..add(rightBracket);
@@ -6900,7 +6915,7 @@
   Token get beginToken => _key.beginToken;
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       new ChildEntities()..add(_key)..add(separator)..add(_value);
 
   @override
@@ -6983,7 +6998,7 @@
 
   @override
   // TODO(paulberry): add commas.
-  Iterable get childEntities => super._childEntities
+  Iterable<SyntacticEntity> get childEntities => super._childEntities
     ..add(leftBracket)
     ..addAll(entries)
     ..add(rightBracket);
@@ -7116,7 +7131,7 @@
   }
 
   @override
-  Iterable get childEntities => super._childEntities
+  Iterable<SyntacticEntity> get childEntities => super._childEntities
     ..add(externalKeyword)
     ..add(modifierKeyword)
     ..add(_returnType)
@@ -7278,7 +7293,7 @@
   }
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(_target)
     ..add(operator)
     ..add(_methodName)
@@ -7401,7 +7416,7 @@
   Token get beginToken => _name.beginToken;
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       new ChildEntities()..add(_name)..add(_expression);
 
   @override
@@ -7558,7 +7573,7 @@
   Token get beginToken => nativeKeyword;
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       new ChildEntities()..add(nativeKeyword)..add(_name);
 
   @override
@@ -7622,7 +7637,7 @@
   Token get beginToken => nativeKeyword;
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(nativeKeyword)
     ..add(_stringLiteral)
     ..add(semicolon);
@@ -7928,7 +7943,8 @@
   Token get beginToken => literal;
 
   @override
-  Iterable get childEntities => new ChildEntities()..add(literal);
+  Iterable<SyntacticEntity> get childEntities =>
+      new ChildEntities()..add(literal);
 
   @override
   Token get endToken => literal;
@@ -7978,7 +7994,7 @@
   Token get beginToken => leftParenthesis;
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(leftParenthesis)
     ..add(_expression)
     ..add(rightParenthesis);
@@ -8047,7 +8063,7 @@
       : super(comment, metadata, partUri);
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       super._childEntities..add(partKeyword)..add(_uri)..add(semicolon);
 
   @override
@@ -8114,7 +8130,7 @@
   }
 
   @override
-  Iterable get childEntities => super._childEntities
+  Iterable<SyntacticEntity> get childEntities => super._childEntities
     ..add(partKeyword)
     ..add(ofKeyword)
     ..add(_libraryName)
@@ -8204,7 +8220,7 @@
   }
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       new ChildEntities()..add(_operand)..add(operator);
 
   @override
@@ -8317,7 +8333,7 @@
   }
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       new ChildEntities()..add(_prefix)..add(period)..add(_identifier);
 
   @override
@@ -8437,7 +8453,7 @@
   }
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       new ChildEntities()..add(operator)..add(_operand);
 
   @override
@@ -8542,7 +8558,7 @@
   }
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       new ChildEntities()..add(_target)..add(operator)..add(_propertyName);
 
   @override
@@ -8661,7 +8677,7 @@
   Token get beginToken => thisKeyword;
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(thisKeyword)
     ..add(period)
     ..add(_constructorName)
@@ -8711,7 +8727,8 @@
   Token get beginToken => rethrowKeyword;
 
   @override
-  Iterable get childEntities => new ChildEntities()..add(rethrowKeyword);
+  Iterable<SyntacticEntity> get childEntities =>
+      new ChildEntities()..add(rethrowKeyword);
 
   @override
   Token get endToken => rethrowKeyword;
@@ -8765,7 +8782,7 @@
   Token get beginToken => returnKeyword;
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       new ChildEntities()..add(returnKeyword)..add(_expression)..add(semicolon);
 
   @override
@@ -8810,7 +8827,8 @@
   Token get beginToken => scriptTag;
 
   @override
-  Iterable get childEntities => new ChildEntities()..add(scriptTag);
+  Iterable<SyntacticEntity> get childEntities =>
+      new ChildEntities()..add(scriptTag);
 
   @override
   Token get endToken => scriptTag;
@@ -8847,7 +8865,7 @@
 
   @override
   // TODO(paulberry): add commas.
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(keyword)
     ..addAll(_shownNames);
 
@@ -8913,7 +8931,7 @@
   }
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       super._childEntities..add(keyword)..add(_type)..add(identifier);
 
   @override
@@ -9000,7 +9018,8 @@
   }
 
   @override
-  Iterable get childEntities => new ChildEntities()..add(token);
+  Iterable<SyntacticEntity> get childEntities =>
+      new ChildEntities()..add(token);
 
   @override
   Token get endToken => token;
@@ -9180,7 +9199,8 @@
   Token get beginToken => literal;
 
   @override
-  Iterable get childEntities => new ChildEntities()..add(literal);
+  Iterable<SyntacticEntity> get childEntities =>
+      new ChildEntities()..add(literal);
 
   @override
   int get contentsEnd => offset + _helper.end;
@@ -9289,7 +9309,8 @@
   Token get beginToken => _elements.beginToken;
 
   @override
-  Iterable get childEntities => new ChildEntities()..addAll(_elements);
+  Iterable<SyntacticEntity> get childEntities =>
+      new ChildEntities()..addAll(_elements);
 
   @override
   int get contentsEnd {
@@ -9526,7 +9547,7 @@
   Token get beginToken => superKeyword;
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(superKeyword)
     ..add(period)
     ..add(_constructorName)
@@ -9575,7 +9596,8 @@
   Token get beginToken => superKeyword;
 
   @override
-  Iterable get childEntities => new ChildEntities()..add(superKeyword);
+  Iterable<SyntacticEntity> get childEntities =>
+      new ChildEntities()..add(superKeyword);
 
   @override
   Token get endToken => superKeyword;
@@ -9616,7 +9638,7 @@
   }
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..addAll(labels)
     ..add(keyword)
     ..add(_expression)
@@ -9659,7 +9681,7 @@
       : super(labels, keyword, colon, statements);
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..addAll(labels)
     ..add(keyword)
     ..add(colon)
@@ -9800,7 +9822,7 @@
   Token get beginToken => switchKeyword;
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(switchKeyword)
     ..add(leftParenthesis)
     ..add(_expression)
@@ -9861,7 +9883,7 @@
 
   @override
   // TODO(paulberry): add "." tokens.
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(poundSign)
     ..addAll(components);
 
@@ -9899,7 +9921,8 @@
   Token get beginToken => thisKeyword;
 
   @override
-  Iterable get childEntities => new ChildEntities()..add(thisKeyword);
+  Iterable<SyntacticEntity> get childEntities =>
+      new ChildEntities()..add(thisKeyword);
 
   @override
   Token get endToken => thisKeyword;
@@ -9945,7 +9968,7 @@
   Token get beginToken => throwKeyword;
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       new ChildEntities()..add(throwKeyword)..add(_expression);
 
   @override
@@ -10011,7 +10034,7 @@
   }
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       super._childEntities..add(_variableList)..add(semicolon);
 
   @override
@@ -10110,7 +10133,7 @@
   NodeList<CatchClause> get catchClauses => _catchClauses;
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(tryKeyword)
     ..add(_body)
     ..addAll(_catchClauses)
@@ -10225,7 +10248,7 @@
 
   @override
   // TODO(paulberry): Add commas.
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(leftBracket)
     ..addAll(_arguments)
     ..add(rightBracket);
@@ -10329,7 +10352,7 @@
   Token get beginToken => _name.beginToken;
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       new ChildEntities()..add(_name)..add(_typeArguments);
 
   @override
@@ -10425,7 +10448,7 @@
   }
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       super._childEntities..add(_name)..add(extendsKeyword)..add(_bound);
 
   @override
@@ -10497,7 +10520,7 @@
   Token get beginToken => leftBracket;
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(leftBracket)
     ..addAll(_typeParameters)
     ..add(rightBracket);
@@ -10683,7 +10706,7 @@
   }
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       super._childEntities..add(_name)..add(equals)..add(_initializer);
 
   /**
@@ -10802,7 +10825,7 @@
 
   @override
   // TODO(paulberry): include commas.
-  Iterable get childEntities => super._childEntities
+  Iterable<SyntacticEntity> get childEntities => super._childEntities
     ..add(keyword)
     ..add(_type)
     ..addAll(_variables);
@@ -10880,7 +10903,7 @@
   Token get beginToken => _variableList.beginToken;
 
   @override
-  Iterable get childEntities =>
+  Iterable<SyntacticEntity> get childEntities =>
       new ChildEntities()..add(_variableList)..add(semicolon);
 
   @override
@@ -10957,7 +10980,7 @@
   }
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(whileKeyword)
     ..add(leftParenthesis)
     ..add(_condition)
@@ -11015,7 +11038,7 @@
 
   @override
   // TODO(paulberry): add commas.
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(withKeyword)
     ..addAll(_mixinTypes);
 
@@ -11080,7 +11103,7 @@
   }
 
   @override
-  Iterable get childEntities => new ChildEntities()
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(yieldKeyword)
     ..add(star)
     ..add(_expression)
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 5d70df8..4118d8d 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -21,7 +21,6 @@
 import 'package:analyzer/src/generated/constant.dart' show EvaluationResultImpl;
 import 'package:analyzer/src/generated/engine.dart'
     show AnalysisContext, AnalysisEngine;
-import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
@@ -700,6 +699,18 @@
     return false;
   }
 
+  /**
+   * Return `true` if the class has a `noSuchMethod()` method distinct from the
+   * one declared in class `Object`, as per the Dart Language Specification
+   * (section 10.4).
+   */
+  bool get hasNoSuchMethod {
+    MethodElement method =
+        lookUpMethod(FunctionElement.NO_SUCH_METHOD_METHOD_NAME, library);
+    ClassElement definingClass = method?.enclosingElement;
+    return definingClass != null && !definingClass.type.isObject;
+  }
+
   @override
   bool get hasReferenceToSuper => hasModifier(Modifier.REFERENCES_SUPER);
 
@@ -3074,7 +3085,7 @@
    * Return `true` if this element has the given [modifier] associated with it.
    */
   bool hasModifier(Modifier modifier) =>
-      BooleanArray.getEnum(_modifiers, modifier);
+      BooleanArray.get(_modifiers, modifier.ordinal);
 
   @override
   bool isAccessibleIn(LibraryElement library) {
@@ -3109,7 +3120,7 @@
    * correspond to the given [value].
    */
   void setModifier(Modifier modifier, bool value) {
-    _modifiers = BooleanArray.setEnum(_modifiers, modifier, value);
+    _modifiers = BooleanArray.set(_modifiers, modifier.ordinal, value);
   }
 
   @override
@@ -6179,12 +6190,12 @@
 }
 
 /**
- * The enumeration `Modifier` defines constants for all of the modifiers defined
- * by the Dart language and for a few additional flags that are useful.
+ * The constants for all of the modifiers defined by the Dart language and for a
+ * few additional flags that are useful.
  *
  * Clients may not extend, implement or mix-in this class.
  */
-class Modifier extends Enum<Modifier> {
+class Modifier implements Comparable<Modifier> {
   /**
    * Indicates that the modifier 'abstract' was applied to the element.
    */
@@ -6301,7 +6312,26 @@
     SYNTHETIC
   ];
 
-  const Modifier(String name, int ordinal) : super(name, ordinal);
+  /**
+   * The name of this modifier.
+   */
+  final String name;
+
+  /**
+   * The ordinal value of the modifier.
+   */
+  final int ordinal;
+
+  const Modifier(this.name, this.ordinal);
+
+  @override
+  int get hashCode => ordinal;
+
+  @override
+  int compareTo(Modifier other) => ordinal - other.ordinal;
+
+  @override
+  String toString() => name;
 }
 
 /**
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart
index 0ee331a..29b347f 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -114,9 +114,6 @@
     List<DartType> parameterTypes = definingType.element.type.typeArguments;
     FunctionType substitutedType =
         baseType.substitute2(argumentTypes, parameterTypes);
-    if (baseType == substitutedType) {
-      return constructor;
-    }
     return new ConstructorMember(constructor, definingType, substitutedType);
   }
 }
@@ -408,9 +405,6 @@
         TypeParameterTypeImpl.getTypes(definingType.typeParameters);
     FunctionType substitutedType =
         baseType.substitute2(argumentTypes, parameterTypes);
-    if (baseType == substitutedType) {
-      return method;
-    }
     return new MethodMember(method, definingType, substitutedType);
   }
 }
@@ -645,9 +639,6 @@
     List<DartType> parameterTypes = definingType.element.type.typeArguments;
     FunctionType substitutedType =
         baseType.substitute2(argumentTypes, parameterTypes);
-    if (baseType == substitutedType) {
-      return method;
-    }
     return new MethodMember(method, definingType, substitutedType);
   }
 }
@@ -776,9 +767,6 @@
           TypeParameterTypeImpl.getTypes(definingType.typeParameters);
       DartType substitutedType =
           baseType.substitute2(argumentTypes, parameterTypes);
-      if (baseType == substitutedType) {
-        return parameter;
-      }
       return new ParameterMember(parameter, definingType, substitutedType);
     }
   }
@@ -990,9 +978,6 @@
         TypeParameterTypeImpl.getTypes(definingType.typeParameters);
     DartType substitutedBound =
         bound.substitute2(argumentTypes, parameterTypes);
-    if (bound == substitutedBound) {
-      return parameter;
-    }
     return new TypeParameterMember(parameter, definingType, substitutedBound);
   }
 }
diff --git a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
new file mode 100644
index 0000000..31ee726
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
@@ -0,0 +1,711 @@
+// 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.
+
+/**
+ * The errors produced during sytactic analysis (scanning and parsing).
+ */
+library analyzer.src.dart.error.syntactic_errors;
+
+import 'package:analyzer/error/error.dart';
+
+/**
+ * The error codes used for errors detected by the parser. The convention for
+ * this class is for the name of the error code to indicate the problem that
+ * caused the error to be generated and for the error message to explain what
+ * is wrong and, when appropriate, how the problem can be corrected.
+ */
+class ParserErrorCode extends ErrorCode {
+  static const ParserErrorCode ABSTRACT_CLASS_MEMBER = const ParserErrorCode(
+      'ABSTRACT_CLASS_MEMBER',
+      "Members of classes cannot be declared to be 'abstract'");
+
+  static const ParserErrorCode ABSTRACT_ENUM = const ParserErrorCode(
+      'ABSTRACT_ENUM', "Enums cannot be declared to be 'abstract'");
+
+  static const ParserErrorCode ABSTRACT_STATIC_METHOD = const ParserErrorCode(
+      'ABSTRACT_STATIC_METHOD',
+      "Static methods cannot be declared to be 'abstract'");
+
+  static const ParserErrorCode ABSTRACT_TOP_LEVEL_FUNCTION =
+      const ParserErrorCode('ABSTRACT_TOP_LEVEL_FUNCTION',
+          "Top-level functions cannot be declared to be 'abstract'");
+
+  static const ParserErrorCode ABSTRACT_TOP_LEVEL_VARIABLE =
+      const ParserErrorCode('ABSTRACT_TOP_LEVEL_VARIABLE',
+          "Top-level variables cannot be declared to be 'abstract'");
+
+  static const ParserErrorCode ABSTRACT_TYPEDEF = const ParserErrorCode(
+      'ABSTRACT_TYPEDEF', "Type aliases cannot be declared to be 'abstract'");
+
+  static const ParserErrorCode ANNOTATION_ON_ENUM_CONSTANT =
+      const ParserErrorCode('ANNOTATION_ON_ENUM_CONSTANT',
+          "Enum constants cannot have annotations");
+
+  /**
+   * 16.32 Identifier Reference: It is a compile-time error if any of the
+   * identifiers async, await, or yield is used as an identifier in a function
+   * body marked with either async, async*, or sync*.
+   */
+  static const ParserErrorCode ASYNC_KEYWORD_USED_AS_IDENTIFIER =
+      const ParserErrorCode('ASYNC_KEYWORD_USED_AS_IDENTIFIER',
+          "The keywords 'async', 'await', and 'yield' may not be used as identifiers in an asynchronous or generator function.");
+
+  /**
+   * Some environments, such as Fletch, do not support async.
+   */
+  static const ParserErrorCode ASYNC_NOT_SUPPORTED = const ParserErrorCode(
+      'ASYNC_NOT_SUPPORTED',
+      "Async and sync are not supported in this environment.");
+
+  static const ParserErrorCode BREAK_OUTSIDE_OF_LOOP = const ParserErrorCode(
+      'BREAK_OUTSIDE_OF_LOOP',
+      "A break statement cannot be used outside of a loop or switch statement");
+
+  static const ParserErrorCode CLASS_IN_CLASS = const ParserErrorCode(
+      'CLASS_IN_CLASS',
+      "Classes can't be declared inside other classes.",
+      "Try moving the class to the top-level.");
+
+  static const ParserErrorCode COLON_IN_PLACE_OF_IN = const ParserErrorCode(
+      'COLON_IN_PLACE_OF_IN', "For-in loops use 'in' rather than a colon");
+
+  static const ParserErrorCode CONST_AND_FINAL = const ParserErrorCode(
+      'CONST_AND_FINAL',
+      "Members can't be declared to be both 'const' and 'final'.",
+      "Try removing either the 'const' or 'final' keyword.");
+
+  static const ParserErrorCode CONST_AND_VAR = const ParserErrorCode(
+      'CONST_AND_VAR',
+      "Members can't be declared to be both 'const' and 'var'.",
+      "Try removing either the 'const' or 'var' keyword.");
+
+  static const ParserErrorCode CONST_CLASS = const ParserErrorCode(
+      'CONST_CLASS',
+      "Classes can't be declared to be 'const'.",
+      "Try removing the 'const' keyword or moving to the class' constructor(s).");
+
+  static const ParserErrorCode CONST_CONSTRUCTOR_WITH_BODY =
+      const ParserErrorCode(
+          'CONST_CONSTRUCTOR_WITH_BODY',
+          "Const constructor can't have a body.",
+          "Try removing the 'const' keyword or the body.");
+
+  static const ParserErrorCode CONST_ENUM = const ParserErrorCode(
+      'CONST_ENUM',
+      "Enums can't be declared to be 'const'.",
+      "Try removing the 'const' keyword.");
+
+  static const ParserErrorCode CONST_FACTORY = const ParserErrorCode(
+      'CONST_FACTORY',
+      "Only redirecting factory constructors can be declared to be 'const'.",
+      "Try removing the 'const' keyword or replacing the body with '=' followed by a valid target.");
+
+  static const ParserErrorCode CONST_METHOD = const ParserErrorCode(
+      'CONST_METHOD',
+      "Getters, setters and methods can't be declared to be 'const'.",
+      "Try removing the 'const' keyword.");
+
+  static const ParserErrorCode CONST_TYPEDEF = const ParserErrorCode(
+      'CONST_TYPEDEF',
+      "Type aliases can't be declared to be 'const'.",
+      "Try removing the 'const' keyword.");
+
+  static const ParserErrorCode CONSTRUCTOR_WITH_RETURN_TYPE =
+      const ParserErrorCode(
+          'CONSTRUCTOR_WITH_RETURN_TYPE',
+          "Constructors can't have a return type.",
+          "Try removing the return type.");
+
+  static const ParserErrorCode CONTINUE_OUTSIDE_OF_LOOP = const ParserErrorCode(
+      'CONTINUE_OUTSIDE_OF_LOOP',
+      "A continue statement cannot be used outside of a loop or switch statement");
+
+  static const ParserErrorCode CONTINUE_WITHOUT_LABEL_IN_CASE =
+      const ParserErrorCode('CONTINUE_WITHOUT_LABEL_IN_CASE',
+          "A continue statement in a switch statement must have a label as a target");
+
+  static const ParserErrorCode DEPRECATED_CLASS_TYPE_ALIAS =
+      const ParserErrorCode('DEPRECATED_CLASS_TYPE_ALIAS',
+          "The 'typedef' mixin application was replaced with 'class'");
+
+  static const ParserErrorCode DIRECTIVE_AFTER_DECLARATION =
+      const ParserErrorCode('DIRECTIVE_AFTER_DECLARATION',
+          "Directives must appear before any declarations");
+
+  static const ParserErrorCode DUPLICATE_LABEL_IN_SWITCH_STATEMENT =
+      const ParserErrorCode('DUPLICATE_LABEL_IN_SWITCH_STATEMENT',
+          "The label {0} was already used in this switch statement");
+
+  static const ParserErrorCode DUPLICATED_MODIFIER = const ParserErrorCode(
+      'DUPLICATED_MODIFIER', "The modifier '{0}' was already specified.");
+
+  static const ParserErrorCode EMPTY_ENUM_BODY = const ParserErrorCode(
+      'EMPTY_ENUM_BODY', "An enum must declare at least one constant name");
+
+  static const ParserErrorCode ENUM_IN_CLASS = const ParserErrorCode(
+      'ENUM_IN_CLASS', "Enums cannot be declared inside classes");
+
+  static const ParserErrorCode EQUALITY_CANNOT_BE_EQUALITY_OPERAND =
+      const ParserErrorCode('EQUALITY_CANNOT_BE_EQUALITY_OPERAND',
+          "Equality expression cannot be operand of another equality expression.");
+
+  static const ParserErrorCode EXPECTED_CASE_OR_DEFAULT = const ParserErrorCode(
+      'EXPECTED_CASE_OR_DEFAULT', "Expected 'case' or 'default'");
+
+  static const ParserErrorCode EXPECTED_CLASS_MEMBER =
+      const ParserErrorCode('EXPECTED_CLASS_MEMBER', "Expected a class member");
+
+  static const ParserErrorCode EXPECTED_EXECUTABLE = const ParserErrorCode(
+      'EXPECTED_EXECUTABLE',
+      "Expected a method, getter, setter or operator declaration");
+
+  static const ParserErrorCode EXPECTED_LIST_OR_MAP_LITERAL =
+      const ParserErrorCode(
+          'EXPECTED_LIST_OR_MAP_LITERAL', "Expected a list or map literal");
+
+  static const ParserErrorCode EXPECTED_STRING_LITERAL = const ParserErrorCode(
+      'EXPECTED_STRING_LITERAL', "Expected a string literal");
+
+  static const ParserErrorCode EXPECTED_TOKEN =
+      const ParserErrorCode('EXPECTED_TOKEN', "Expected to find '{0}'");
+
+  static const ParserErrorCode EXPECTED_TYPE_NAME =
+      const ParserErrorCode('EXPECTED_TYPE_NAME', "Expected a type name");
+
+  static const ParserErrorCode EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE =
+      const ParserErrorCode('EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE',
+          "Export directives must preceed part directives");
+
+  static const ParserErrorCode EXTERNAL_AFTER_CONST = const ParserErrorCode(
+      'EXTERNAL_AFTER_CONST',
+      "The modifier 'external' should be before the modifier 'const'");
+
+  static const ParserErrorCode EXTERNAL_AFTER_FACTORY = const ParserErrorCode(
+      'EXTERNAL_AFTER_FACTORY',
+      "The modifier 'external' should be before the modifier 'factory'");
+
+  static const ParserErrorCode EXTERNAL_AFTER_STATIC = const ParserErrorCode(
+      'EXTERNAL_AFTER_STATIC',
+      "The modifier 'external' should be before the modifier 'static'");
+
+  static const ParserErrorCode EXTERNAL_CLASS = const ParserErrorCode(
+      'EXTERNAL_CLASS', "Classes cannot be declared to be 'external'");
+
+  static const ParserErrorCode EXTERNAL_CONSTRUCTOR_WITH_BODY =
+      const ParserErrorCode('EXTERNAL_CONSTRUCTOR_WITH_BODY',
+          "External constructors cannot have a body");
+
+  static const ParserErrorCode EXTERNAL_ENUM = const ParserErrorCode(
+      'EXTERNAL_ENUM', "Enums cannot be declared to be 'external'");
+
+  static const ParserErrorCode EXTERNAL_FIELD = const ParserErrorCode(
+      'EXTERNAL_FIELD', "Fields cannot be declared to be 'external'");
+
+  static const ParserErrorCode EXTERNAL_GETTER_WITH_BODY =
+      const ParserErrorCode(
+          'EXTERNAL_GETTER_WITH_BODY', "External getters cannot have a body");
+
+  static const ParserErrorCode EXTERNAL_METHOD_WITH_BODY =
+      const ParserErrorCode(
+          'EXTERNAL_METHOD_WITH_BODY', "External methods cannot have a body");
+
+  static const ParserErrorCode EXTERNAL_OPERATOR_WITH_BODY =
+      const ParserErrorCode('EXTERNAL_OPERATOR_WITH_BODY',
+          "External operators cannot have a body");
+
+  static const ParserErrorCode EXTERNAL_SETTER_WITH_BODY =
+      const ParserErrorCode(
+          'EXTERNAL_SETTER_WITH_BODY', "External setters cannot have a body");
+
+  static const ParserErrorCode EXTERNAL_TYPEDEF = const ParserErrorCode(
+      'EXTERNAL_TYPEDEF', "Type aliases cannot be declared to be 'external'");
+
+  static const ParserErrorCode FACTORY_TOP_LEVEL_DECLARATION =
+      const ParserErrorCode('FACTORY_TOP_LEVEL_DECLARATION',
+          "Top-level declarations cannot be declared to be 'factory'");
+
+  static const ParserErrorCode FACTORY_WITH_INITIALIZERS =
+      const ParserErrorCode(
+          'FACTORY_WITH_INITIALIZERS',
+          "A 'factory' constructor cannot have initializers",
+          "Either remove the 'factory' keyword to make this a generative "
+          "constructor or remove the initializers.");
+
+  static const ParserErrorCode FACTORY_WITHOUT_BODY = const ParserErrorCode(
+      'FACTORY_WITHOUT_BODY',
+      "A non-redirecting 'factory' constructor must have a body");
+
+  static const ParserErrorCode FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR =
+      const ParserErrorCode('FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR',
+          "Field initializers can only be used in a constructor");
+
+  static const ParserErrorCode FINAL_AND_VAR = const ParserErrorCode(
+      'FINAL_AND_VAR',
+      "Members cannot be declared to be both 'final' and 'var'");
+
+  static const ParserErrorCode FINAL_CLASS = const ParserErrorCode(
+      'FINAL_CLASS', "Classes cannot be declared to be 'final'");
+
+  static const ParserErrorCode FINAL_CONSTRUCTOR = const ParserErrorCode(
+      'FINAL_CONSTRUCTOR', "A constructor cannot be declared to be 'final'");
+
+  static const ParserErrorCode FINAL_ENUM = const ParserErrorCode(
+      'FINAL_ENUM', "Enums cannot be declared to be 'final'");
+
+  static const ParserErrorCode FINAL_METHOD = const ParserErrorCode(
+      'FINAL_METHOD',
+      "Getters, setters and methods cannot be declared to be 'final'");
+
+  static const ParserErrorCode FINAL_TYPEDEF = const ParserErrorCode(
+      'FINAL_TYPEDEF', "Type aliases cannot be declared to be 'final'");
+
+  static const ParserErrorCode FUNCTION_TYPED_PARAMETER_VAR = const ParserErrorCode(
+      'FUNCTION_TYPED_PARAMETER_VAR',
+      "Function typed parameters cannot specify 'const', 'final' or 'var' instead of return type");
+
+  static const ParserErrorCode GETTER_IN_FUNCTION = const ParserErrorCode(
+      'GETTER_IN_FUNCTION',
+      "Getters cannot be defined within methods or functions");
+
+  static const ParserErrorCode GETTER_WITH_PARAMETERS = const ParserErrorCode(
+      'GETTER_WITH_PARAMETERS',
+      "Getter should be declared without a parameter list");
+
+  static const ParserErrorCode ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE =
+      const ParserErrorCode('ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE',
+          "Illegal assignment to non-assignable expression");
+
+  static const ParserErrorCode IMPLEMENTS_BEFORE_EXTENDS =
+      const ParserErrorCode('IMPLEMENTS_BEFORE_EXTENDS',
+          "The extends clause must be before the implements clause");
+
+  static const ParserErrorCode IMPLEMENTS_BEFORE_WITH = const ParserErrorCode(
+      'IMPLEMENTS_BEFORE_WITH',
+      "The with clause must be before the implements clause");
+
+  static const ParserErrorCode IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE =
+      const ParserErrorCode('IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE',
+          "Import directives must preceed part directives");
+
+  static const ParserErrorCode INITIALIZED_VARIABLE_IN_FOR_EACH =
+      const ParserErrorCode('INITIALIZED_VARIABLE_IN_FOR_EACH',
+          "The loop variable in a for-each loop cannot be initialized");
+
+  static const ParserErrorCode INVALID_AWAIT_IN_FOR = const ParserErrorCode(
+      'INVALID_AWAIT_IN_FOR',
+      "The modifier 'await' is not allowed for a normal 'for' statement",
+      "Remove the keyword or use a for-each statement.");
+
+  static const ParserErrorCode INVALID_CODE_POINT = const ParserErrorCode(
+      'INVALID_CODE_POINT',
+      "The escape sequence '{0}' is not a valid code point");
+
+  static const ParserErrorCode INVALID_COMMENT_REFERENCE = const ParserErrorCode(
+      'INVALID_COMMENT_REFERENCE',
+      "Comment references should contain a possibly prefixed identifier and can start with 'new', but should not contain anything else");
+
+  static const ParserErrorCode INVALID_HEX_ESCAPE = const ParserErrorCode(
+      'INVALID_HEX_ESCAPE',
+      "An escape sequence starting with '\\x' must be followed by 2 hexidecimal digits");
+
+  static const ParserErrorCode INVALID_LITERAL_IN_CONFIGURATION =
+      const ParserErrorCode('INVALID_LITERAL_IN_CONFIGURATION',
+          "The literal in a configuration cannot contain interpolation");
+
+  static const ParserErrorCode INVALID_OPERATOR = const ParserErrorCode(
+      'INVALID_OPERATOR', "The string '{0}' is not a valid operator");
+
+  static const ParserErrorCode INVALID_OPERATOR_FOR_SUPER =
+      const ParserErrorCode('INVALID_OPERATOR_FOR_SUPER',
+          "The operator '{0}' cannot be used with 'super'");
+
+  static const ParserErrorCode INVALID_STAR_AFTER_ASYNC = const ParserErrorCode(
+      'INVALID_STAR_AFTER_ASYNC',
+      "The modifier 'async*' is not allowed for an expression function body",
+      "Convert the body to a block.");
+
+  static const ParserErrorCode INVALID_SYNC = const ParserErrorCode(
+      'INVALID_SYNC',
+      "The modifier 'sync' is not allowed for an exrpression function body",
+      "Convert the body to a block.");
+
+  static const ParserErrorCode INVALID_UNICODE_ESCAPE = const ParserErrorCode(
+      'INVALID_UNICODE_ESCAPE',
+      "An escape sequence starting with '\\u' must be followed by 4 hexidecimal digits or from 1 to 6 digits between '{' and '}'");
+
+  static const ParserErrorCode LIBRARY_DIRECTIVE_NOT_FIRST =
+      const ParserErrorCode('LIBRARY_DIRECTIVE_NOT_FIRST',
+          "The library directive must appear before all other directives");
+
+  static const ParserErrorCode LOCAL_FUNCTION_DECLARATION_MODIFIER =
+      const ParserErrorCode('LOCAL_FUNCTION_DECLARATION_MODIFIER',
+          "Local function declarations cannot specify any modifier");
+
+  static const ParserErrorCode MISSING_ASSIGNABLE_SELECTOR =
+      const ParserErrorCode('MISSING_ASSIGNABLE_SELECTOR',
+          "Missing selector such as \".<identifier>\" or \"[0]\"");
+
+  static const ParserErrorCode MISSING_ASSIGNMENT_IN_INITIALIZER =
+      const ParserErrorCode('MISSING_ASSIGNMENT_IN_INITIALIZER',
+          "Expected an assignment after the field name");
+
+  static const ParserErrorCode MISSING_CATCH_OR_FINALLY = const ParserErrorCode(
+      'MISSING_CATCH_OR_FINALLY',
+      "A try statement must have either a catch or finally clause");
+
+  static const ParserErrorCode MISSING_CLASS_BODY = const ParserErrorCode(
+      'MISSING_CLASS_BODY',
+      "A class definition must have a body, even if it is empty");
+
+  static const ParserErrorCode MISSING_CLOSING_PARENTHESIS =
+      const ParserErrorCode(
+          'MISSING_CLOSING_PARENTHESIS', "The closing parenthesis is missing");
+
+  static const ParserErrorCode MISSING_CONST_FINAL_VAR_OR_TYPE =
+      const ParserErrorCode('MISSING_CONST_FINAL_VAR_OR_TYPE',
+          "Variables must be declared using the keywords 'const', 'final', 'var' or a type name");
+
+  static const ParserErrorCode MISSING_ENUM_BODY = const ParserErrorCode(
+      'MISSING_ENUM_BODY',
+      "An enum definition must have a body with at least one constant name");
+
+  static const ParserErrorCode MISSING_EXPRESSION_IN_INITIALIZER =
+      const ParserErrorCode('MISSING_EXPRESSION_IN_INITIALIZER',
+          "Expected an expression after the assignment operator");
+
+  static const ParserErrorCode MISSING_EXPRESSION_IN_THROW =
+      const ParserErrorCode('MISSING_EXPRESSION_IN_THROW',
+          "Missing expression after 'throw'.", "Did you mean 'rethrow'?");
+
+  static const ParserErrorCode MISSING_FUNCTION_BODY = const ParserErrorCode(
+      'MISSING_FUNCTION_BODY', "A function body must be provided");
+
+  static const ParserErrorCode MISSING_FUNCTION_PARAMETERS =
+      const ParserErrorCode('MISSING_FUNCTION_PARAMETERS',
+          "Functions must have an explicit list of parameters");
+
+  static const ParserErrorCode MISSING_METHOD_PARAMETERS =
+      const ParserErrorCode('MISSING_METHOD_PARAMETERS',
+          "Methods must have an explicit list of parameters");
+
+  static const ParserErrorCode MISSING_GET = const ParserErrorCode(
+      'MISSING_GET',
+      "Getters must have the keyword 'get' before the getter name");
+
+  static const ParserErrorCode MISSING_IDENTIFIER =
+      const ParserErrorCode('MISSING_IDENTIFIER', "Expected an identifier");
+
+  static const ParserErrorCode MISSING_INITIALIZER =
+      const ParserErrorCode('MISSING_INITIALIZER', "Expected an initializer");
+
+  static const ParserErrorCode MISSING_KEYWORD_OPERATOR = const ParserErrorCode(
+      'MISSING_KEYWORD_OPERATOR',
+      "Operator declarations must be preceeded by the keyword 'operator'");
+
+  static const ParserErrorCode MISSING_NAME_IN_LIBRARY_DIRECTIVE =
+      const ParserErrorCode('MISSING_NAME_IN_LIBRARY_DIRECTIVE',
+          "Library directives must include a library name");
+
+  static const ParserErrorCode MISSING_NAME_IN_PART_OF_DIRECTIVE =
+      const ParserErrorCode('MISSING_NAME_IN_PART_OF_DIRECTIVE',
+          "Library directives must include a library name");
+
+  static const ParserErrorCode MISSING_PREFIX_IN_DEFERRED_IMPORT =
+      const ParserErrorCode('MISSING_PREFIX_IN_DEFERRED_IMPORT',
+          "Deferred imports must have a prefix");
+
+  static const ParserErrorCode MISSING_STAR_AFTER_SYNC = const ParserErrorCode(
+      'MISSING_STAR_AFTER_SYNC',
+      "The modifier 'sync' must be followed by a star ('*')",
+      "Remove the modifier or add a star.");
+
+  static const ParserErrorCode MISSING_STATEMENT =
+      const ParserErrorCode('MISSING_STATEMENT', "Expected a statement");
+
+  static const ParserErrorCode MISSING_TERMINATOR_FOR_PARAMETER_GROUP =
+      const ParserErrorCode('MISSING_TERMINATOR_FOR_PARAMETER_GROUP',
+          "There is no '{0}' to close the parameter group");
+
+  static const ParserErrorCode MISSING_TYPEDEF_PARAMETERS =
+      const ParserErrorCode('MISSING_TYPEDEF_PARAMETERS',
+          "Type aliases for functions must have an explicit list of parameters");
+
+  static const ParserErrorCode MISSING_VARIABLE_IN_FOR_EACH = const ParserErrorCode(
+      'MISSING_VARIABLE_IN_FOR_EACH',
+      "A loop variable must be declared in a for-each loop before the 'in', but none were found");
+
+  static const ParserErrorCode MIXED_PARAMETER_GROUPS = const ParserErrorCode(
+      'MIXED_PARAMETER_GROUPS',
+      "Cannot have both positional and named parameters in a single parameter list");
+
+  static const ParserErrorCode MULTIPLE_EXTENDS_CLAUSES = const ParserErrorCode(
+      'MULTIPLE_EXTENDS_CLAUSES',
+      "Each class definition can have at most one extends clause");
+
+  static const ParserErrorCode MULTIPLE_IMPLEMENTS_CLAUSES =
+      const ParserErrorCode('MULTIPLE_IMPLEMENTS_CLAUSES',
+          "Each class definition can have at most one implements clause");
+
+  static const ParserErrorCode MULTIPLE_LIBRARY_DIRECTIVES =
+      const ParserErrorCode('MULTIPLE_LIBRARY_DIRECTIVES',
+          "Only one library directive may be declared in a file");
+
+  static const ParserErrorCode MULTIPLE_NAMED_PARAMETER_GROUPS =
+      const ParserErrorCode('MULTIPLE_NAMED_PARAMETER_GROUPS',
+          "Cannot have multiple groups of named parameters in a single parameter list");
+
+  static const ParserErrorCode MULTIPLE_PART_OF_DIRECTIVES =
+      const ParserErrorCode('MULTIPLE_PART_OF_DIRECTIVES',
+          "Only one part-of directive may be declared in a file");
+
+  static const ParserErrorCode MULTIPLE_POSITIONAL_PARAMETER_GROUPS =
+      const ParserErrorCode('MULTIPLE_POSITIONAL_PARAMETER_GROUPS',
+          "Cannot have multiple groups of positional parameters in a single parameter list");
+
+  static const ParserErrorCode MULTIPLE_VARIABLES_IN_FOR_EACH =
+      const ParserErrorCode('MULTIPLE_VARIABLES_IN_FOR_EACH',
+          "A single loop variable must be declared in a for-each loop before the 'in', but {0} were found");
+
+  static const ParserErrorCode MULTIPLE_WITH_CLAUSES = const ParserErrorCode(
+      'MULTIPLE_WITH_CLAUSES',
+      "Each class definition can have at most one with clause");
+
+  static const ParserErrorCode NAMED_FUNCTION_EXPRESSION =
+      const ParserErrorCode(
+          'NAMED_FUNCTION_EXPRESSION', "Function expressions cannot be named");
+
+  static const ParserErrorCode NAMED_PARAMETER_OUTSIDE_GROUP =
+      const ParserErrorCode('NAMED_PARAMETER_OUTSIDE_GROUP',
+          "Named parameters must be enclosed in curly braces ('{' and '}')");
+
+  static const ParserErrorCode NATIVE_CLAUSE_IN_NON_SDK_CODE =
+      const ParserErrorCode('NATIVE_CLAUSE_IN_NON_SDK_CODE',
+          "Native clause can only be used in the SDK and code that is loaded through native extensions");
+
+  static const ParserErrorCode NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE =
+      const ParserErrorCode('NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE',
+          "Native functions can only be declared in the SDK and code that is loaded through native extensions");
+
+  static const ParserErrorCode NON_CONSTRUCTOR_FACTORY = const ParserErrorCode(
+      'NON_CONSTRUCTOR_FACTORY',
+      "Only constructors can be declared to be a 'factory'");
+
+  static const ParserErrorCode NON_IDENTIFIER_LIBRARY_NAME =
+      const ParserErrorCode('NON_IDENTIFIER_LIBRARY_NAME',
+          "The name of a library must be an identifier");
+
+  static const ParserErrorCode NON_PART_OF_DIRECTIVE_IN_PART =
+      const ParserErrorCode('NON_PART_OF_DIRECTIVE_IN_PART',
+          "The part-of directive must be the only directive in a part");
+
+  static const ParserErrorCode NON_STRING_LITERAL_AS_URI =
+      const ParserErrorCode(
+          'NON_STRING_LITERAL_AS_URI',
+          "The URI must be a string literal",
+          "Enclose the URI in either single or double quotes.");
+
+  static const ParserErrorCode NON_USER_DEFINABLE_OPERATOR =
+      const ParserErrorCode('NON_USER_DEFINABLE_OPERATOR',
+          "The operator '{0}' is not user definable");
+
+  static const ParserErrorCode NORMAL_BEFORE_OPTIONAL_PARAMETERS =
+      const ParserErrorCode('NORMAL_BEFORE_OPTIONAL_PARAMETERS',
+          "Normal parameters must occur before optional parameters");
+
+  static const ParserErrorCode NULLABLE_TYPE_IN_EXTENDS = const ParserErrorCode(
+      'NULLABLE_TYPE_IN_EXTENDS',
+      "A nullable type cannot be used in an extends clause",
+      "Remove the '?' from the type name");
+
+  static const ParserErrorCode NULLABLE_TYPE_IN_IMPLEMENTS =
+      const ParserErrorCode(
+          'NULLABLE_TYPE_IN_IMPLEMENTS',
+          "A nullable type cannot be used in an implements clause",
+          "Remove the '?' from the type name");
+
+  static const ParserErrorCode NULLABLE_TYPE_IN_WITH = const ParserErrorCode(
+      'NULLABLE_TYPE_IN_WITH',
+      "A nullable type cannot be used in a with clause",
+      "Remove the '?' from the type name");
+
+  static const ParserErrorCode NULLABLE_TYPE_PARAMETER = const ParserErrorCode(
+      'NULLABLE_TYPE_PARAMETER',
+      "Type parameters cannot be nullable",
+      "Remove the '?' from the type name");
+
+  static const ParserErrorCode POSITIONAL_AFTER_NAMED_ARGUMENT =
+      const ParserErrorCode('POSITIONAL_AFTER_NAMED_ARGUMENT',
+          "Positional arguments must occur before named arguments");
+
+  static const ParserErrorCode POSITIONAL_PARAMETER_OUTSIDE_GROUP =
+      const ParserErrorCode('POSITIONAL_PARAMETER_OUTSIDE_GROUP',
+          "Positional parameters must be enclosed in square brackets ('[' and ']')");
+
+  static const ParserErrorCode REDIRECTING_CONSTRUCTOR_WITH_BODY =
+      const ParserErrorCode('REDIRECTING_CONSTRUCTOR_WITH_BODY',
+          "Redirecting constructors cannot have a body");
+
+  static const ParserErrorCode REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR =
+      const ParserErrorCode('REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR',
+          "Only factory constructor can specify '=' redirection.");
+
+  static const ParserErrorCode SETTER_IN_FUNCTION = const ParserErrorCode(
+      'SETTER_IN_FUNCTION',
+      "Setters cannot be defined within methods or functions");
+
+  static const ParserErrorCode STATIC_AFTER_CONST = const ParserErrorCode(
+      'STATIC_AFTER_CONST',
+      "The modifier 'static' should be before the modifier 'const'");
+
+  static const ParserErrorCode STATIC_AFTER_FINAL = const ParserErrorCode(
+      'STATIC_AFTER_FINAL',
+      "The modifier 'static' should be before the modifier 'final'");
+
+  static const ParserErrorCode STATIC_AFTER_VAR = const ParserErrorCode(
+      'STATIC_AFTER_VAR',
+      "The modifier 'static' should be before the modifier 'var'");
+
+  static const ParserErrorCode STATIC_CONSTRUCTOR = const ParserErrorCode(
+      'STATIC_CONSTRUCTOR', "Constructors cannot be static");
+
+  static const ParserErrorCode STATIC_GETTER_WITHOUT_BODY =
+      const ParserErrorCode(
+          'STATIC_GETTER_WITHOUT_BODY', "A 'static' getter must have a body");
+
+  static const ParserErrorCode STATIC_OPERATOR =
+      const ParserErrorCode('STATIC_OPERATOR', "Operators cannot be static");
+
+  static const ParserErrorCode STATIC_SETTER_WITHOUT_BODY =
+      const ParserErrorCode(
+          'STATIC_SETTER_WITHOUT_BODY', "A 'static' setter must have a body");
+
+  static const ParserErrorCode STATIC_TOP_LEVEL_DECLARATION =
+      const ParserErrorCode('STATIC_TOP_LEVEL_DECLARATION',
+          "Top-level declarations cannot be declared to be 'static'");
+
+  static const ParserErrorCode SWITCH_HAS_CASE_AFTER_DEFAULT_CASE =
+      const ParserErrorCode('SWITCH_HAS_CASE_AFTER_DEFAULT_CASE',
+          "The 'default' case should be the last case in a switch statement");
+
+  static const ParserErrorCode SWITCH_HAS_MULTIPLE_DEFAULT_CASES =
+      const ParserErrorCode('SWITCH_HAS_MULTIPLE_DEFAULT_CASES',
+          "The 'default' case can only be declared once");
+
+  static const ParserErrorCode TOP_LEVEL_OPERATOR = const ParserErrorCode(
+      'TOP_LEVEL_OPERATOR', "Operators must be declared within a class");
+
+  static const ParserErrorCode TYPEDEF_IN_CLASS = const ParserErrorCode(
+      'TYPEDEF_IN_CLASS',
+      "Function type aliases cannot be declared inside classes");
+
+  static const ParserErrorCode UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP =
+      const ParserErrorCode('UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP',
+          "There is no '{0}' to open a parameter group");
+
+  static const ParserErrorCode UNEXPECTED_TOKEN =
+      const ParserErrorCode('UNEXPECTED_TOKEN', "Unexpected token '{0}'");
+
+  static const ParserErrorCode WITH_BEFORE_EXTENDS = const ParserErrorCode(
+      'WITH_BEFORE_EXTENDS',
+      "The extends clause must be before the with clause");
+
+  static const ParserErrorCode WITH_WITHOUT_EXTENDS = const ParserErrorCode(
+      'WITH_WITHOUT_EXTENDS',
+      "The with clause cannot be used without an extends clause");
+
+  static const ParserErrorCode WRONG_SEPARATOR_FOR_NAMED_PARAMETER =
+      const ParserErrorCode('WRONG_SEPARATOR_FOR_NAMED_PARAMETER',
+          "The default value of a named parameter should be preceeded by ':'");
+
+  static const ParserErrorCode WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER =
+      const ParserErrorCode('WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER',
+          "The default value of a positional parameter should be preceeded by '='");
+
+  static const ParserErrorCode WRONG_TERMINATOR_FOR_PARAMETER_GROUP =
+      const ParserErrorCode('WRONG_TERMINATOR_FOR_PARAMETER_GROUP',
+          "Expected '{0}' to close parameter group");
+
+  static const ParserErrorCode VAR_AND_TYPE = const ParserErrorCode(
+      'VAR_AND_TYPE',
+      "Variables cannot be declared using both 'var' and a type name; remove the 'var'");
+
+  static const ParserErrorCode VAR_AS_TYPE_NAME = const ParserErrorCode(
+      'VAR_AS_TYPE_NAME', "The keyword 'var' cannot be used as a type name");
+
+  static const ParserErrorCode VAR_CLASS = const ParserErrorCode(
+      'VAR_CLASS', "Classes cannot be declared to be 'var'");
+
+  static const ParserErrorCode VAR_ENUM =
+      const ParserErrorCode('VAR_ENUM', "Enums cannot be declared to be 'var'");
+
+  static const ParserErrorCode VAR_RETURN_TYPE = const ParserErrorCode(
+      'VAR_RETURN_TYPE', "The return type cannot be 'var'");
+
+  static const ParserErrorCode VAR_TYPEDEF = const ParserErrorCode(
+      'VAR_TYPEDEF', "Type aliases cannot be declared to be 'var'");
+
+  static const ParserErrorCode VOID_PARAMETER = const ParserErrorCode(
+      'VOID_PARAMETER', "Parameters cannot have a type of 'void'");
+
+  static const ParserErrorCode VOID_VARIABLE = const ParserErrorCode(
+      'VOID_VARIABLE', "Variables cannot have a type of 'void'");
+
+  /**
+   * Initialize a newly created error code to have the given [name]. The message
+   * associated with the error will be created from the given [message]
+   * template. The correction associated with the error will be created from the
+   * given [correction] template.
+   */
+  const ParserErrorCode(String name, String message, [String correction])
+      : super(name, message, correction);
+
+  @override
+  ErrorSeverity get errorSeverity => ErrorSeverity.ERROR;
+
+  @override
+  ErrorType get type => ErrorType.SYNTACTIC_ERROR;
+}
+
+/**
+ * The error codes used for errors detected by the scanner.
+ */
+class ScannerErrorCode extends ErrorCode {
+  static const ScannerErrorCode ILLEGAL_CHARACTER =
+      const ScannerErrorCode('ILLEGAL_CHARACTER', "Illegal character {0}");
+
+  static const ScannerErrorCode MISSING_DIGIT =
+      const ScannerErrorCode('MISSING_DIGIT', "Decimal digit expected");
+
+  static const ScannerErrorCode MISSING_HEX_DIGIT =
+      const ScannerErrorCode('MISSING_HEX_DIGIT', "Hexidecimal digit expected");
+
+  static const ScannerErrorCode MISSING_QUOTE =
+      const ScannerErrorCode('MISSING_QUOTE', "Expected quote (' or \")");
+
+  static const ScannerErrorCode UNABLE_GET_CONTENT = const ScannerErrorCode(
+      'UNABLE_GET_CONTENT', "Unable to get content: {0}");
+
+  static const ScannerErrorCode UNTERMINATED_MULTI_LINE_COMMENT =
+      const ScannerErrorCode(
+          'UNTERMINATED_MULTI_LINE_COMMENT', "Unterminated multi-line comment");
+
+  static const ScannerErrorCode UNTERMINATED_STRING_LITERAL =
+      const ScannerErrorCode(
+          'UNTERMINATED_STRING_LITERAL', "Unterminated string literal");
+
+  /**
+   * Initialize a newly created error code to have the given [name]. The message
+   * associated with the error will be created from the given [message]
+   * template. The correction associated with the error will be created from the
+   * given [correction] template.
+   */
+  const ScannerErrorCode(String name, String message, [String correction])
+      : super(name, message, correction);
+
+  @override
+  ErrorSeverity get errorSeverity => ErrorSeverity.ERROR;
+
+  @override
+  ErrorType get type => ErrorType.SYNTACTIC_ERROR;
+}
diff --git a/pkg/analyzer/lib/src/dart/scanner/scanner.dart b/pkg/analyzer/lib/src/dart/scanner/scanner.dart
index 4ea8f2c..3c74e78 100644
--- a/pkg/analyzer/lib/src/dart/scanner/scanner.dart
+++ b/pkg/analyzer/lib/src/dart/scanner/scanner.dart
@@ -8,11 +8,14 @@
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/dart/error/syntactic_errors.dart';
 import 'package:analyzer/src/dart/scanner/reader.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:charcode/ascii.dart';
 
+export 'package:analyzer/src/dart/error/syntactic_errors.dart';
+
 /**
  * A state in a state machine used to scan keywords.
  */
@@ -1350,46 +1353,3 @@
         StringUtilities.startsWith3(value, 0, $slash, $asterisk, $asterisk);
   }
 }
-
-/**
- * The error codes used for errors detected by the scanner.
- */
-class ScannerErrorCode extends ErrorCode {
-  static const ScannerErrorCode ILLEGAL_CHARACTER =
-      const ScannerErrorCode('ILLEGAL_CHARACTER', "Illegal character {0}");
-
-  static const ScannerErrorCode MISSING_DIGIT =
-      const ScannerErrorCode('MISSING_DIGIT', "Decimal digit expected");
-
-  static const ScannerErrorCode MISSING_HEX_DIGIT =
-      const ScannerErrorCode('MISSING_HEX_DIGIT', "Hexidecimal digit expected");
-
-  static const ScannerErrorCode MISSING_QUOTE =
-      const ScannerErrorCode('MISSING_QUOTE', "Expected quote (' or \")");
-
-  static const ScannerErrorCode UNABLE_GET_CONTENT = const ScannerErrorCode(
-      'UNABLE_GET_CONTENT', "Unable to get content: {0}");
-
-  static const ScannerErrorCode UNTERMINATED_MULTI_LINE_COMMENT =
-      const ScannerErrorCode(
-          'UNTERMINATED_MULTI_LINE_COMMENT', "Unterminated multi-line comment");
-
-  static const ScannerErrorCode UNTERMINATED_STRING_LITERAL =
-      const ScannerErrorCode(
-          'UNTERMINATED_STRING_LITERAL', "Unterminated string literal");
-
-  /**
-   * Initialize a newly created error code to have the given [name]. The message
-   * associated with the error will be created from the given [message]
-   * template. The correction associated with the error will be created from the
-   * given [correction] template.
-   */
-  const ScannerErrorCode(String name, String message, [String correction])
-      : super(name, message, correction);
-
-  @override
-  ErrorSeverity get errorSeverity => ErrorSeverity.ERROR;
-
-  @override
-  ErrorType get type => ErrorType.SYNTACTIC_ERROR;
-}
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index d87b593..06d6ae3 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -2204,6 +2204,19 @@
  */
 class HintCode extends ErrorCode {
   /**
+   * When an abstract supertype member is references with `super` as its target,
+   * it cannot be overridden, so it is always a runtime error.
+   *
+   * Parameters:
+   * 0: the display name for the kind of the referenced element
+   * 1: the name of the referenced element
+   */
+  static const HintCode ABSTRACT_SUPER_MEMBER_REFERENCE = const HintCode(
+      'ABSTRACT_SUPER_MEMBER_REFERENCE',
+      "The {0} '{1}' is always abstract in the supertype.",
+      null);
+
+  /**
    * This hint is generated anywhere where the
    * [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE] would have been generated,
    * if we used propagated information for the warnings.
@@ -4668,6 +4681,9 @@
   static const StrongModeCode DOWN_CAST_IMPLICIT = const StrongModeCode(
       ErrorType.HINT, 'DOWN_CAST_IMPLICIT', _implicitCastMessage);
 
+  static const StrongModeCode DOWN_CAST_IMPLICIT_ASSIGN = const StrongModeCode(
+      ErrorType.HINT, 'DOWN_CAST_IMPLICIT_ASSIGN', _implicitCastMessage);
+
   static const StrongModeCode DYNAMIC_CAST = const StrongModeCode(
       ErrorType.HINT, 'DYNAMIC_CAST', _implicitCastMessage);
 
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index ba6c884..b61eb2b 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -7,6 +7,7 @@
 import 'dart:collection';
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/syntactic_entity.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -1618,6 +1619,7 @@
    * invoked using the call operator '()'.
    */
   bool _isExecutableType(DartType type) {
+    type = type?.resolveToBound(_resolver.typeProvider.objectType);
     if (type.isDynamic || type is FunctionType) {
       return true;
     } else if (!_enableStrictCallChecks &&
@@ -1989,7 +1991,7 @@
             element2.lookUpGetter(name3, _definingLibrary);
         if (getter != null) {
           nameNode3.staticElement = getter;
-          annotation.element = element2;
+          annotation.element = getter;
           _resolveAnnotationElementGetter(annotation, getter);
           return;
         }
@@ -2612,7 +2614,7 @@
   Element get bestElement => null;
 
   @override
-  Iterable get childEntities {
+  Iterable<SyntacticEntity> get childEntities {
     // Should never be called, since a SyntheticIdentifier never appears in the
     // AST--it is just used for lookup.
     assert(false);
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index d4064c4..01b2ced 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -19,7 +19,6 @@
 import 'package:analyzer/src/context/cache.dart';
 import 'package:analyzer/src/context/context.dart';
 import 'package:analyzer/src/generated/constant.dart';
-import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -950,19 +949,21 @@
 /**
  * The levels at which a source can be analyzed.
  */
-class AnalysisLevel extends Enum<AnalysisLevel> {
+class AnalysisLevel implements Comparable<AnalysisLevel> {
   /**
    * Indicates a source should be fully analyzed.
    */
   static const AnalysisLevel ALL = const AnalysisLevel('ALL', 0);
 
   /**
-   * Indicates a source should be resolved and that errors, warnings and hints are needed.
+   * Indicates a source should be resolved and that errors, warnings and hints
+   * are needed.
    */
   static const AnalysisLevel ERRORS = const AnalysisLevel('ERRORS', 1);
 
   /**
-   * Indicates a source should be resolved, but that errors, warnings and hints are not needed.
+   * Indicates a source should be resolved, but that errors, warnings and hints
+   * are not needed.
    */
   static const AnalysisLevel RESOLVED = const AnalysisLevel('RESOLVED', 2);
 
@@ -973,7 +974,26 @@
 
   static const List<AnalysisLevel> values = const [ALL, ERRORS, RESOLVED, NONE];
 
-  const AnalysisLevel(String name, int ordinal) : super(name, ordinal);
+  /**
+   * The name of this analysis level.
+   */
+  final String name;
+
+  /**
+   * The ordinal value of the analysis level.
+   */
+  final int ordinal;
+
+  const AnalysisLevel(this.name, this.ordinal);
+
+  @override
+  int get hashCode => ordinal;
+
+  @override
+  int compareTo(AnalysisLevel other) => ordinal - other.ordinal;
+
+  @override
+  String toString() => name;
 }
 
 /**
@@ -1065,6 +1085,7 @@
   /**
    * Return `true` to if analysis is to enable async support.
    */
+  @deprecated
   bool get enableAsync;
 
   /**
@@ -1198,12 +1219,11 @@
   static const int DEFAULT_CACHE_SIZE = 64;
 
   static const int ENABLE_ASSERT_FLAG = 0x01;
-  static const int ENABLE_ASYNC_FLAG = 0x02;
-  static const int ENABLE_GENERIC_METHODS_FLAG = 0x04;
-  static const int ENABLE_STRICT_CALL_CHECKS_FLAG = 0x08;
-  static const int ENABLE_STRONG_MODE_FLAG = 0x10;
-  static const int ENABLE_STRONG_MODE_HINTS_FLAG = 0x20;
-  static const int ENABLE_SUPER_MIXINS_FLAG = 0x40;
+  static const int ENABLE_GENERIC_METHODS_FLAG = 0x02;
+  static const int ENABLE_STRICT_CALL_CHECKS_FLAG = 0x04;
+  static const int ENABLE_STRONG_MODE_FLAG = 0x08;
+  static const int ENABLE_STRONG_MODE_HINTS_FLAG = 0x10;
+  static const int ENABLE_SUPER_MIXINS_FLAG = 0x20;
 
   /**
    * The default list of non-nullable type names.
@@ -1230,9 +1250,6 @@
   bool enableAssertMessage = false;
 
   @override
-  bool enableAsync = true;
-
-  @override
   bool enableGenericMethods = false;
 
   @override
@@ -1333,7 +1350,6 @@
     dart2jsHint = options.dart2jsHint;
     enableAssertInitializer = options.enableAssertInitializer;
     enableAssertMessage = options.enableAssertMessage;
-    enableAsync = options.enableAsync;
     enableStrictCallChecks = options.enableStrictCallChecks;
     enableGenericMethods = options.enableGenericMethods;
     enableInitializingFormalAccess = options.enableInitializingFormalAccess;
@@ -1388,6 +1404,13 @@
     _analyzeFunctionBodiesPredicate = value;
   }
 
+  @deprecated
+  @override
+  bool get enableAsync => true;
+
+  @deprecated
+  void set enableAsync(bool enable) {}
+
   /**
    * A flag indicating whether interface libraries are to be supported (DEP 40).
    */
@@ -1399,7 +1422,6 @@
   @override
   int encodeCrossContextOptions() =>
       (enableAssertMessage ? ENABLE_ASSERT_FLAG : 0) |
-      (enableAsync ? ENABLE_ASYNC_FLAG : 0) |
       (enableGenericMethods ? ENABLE_GENERIC_METHODS_FLAG : 0) |
       (enableStrictCallChecks ? ENABLE_STRICT_CALL_CHECKS_FLAG : 0) |
       (strongMode ? ENABLE_STRONG_MODE_FLAG : 0) |
@@ -1409,7 +1431,6 @@
   @override
   void setCrossContextOptionsFrom(AnalysisOptions options) {
     enableAssertMessage = options.enableAssertMessage;
-    enableAsync = options.enableAsync;
     enableGenericMethods = options.enableGenericMethods;
     enableStrictCallChecks = options.enableStrictCallChecks;
     enableSuperMixins = options.enableSuperMixins;
@@ -1441,9 +1462,6 @@
     if (encoding & ENABLE_ASSERT_FLAG > 0) {
       add('assert');
     }
-    if (encoding & ENABLE_ASYNC_FLAG > 0) {
-      add('async');
-    }
     if (encoding & ENABLE_GENERIC_METHODS_FLAG > 0) {
       add('genericMethods');
     }
@@ -1580,7 +1598,7 @@
 /**
  * The possible states of cached data.
  */
-class CacheState extends Enum<CacheState> {
+class CacheState implements Comparable<CacheState> {
   /**
    * The data is not in the cache and the last time an attempt was made to
    * compute the data an exception occurred, making it pointless to attempt to
@@ -1641,7 +1659,26 @@
     VALID
   ];
 
-  const CacheState(String name, int ordinal) : super(name, ordinal);
+  /**
+   * The name of this cache state.
+   */
+  final String name;
+
+  /**
+   * The ordinal value of the cache state.
+   */
+  final int ordinal;
+
+  const CacheState(this.name, this.ordinal);
+
+  @override
+  int get hashCode => ordinal;
+
+  @override
+  int compareTo(CacheState other) => ordinal - other.ordinal;
+
+  @override
+  String toString() => name;
 }
 
 /**
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 47a4979..13964ba 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -2656,7 +2656,7 @@
         overriddenMember = _enclosingClass.lookUpInheritedConcreteMethod(
             memberName, _currentLibrary);
       }
-      if (overriddenMember == null && !_hasNoSuchMethod(_enclosingClass)) {
+      if (overriddenMember == null && !_enclosingClass.hasNoSuchMethod) {
         _errorReporter.reportErrorForNode(
             StaticWarningCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER,
             nameNode,
@@ -4971,7 +4971,7 @@
       SimpleIdentifier classNameNode) {
     if (_enclosingClass.isAbstract) {
       return;
-    } else if (_hasNoSuchMethod(_enclosingClass)) {
+    } else if (_enclosingClass.hasNoSuchMethod) {
       return;
     }
     //
@@ -6098,7 +6098,7 @@
     }
     // If there is a noSuchMethod method, then don't report the warning,
     // see dartbug.com/16078
-    if (_hasNoSuchMethod(classElement)) {
+    if (_enclosingClass.hasNoSuchMethod) {
       return;
     }
     ExecutableElement callMethod = _inheritanceManager.lookupMember(
@@ -6361,16 +6361,24 @@
   }
 
   ExecutableElement _getOverriddenMember(Element member) {
-    if (member == null || _inheritanceManager == null) {
+    if (member == null) {
       return null;
     }
-
     ClassElement classElement =
         member.getAncestor((element) => element is ClassElement);
     if (classElement == null) {
       return null;
     }
-    return _inheritanceManager.lookupInheritance(classElement, member.name);
+    String name = member.name;
+    ClassElement superclass = classElement.supertype?.element;
+    while (superclass != null) {
+      ExecutableElement member = superclass.getMethod(name) ?? superclass.getGetter(name) ?? superclass.getSetter(name);
+      if (member != null) {
+        return member;
+      }
+      superclass = superclass.supertype?.element;
+    }
+    return null;
   }
 
   /**
@@ -6387,22 +6395,6 @@
   }
 
   /**
-   * Return `true` if the given [classElement] has a noSuchMethod() method
-   * distinct from the one declared in class Object, as per the Dart Language
-   * Specification (section 10.4).
-   */
-  bool _hasNoSuchMethod(ClassElement classElement) {
-    MethodElement method = classElement.lookUpMethod(
-        FunctionElement.NO_SUCH_METHOD_METHOD_NAME, classElement.library);
-    if (method == null) {
-      return false;
-    }
-    ClassElement definingClass =
-        method.getAncestor((Element element) => element is ClassElement);
-    return definingClass != null && !definingClass.type.isObject;
-  }
-
-  /**
    * Return `true` if the given [constructor] redirects to itself, directly or
    * indirectly.
    */
diff --git a/pkg/analyzer/lib/src/generated/java_core.dart b/pkg/analyzer/lib/src/generated/java_core.dart
index ed0d03f..edaccce 100644
--- a/pkg/analyzer/lib/src/generated/java_core.dart
+++ b/pkg/analyzer/lib/src/generated/java_core.dart
@@ -125,6 +125,7 @@
   }
 }
 
+@deprecated
 abstract class Enum<E extends Enum> implements Comparable<E> {
   /// The name of this enum constant, as declared in the enum declaration.
   final String name;
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index 182b2a0..fb111ff 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -13,6 +13,7 @@
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/dart/error/syntactic_errors.dart';
 import 'package:analyzer/src/dart/scanner/reader.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/error/codes.dart';
@@ -23,6 +24,7 @@
 import 'package:analyzer/src/generated/utilities_dart.dart';
 
 export 'package:analyzer/src/dart/ast/utilities.dart' show ResolutionCopier;
+export 'package:analyzer/src/dart/error/syntactic_errors.dart';
 
 /**
  * A simple data-holder for a method that needs to return multiple values.
@@ -70,36 +72,6 @@
 }
 
 /**
- * Wrapper around [Function] which should be called with "target" and
- * "arguments".
- */
-class MethodTrampoline {
-  int parameterCount;
-  Function trampoline;
-  MethodTrampoline(this.parameterCount, this.trampoline);
-  Object invoke(target, List arguments) {
-    if (arguments.length != parameterCount) {
-      throw new ArgumentError("${arguments.length} != $parameterCount");
-    }
-    switch (parameterCount) {
-      case 0:
-        return trampoline(target);
-      case 1:
-        return trampoline(target, arguments[0]);
-      case 2:
-        return trampoline(target, arguments[0], arguments[1]);
-      case 3:
-        return trampoline(target, arguments[0], arguments[1], arguments[2]);
-      case 4:
-        return trampoline(
-            target, arguments[0], arguments[1], arguments[2], arguments[3]);
-      default:
-        throw new ArgumentError("Not implemented for > 4 arguments");
-    }
-  }
-}
-
-/**
  * A simple data-holder for a method that needs to return multiple values.
  */
 class Modifiers {
@@ -226,11 +198,6 @@
   bool _enableNnbd = false;
 
   /**
-   * A flag indicating whether the parser is to parse the async support.
-   */
-  bool _parseAsync = true;
-
-  /**
    * A flag indicating whether parser is to parse function bodies.
    */
   bool _parseFunctionBodies = true;
@@ -342,10 +309,11 @@
 
   /**
    * Set whether the parser is to parse the async support.
+   *
+   * Support for removing the 'async' library has been removed.
    */
-  void set parseAsync(bool parseAsync) {
-    this._parseAsync = parseAsync;
-  }
+  @deprecated
+  void set parseAsync(bool parseAsync) {}
 
   @deprecated
   bool get parseConditionalDirectives => true;
@@ -2754,6 +2722,7 @@
   ExtendsClause parseExtendsClause() {
     Token keyword = getAndAdvance();
     TypeName superclass = parseTypeName(false);
+    _mustNotBeNullable(superclass, ParserErrorCode.NULLABLE_TYPE_IN_EXTENDS);
     return new ExtendsClause(keyword, superclass);
   }
 
@@ -3067,9 +3036,6 @@
         if (lexeme == ASYNC) {
           foundAsync = true;
           keyword = getAndAdvance();
-          if (!_parseAsync) {
-            _reportErrorForToken(ParserErrorCode.ASYNC_NOT_SUPPORTED, keyword);
-          }
           if (_matches(TokenType.STAR)) {
             star = getAndAdvance();
             _inGenerator = true;
@@ -3079,9 +3045,6 @@
         } else if (lexeme == SYNC) {
           foundSync = true;
           keyword = getAndAdvance();
-          if (!_parseAsync) {
-            _reportErrorForToken(ParserErrorCode.ASYNC_NOT_SUPPORTED, keyword);
-          }
           if (_matches(TokenType.STAR)) {
             star = getAndAdvance();
             _inGenerator = true;
@@ -3371,10 +3334,11 @@
   ImplementsClause parseImplementsClause() {
     Token keyword = getAndAdvance();
     List<TypeName> interfaces = <TypeName>[];
-    interfaces.add(parseTypeName(false));
-    while (_optional(TokenType.COMMA)) {
-      interfaces.add(parseTypeName(false));
-    }
+    do {
+      TypeName typeName = parseTypeName(false);
+      _mustNotBeNullable(typeName, ParserErrorCode.NULLABLE_TYPE_IN_IMPLEMENTS);
+      interfaces.add(typeName);
+    } while (_optional(TokenType.COMMA));
     return new ImplementsClause(keyword, interfaces);
   }
 
@@ -4937,6 +4901,10 @@
   TypeParameter parseTypeParameter() {
     CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
     SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true);
+    if (_matches(TokenType.QUESTION)) {
+      _reportErrorForCurrentToken(ParserErrorCode.NULLABLE_TYPE_PARAMETER);
+      _advance();
+    }
     if (_matchesKeyword(Keyword.EXTENDS)) {
       Token keyword = getAndAdvance();
       TypeName bound = parseTypeName(false);
@@ -5170,10 +5138,12 @@
    */
   WithClause parseWithClause() {
     Token withKeyword = getAndAdvance();
-    List<TypeName> types = <TypeName>[parseTypeName(false)];
-    while (_optional(TokenType.COMMA)) {
-      types.add(parseTypeName(false));
-    }
+    List<TypeName> types = <TypeName>[];
+    do {
+      TypeName typeName = parseTypeName(false);
+      _mustNotBeNullable(typeName, ParserErrorCode.NULLABLE_TYPE_IN_WITH);
+      types.add(typeName);
+    } while (_optional(TokenType.COMMA));
     return new WithClause(withKeyword, types);
   }
 
@@ -5372,25 +5342,24 @@
   }
 
   /**
-   * Append the character equivalent of the given [scalarValue] to the given
+   * Append the character equivalent of the given [codePoint] to the given
    * [builder]. Use the [startIndex] and [endIndex] to report an error, and
-   * don't append anything to the builder, if the scalar value is invalid. The
+   * don't append anything to the builder, if the code point is invalid. The
    * [escapeSequence] is the escape sequence that was parsed to produce the
-   * scalar value (used for error reporting).
+   * code point (used for error reporting).
    */
-  void _appendScalarValue(StringBuffer buffer, String escapeSequence,
-      int scalarValue, int startIndex, int endIndex) {
-    if (scalarValue < 0 ||
-        scalarValue > Character.MAX_CODE_POINT ||
-        (scalarValue >= 0xD800 && scalarValue <= 0xDFFF)) {
+  void _appendCodePoint(StringBuffer buffer, String source, int codePoint,
+      int startIndex, int endIndex) {
+    if (codePoint < 0 || codePoint > Character.MAX_CODE_POINT) {
+      String escapeSequence = source.substring(startIndex, endIndex + 1);
       _reportErrorForCurrentToken(
           ParserErrorCode.INVALID_CODE_POINT, [escapeSequence]);
       return;
     }
-    if (scalarValue < Character.MAX_VALUE) {
-      buffer.writeCharCode(scalarValue);
+    if (codePoint < Character.MAX_VALUE) {
+      buffer.writeCharCode(codePoint);
     } else {
-      buffer.write(Character.toChars(scalarValue));
+      buffer.write(Character.toChars(codePoint));
     }
   }
 
@@ -5964,6 +5933,16 @@
       _currentToken.lexeme == identifier;
 
   /**
+   * Report an error with the given [errorCode] if the given [typeName] has been
+   * marked as nullable.
+   */
+  void _mustNotBeNullable(TypeName typeName, ParserErrorCode errorCode) {
+    if (typeName.question != null) {
+      _reportErrorForToken(errorCode, typeName.question);
+    }
+  }
+
+  /**
    * If the current token has the given [type], then advance to the next token
    * and return `true`. Otherwise, return `false` without advancing. This method
    * should not be invoked with an argument value of [TokenType.GT].
@@ -7315,7 +7294,6 @@
     parser._inInitializer = _inInitializer;
     parser._inLoop = _inLoop;
     parser._inSwitch = _inSwitch;
-    parser._parseAsync = _parseAsync;
     parser._parseFunctionBodies = _parseFunctionBodies;
     try {
       parseOperation(parser);
@@ -7740,8 +7718,7 @@
           // Illegal escape sequence: not enough or too many hex digits
           _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE);
         }
-        _appendScalarValue(buffer, lexeme.substring(index, currentIndex + 1),
-            value, index, currentIndex);
+        _appendCodePoint(buffer, lexeme, value, index, currentIndex);
         return currentIndex + 1;
       } else {
         if (currentIndex + 3 >= length) {
@@ -7760,9 +7737,9 @@
           // Illegal escape sequence: invalid hex digits
           _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE);
         } else {
-          _appendScalarValue(
+          _appendCodePoint(
               buffer,
-              lexeme.substring(index, currentIndex + 1),
+              lexeme,
               (((((Character.digit(firstDigit, 16) << 4) +
                                   Character.digit(secondDigit, 16)) <<
                               4) +
@@ -8129,640 +8106,3 @@
   @override
   Token copy() => new Parser_SyntheticKeywordToken(keyword, offset);
 }
-
-/**
- * The error codes used for errors detected by the parser. The convention for
- * this class is for the name of the error code to indicate the problem that
- * caused the error to be generated and for the error message to explain what
- * is wrong and, when appropriate, how the problem can be corrected.
- */
-class ParserErrorCode extends ErrorCode {
-  static const ParserErrorCode ABSTRACT_CLASS_MEMBER = const ParserErrorCode(
-      'ABSTRACT_CLASS_MEMBER',
-      "Members of classes cannot be declared to be 'abstract'");
-
-  static const ParserErrorCode ABSTRACT_ENUM = const ParserErrorCode(
-      'ABSTRACT_ENUM', "Enums cannot be declared to be 'abstract'");
-
-  static const ParserErrorCode ABSTRACT_STATIC_METHOD = const ParserErrorCode(
-      'ABSTRACT_STATIC_METHOD',
-      "Static methods cannot be declared to be 'abstract'");
-
-  static const ParserErrorCode ABSTRACT_TOP_LEVEL_FUNCTION =
-      const ParserErrorCode('ABSTRACT_TOP_LEVEL_FUNCTION',
-          "Top-level functions cannot be declared to be 'abstract'");
-
-  static const ParserErrorCode ABSTRACT_TOP_LEVEL_VARIABLE =
-      const ParserErrorCode('ABSTRACT_TOP_LEVEL_VARIABLE',
-          "Top-level variables cannot be declared to be 'abstract'");
-
-  static const ParserErrorCode ABSTRACT_TYPEDEF = const ParserErrorCode(
-      'ABSTRACT_TYPEDEF', "Type aliases cannot be declared to be 'abstract'");
-
-  static const ParserErrorCode ANNOTATION_ON_ENUM_CONSTANT =
-      const ParserErrorCode('ANNOTATION_ON_ENUM_CONSTANT',
-          "Enum constants cannot have annotations");
-
-  /**
-   * 16.32 Identifier Reference: It is a compile-time error if any of the
-   * identifiers async, await, or yield is used as an identifier in a function
-   * body marked with either async, async*, or sync*.
-   */
-  static const ParserErrorCode ASYNC_KEYWORD_USED_AS_IDENTIFIER =
-      const ParserErrorCode('ASYNC_KEYWORD_USED_AS_IDENTIFIER',
-          "The keywords 'async', 'await', and 'yield' may not be used as identifiers in an asynchronous or generator function.");
-
-  /**
-   * Some environments, such as Fletch, do not support async.
-   */
-  static const ParserErrorCode ASYNC_NOT_SUPPORTED = const ParserErrorCode(
-      'ASYNC_NOT_SUPPORTED',
-      "Async and sync are not supported in this environment.");
-
-  static const ParserErrorCode BREAK_OUTSIDE_OF_LOOP = const ParserErrorCode(
-      'BREAK_OUTSIDE_OF_LOOP',
-      "A break statement cannot be used outside of a loop or switch statement");
-
-  static const ParserErrorCode CLASS_IN_CLASS = const ParserErrorCode(
-      'CLASS_IN_CLASS',
-      "Classes can't be declared inside other classes.",
-      "Try moving the class to the top-level.");
-
-  static const ParserErrorCode COLON_IN_PLACE_OF_IN = const ParserErrorCode(
-      'COLON_IN_PLACE_OF_IN', "For-in loops use 'in' rather than a colon");
-
-  static const ParserErrorCode CONST_AND_FINAL = const ParserErrorCode(
-      'CONST_AND_FINAL',
-      "Members can't be declared to be both 'const' and 'final'.",
-      "Try removing either the 'const' or 'final' keyword.");
-
-  static const ParserErrorCode CONST_AND_VAR = const ParserErrorCode(
-      'CONST_AND_VAR',
-      "Members can't be declared to be both 'const' and 'var'.",
-      "Try removing either the 'const' or 'var' keyword.");
-
-  static const ParserErrorCode CONST_CLASS = const ParserErrorCode(
-      'CONST_CLASS',
-      "Classes can't be declared to be 'const'.",
-      "Try removing the 'const' keyword or moving to the class' constructor(s).");
-
-  static const ParserErrorCode CONST_CONSTRUCTOR_WITH_BODY =
-      const ParserErrorCode(
-          'CONST_CONSTRUCTOR_WITH_BODY',
-          "Const constructor can't have a body.",
-          "Try removing the 'const' keyword or the body.");
-
-  static const ParserErrorCode CONST_ENUM = const ParserErrorCode(
-      'CONST_ENUM',
-      "Enums can't be declared to be 'const'.",
-      "Try removing the 'const' keyword.");
-
-  static const ParserErrorCode CONST_FACTORY = const ParserErrorCode(
-      'CONST_FACTORY',
-      "Only redirecting factory constructors can be declared to be 'const'.",
-      "Try removing the 'const' keyword or replacing the body with '=' followed by a valid target.");
-
-  static const ParserErrorCode CONST_METHOD = const ParserErrorCode(
-      'CONST_METHOD',
-      "Getters, setters and methods can't be declared to be 'const'.",
-      "Try removing the 'const' keyword.");
-
-  static const ParserErrorCode CONST_TYPEDEF = const ParserErrorCode(
-      'CONST_TYPEDEF',
-      "Type aliases can't be declared to be 'const'.",
-      "Try removing the 'const' keyword.");
-
-  static const ParserErrorCode CONSTRUCTOR_WITH_RETURN_TYPE =
-      const ParserErrorCode(
-          'CONSTRUCTOR_WITH_RETURN_TYPE',
-          "Constructors can't have a return type.",
-          "Try removing the return type.");
-
-  static const ParserErrorCode CONTINUE_OUTSIDE_OF_LOOP = const ParserErrorCode(
-      'CONTINUE_OUTSIDE_OF_LOOP',
-      "A continue statement cannot be used outside of a loop or switch statement");
-
-  static const ParserErrorCode CONTINUE_WITHOUT_LABEL_IN_CASE =
-      const ParserErrorCode('CONTINUE_WITHOUT_LABEL_IN_CASE',
-          "A continue statement in a switch statement must have a label as a target");
-
-  static const ParserErrorCode DEPRECATED_CLASS_TYPE_ALIAS =
-      const ParserErrorCode('DEPRECATED_CLASS_TYPE_ALIAS',
-          "The 'typedef' mixin application was replaced with 'class'");
-
-  static const ParserErrorCode DIRECTIVE_AFTER_DECLARATION =
-      const ParserErrorCode('DIRECTIVE_AFTER_DECLARATION',
-          "Directives must appear before any declarations");
-
-  static const ParserErrorCode DUPLICATE_LABEL_IN_SWITCH_STATEMENT =
-      const ParserErrorCode('DUPLICATE_LABEL_IN_SWITCH_STATEMENT',
-          "The label {0} was already used in this switch statement");
-
-  static const ParserErrorCode DUPLICATED_MODIFIER = const ParserErrorCode(
-      'DUPLICATED_MODIFIER', "The modifier '{0}' was already specified.");
-
-  static const ParserErrorCode EMPTY_ENUM_BODY = const ParserErrorCode(
-      'EMPTY_ENUM_BODY', "An enum must declare at least one constant name");
-
-  static const ParserErrorCode ENUM_IN_CLASS = const ParserErrorCode(
-      'ENUM_IN_CLASS', "Enums cannot be declared inside classes");
-
-  static const ParserErrorCode EQUALITY_CANNOT_BE_EQUALITY_OPERAND =
-      const ParserErrorCode('EQUALITY_CANNOT_BE_EQUALITY_OPERAND',
-          "Equality expression cannot be operand of another equality expression.");
-
-  static const ParserErrorCode EXPECTED_CASE_OR_DEFAULT = const ParserErrorCode(
-      'EXPECTED_CASE_OR_DEFAULT', "Expected 'case' or 'default'");
-
-  static const ParserErrorCode EXPECTED_CLASS_MEMBER =
-      const ParserErrorCode('EXPECTED_CLASS_MEMBER', "Expected a class member");
-
-  static const ParserErrorCode EXPECTED_EXECUTABLE = const ParserErrorCode(
-      'EXPECTED_EXECUTABLE',
-      "Expected a method, getter, setter or operator declaration");
-
-  static const ParserErrorCode EXPECTED_LIST_OR_MAP_LITERAL =
-      const ParserErrorCode(
-          'EXPECTED_LIST_OR_MAP_LITERAL', "Expected a list or map literal");
-
-  static const ParserErrorCode EXPECTED_STRING_LITERAL = const ParserErrorCode(
-      'EXPECTED_STRING_LITERAL', "Expected a string literal");
-
-  static const ParserErrorCode EXPECTED_TOKEN =
-      const ParserErrorCode('EXPECTED_TOKEN', "Expected to find '{0}'");
-
-  static const ParserErrorCode EXPECTED_TYPE_NAME =
-      const ParserErrorCode('EXPECTED_TYPE_NAME', "Expected a type name");
-
-  static const ParserErrorCode EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE =
-      const ParserErrorCode('EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE',
-          "Export directives must preceed part directives");
-
-  static const ParserErrorCode EXTERNAL_AFTER_CONST = const ParserErrorCode(
-      'EXTERNAL_AFTER_CONST',
-      "The modifier 'external' should be before the modifier 'const'");
-
-  static const ParserErrorCode EXTERNAL_AFTER_FACTORY = const ParserErrorCode(
-      'EXTERNAL_AFTER_FACTORY',
-      "The modifier 'external' should be before the modifier 'factory'");
-
-  static const ParserErrorCode EXTERNAL_AFTER_STATIC = const ParserErrorCode(
-      'EXTERNAL_AFTER_STATIC',
-      "The modifier 'external' should be before the modifier 'static'");
-
-  static const ParserErrorCode EXTERNAL_CLASS = const ParserErrorCode(
-      'EXTERNAL_CLASS', "Classes cannot be declared to be 'external'");
-
-  static const ParserErrorCode EXTERNAL_CONSTRUCTOR_WITH_BODY =
-      const ParserErrorCode('EXTERNAL_CONSTRUCTOR_WITH_BODY',
-          "External constructors cannot have a body");
-
-  static const ParserErrorCode EXTERNAL_ENUM = const ParserErrorCode(
-      'EXTERNAL_ENUM', "Enums cannot be declared to be 'external'");
-
-  static const ParserErrorCode EXTERNAL_FIELD = const ParserErrorCode(
-      'EXTERNAL_FIELD', "Fields cannot be declared to be 'external'");
-
-  static const ParserErrorCode EXTERNAL_GETTER_WITH_BODY =
-      const ParserErrorCode(
-          'EXTERNAL_GETTER_WITH_BODY', "External getters cannot have a body");
-
-  static const ParserErrorCode EXTERNAL_METHOD_WITH_BODY =
-      const ParserErrorCode(
-          'EXTERNAL_METHOD_WITH_BODY', "External methods cannot have a body");
-
-  static const ParserErrorCode EXTERNAL_OPERATOR_WITH_BODY =
-      const ParserErrorCode('EXTERNAL_OPERATOR_WITH_BODY',
-          "External operators cannot have a body");
-
-  static const ParserErrorCode EXTERNAL_SETTER_WITH_BODY =
-      const ParserErrorCode(
-          'EXTERNAL_SETTER_WITH_BODY', "External setters cannot have a body");
-
-  static const ParserErrorCode EXTERNAL_TYPEDEF = const ParserErrorCode(
-      'EXTERNAL_TYPEDEF', "Type aliases cannot be declared to be 'external'");
-
-  static const ParserErrorCode FACTORY_TOP_LEVEL_DECLARATION =
-      const ParserErrorCode('FACTORY_TOP_LEVEL_DECLARATION',
-          "Top-level declarations cannot be declared to be 'factory'");
-
-  static const ParserErrorCode FACTORY_WITH_INITIALIZERS =
-      const ParserErrorCode(
-          'FACTORY_WITH_INITIALIZERS',
-          "A 'factory' constructor cannot have initializers",
-          "Either remove the 'factory' keyword to make this a generative "
-          "constructor or remove the initializers.");
-
-  static const ParserErrorCode FACTORY_WITHOUT_BODY = const ParserErrorCode(
-      'FACTORY_WITHOUT_BODY',
-      "A non-redirecting 'factory' constructor must have a body");
-
-  static const ParserErrorCode FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR =
-      const ParserErrorCode('FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR',
-          "Field initializers can only be used in a constructor");
-
-  static const ParserErrorCode FINAL_AND_VAR = const ParserErrorCode(
-      'FINAL_AND_VAR',
-      "Members cannot be declared to be both 'final' and 'var'");
-
-  static const ParserErrorCode FINAL_CLASS = const ParserErrorCode(
-      'FINAL_CLASS', "Classes cannot be declared to be 'final'");
-
-  static const ParserErrorCode FINAL_CONSTRUCTOR = const ParserErrorCode(
-      'FINAL_CONSTRUCTOR', "A constructor cannot be declared to be 'final'");
-
-  static const ParserErrorCode FINAL_ENUM = const ParserErrorCode(
-      'FINAL_ENUM', "Enums cannot be declared to be 'final'");
-
-  static const ParserErrorCode FINAL_METHOD = const ParserErrorCode(
-      'FINAL_METHOD',
-      "Getters, setters and methods cannot be declared to be 'final'");
-
-  static const ParserErrorCode FINAL_TYPEDEF = const ParserErrorCode(
-      'FINAL_TYPEDEF', "Type aliases cannot be declared to be 'final'");
-
-  static const ParserErrorCode FUNCTION_TYPED_PARAMETER_VAR = const ParserErrorCode(
-      'FUNCTION_TYPED_PARAMETER_VAR',
-      "Function typed parameters cannot specify 'const', 'final' or 'var' instead of return type");
-
-  static const ParserErrorCode GETTER_IN_FUNCTION = const ParserErrorCode(
-      'GETTER_IN_FUNCTION',
-      "Getters cannot be defined within methods or functions");
-
-  static const ParserErrorCode GETTER_WITH_PARAMETERS = const ParserErrorCode(
-      'GETTER_WITH_PARAMETERS',
-      "Getter should be declared without a parameter list");
-
-  static const ParserErrorCode ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE =
-      const ParserErrorCode('ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE',
-          "Illegal assignment to non-assignable expression");
-
-  static const ParserErrorCode IMPLEMENTS_BEFORE_EXTENDS =
-      const ParserErrorCode('IMPLEMENTS_BEFORE_EXTENDS',
-          "The extends clause must be before the implements clause");
-
-  static const ParserErrorCode IMPLEMENTS_BEFORE_WITH = const ParserErrorCode(
-      'IMPLEMENTS_BEFORE_WITH',
-      "The with clause must be before the implements clause");
-
-  static const ParserErrorCode IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE =
-      const ParserErrorCode('IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE',
-          "Import directives must preceed part directives");
-
-  static const ParserErrorCode INITIALIZED_VARIABLE_IN_FOR_EACH =
-      const ParserErrorCode('INITIALIZED_VARIABLE_IN_FOR_EACH',
-          "The loop variable in a for-each loop cannot be initialized");
-
-  static const ParserErrorCode INVALID_AWAIT_IN_FOR = const ParserErrorCode(
-      'INVALID_AWAIT_IN_FOR',
-      "The modifier 'await' is not allowed for a normal 'for' statement",
-      "Remove the keyword or use a for-each statement.");
-
-  static const ParserErrorCode INVALID_CODE_POINT = const ParserErrorCode(
-      'INVALID_CODE_POINT',
-      "The escape sequence '{0}' is not a valid code point");
-
-  static const ParserErrorCode INVALID_COMMENT_REFERENCE = const ParserErrorCode(
-      'INVALID_COMMENT_REFERENCE',
-      "Comment references should contain a possibly prefixed identifier and can start with 'new', but should not contain anything else");
-
-  static const ParserErrorCode INVALID_HEX_ESCAPE = const ParserErrorCode(
-      'INVALID_HEX_ESCAPE',
-      "An escape sequence starting with '\\x' must be followed by 2 hexidecimal digits");
-
-  static const ParserErrorCode INVALID_LITERAL_IN_CONFIGURATION =
-      const ParserErrorCode('INVALID_LITERAL_IN_CONFIGURATION',
-          "The literal in a configuration cannot contain interpolation");
-
-  static const ParserErrorCode INVALID_OPERATOR = const ParserErrorCode(
-      'INVALID_OPERATOR', "The string '{0}' is not a valid operator");
-
-  static const ParserErrorCode INVALID_OPERATOR_FOR_SUPER =
-      const ParserErrorCode('INVALID_OPERATOR_FOR_SUPER',
-          "The operator '{0}' cannot be used with 'super'");
-
-  static const ParserErrorCode INVALID_STAR_AFTER_ASYNC = const ParserErrorCode(
-      'INVALID_STAR_AFTER_ASYNC',
-      "The modifier 'async*' is not allowed for an expression function body",
-      "Convert the body to a block.");
-
-  static const ParserErrorCode INVALID_SYNC = const ParserErrorCode(
-      'INVALID_SYNC',
-      "The modifier 'sync' is not allowed for an exrpression function body",
-      "Convert the body to a block.");
-
-  static const ParserErrorCode INVALID_UNICODE_ESCAPE = const ParserErrorCode(
-      'INVALID_UNICODE_ESCAPE',
-      "An escape sequence starting with '\\u' must be followed by 4 hexidecimal digits or from 1 to 6 digits between '{' and '}'");
-
-  static const ParserErrorCode LIBRARY_DIRECTIVE_NOT_FIRST =
-      const ParserErrorCode('LIBRARY_DIRECTIVE_NOT_FIRST',
-          "The library directive must appear before all other directives");
-
-  static const ParserErrorCode LOCAL_FUNCTION_DECLARATION_MODIFIER =
-      const ParserErrorCode('LOCAL_FUNCTION_DECLARATION_MODIFIER',
-          "Local function declarations cannot specify any modifier");
-
-  static const ParserErrorCode MISSING_ASSIGNABLE_SELECTOR =
-      const ParserErrorCode('MISSING_ASSIGNABLE_SELECTOR',
-          "Missing selector such as \".<identifier>\" or \"[0]\"");
-
-  static const ParserErrorCode MISSING_ASSIGNMENT_IN_INITIALIZER =
-      const ParserErrorCode('MISSING_ASSIGNMENT_IN_INITIALIZER',
-          "Expected an assignment after the field name");
-
-  static const ParserErrorCode MISSING_CATCH_OR_FINALLY = const ParserErrorCode(
-      'MISSING_CATCH_OR_FINALLY',
-      "A try statement must have either a catch or finally clause");
-
-  static const ParserErrorCode MISSING_CLASS_BODY = const ParserErrorCode(
-      'MISSING_CLASS_BODY',
-      "A class definition must have a body, even if it is empty");
-
-  static const ParserErrorCode MISSING_CLOSING_PARENTHESIS =
-      const ParserErrorCode(
-          'MISSING_CLOSING_PARENTHESIS', "The closing parenthesis is missing");
-
-  static const ParserErrorCode MISSING_CONST_FINAL_VAR_OR_TYPE =
-      const ParserErrorCode('MISSING_CONST_FINAL_VAR_OR_TYPE',
-          "Variables must be declared using the keywords 'const', 'final', 'var' or a type name");
-
-  static const ParserErrorCode MISSING_ENUM_BODY = const ParserErrorCode(
-      'MISSING_ENUM_BODY',
-      "An enum definition must have a body with at least one constant name");
-
-  static const ParserErrorCode MISSING_EXPRESSION_IN_INITIALIZER =
-      const ParserErrorCode('MISSING_EXPRESSION_IN_INITIALIZER',
-          "Expected an expression after the assignment operator");
-
-  static const ParserErrorCode MISSING_EXPRESSION_IN_THROW =
-      const ParserErrorCode('MISSING_EXPRESSION_IN_THROW',
-          "Missing expression after 'throw'.", "Did you mean 'rethrow'?");
-
-  static const ParserErrorCode MISSING_FUNCTION_BODY = const ParserErrorCode(
-      'MISSING_FUNCTION_BODY', "A function body must be provided");
-
-  static const ParserErrorCode MISSING_FUNCTION_PARAMETERS =
-      const ParserErrorCode('MISSING_FUNCTION_PARAMETERS',
-          "Functions must have an explicit list of parameters");
-
-  static const ParserErrorCode MISSING_METHOD_PARAMETERS =
-      const ParserErrorCode('MISSING_METHOD_PARAMETERS',
-          "Methods must have an explicit list of parameters");
-
-  static const ParserErrorCode MISSING_GET = const ParserErrorCode(
-      'MISSING_GET',
-      "Getters must have the keyword 'get' before the getter name");
-
-  static const ParserErrorCode MISSING_IDENTIFIER =
-      const ParserErrorCode('MISSING_IDENTIFIER', "Expected an identifier");
-
-  static const ParserErrorCode MISSING_INITIALIZER =
-      const ParserErrorCode('MISSING_INITIALIZER', "Expected an initializer");
-
-  static const ParserErrorCode MISSING_KEYWORD_OPERATOR = const ParserErrorCode(
-      'MISSING_KEYWORD_OPERATOR',
-      "Operator declarations must be preceeded by the keyword 'operator'");
-
-  static const ParserErrorCode MISSING_NAME_IN_LIBRARY_DIRECTIVE =
-      const ParserErrorCode('MISSING_NAME_IN_LIBRARY_DIRECTIVE',
-          "Library directives must include a library name");
-
-  static const ParserErrorCode MISSING_NAME_IN_PART_OF_DIRECTIVE =
-      const ParserErrorCode('MISSING_NAME_IN_PART_OF_DIRECTIVE',
-          "Library directives must include a library name");
-
-  static const ParserErrorCode MISSING_PREFIX_IN_DEFERRED_IMPORT =
-      const ParserErrorCode('MISSING_PREFIX_IN_DEFERRED_IMPORT',
-          "Deferred imports must have a prefix");
-
-  static const ParserErrorCode MISSING_STAR_AFTER_SYNC = const ParserErrorCode(
-      'MISSING_STAR_AFTER_SYNC',
-      "The modifier 'sync' must be followed by a star ('*')",
-      "Remove the modifier or add a star.");
-
-  static const ParserErrorCode MISSING_STATEMENT =
-      const ParserErrorCode('MISSING_STATEMENT', "Expected a statement");
-
-  static const ParserErrorCode MISSING_TERMINATOR_FOR_PARAMETER_GROUP =
-      const ParserErrorCode('MISSING_TERMINATOR_FOR_PARAMETER_GROUP',
-          "There is no '{0}' to close the parameter group");
-
-  static const ParserErrorCode MISSING_TYPEDEF_PARAMETERS =
-      const ParserErrorCode('MISSING_TYPEDEF_PARAMETERS',
-          "Type aliases for functions must have an explicit list of parameters");
-
-  static const ParserErrorCode MISSING_VARIABLE_IN_FOR_EACH = const ParserErrorCode(
-      'MISSING_VARIABLE_IN_FOR_EACH',
-      "A loop variable must be declared in a for-each loop before the 'in', but none were found");
-
-  static const ParserErrorCode MIXED_PARAMETER_GROUPS = const ParserErrorCode(
-      'MIXED_PARAMETER_GROUPS',
-      "Cannot have both positional and named parameters in a single parameter list");
-
-  static const ParserErrorCode MULTIPLE_EXTENDS_CLAUSES = const ParserErrorCode(
-      'MULTIPLE_EXTENDS_CLAUSES',
-      "Each class definition can have at most one extends clause");
-
-  static const ParserErrorCode MULTIPLE_IMPLEMENTS_CLAUSES =
-      const ParserErrorCode('MULTIPLE_IMPLEMENTS_CLAUSES',
-          "Each class definition can have at most one implements clause");
-
-  static const ParserErrorCode MULTIPLE_LIBRARY_DIRECTIVES =
-      const ParserErrorCode('MULTIPLE_LIBRARY_DIRECTIVES',
-          "Only one library directive may be declared in a file");
-
-  static const ParserErrorCode MULTIPLE_NAMED_PARAMETER_GROUPS =
-      const ParserErrorCode('MULTIPLE_NAMED_PARAMETER_GROUPS',
-          "Cannot have multiple groups of named parameters in a single parameter list");
-
-  static const ParserErrorCode MULTIPLE_PART_OF_DIRECTIVES =
-      const ParserErrorCode('MULTIPLE_PART_OF_DIRECTIVES',
-          "Only one part-of directive may be declared in a file");
-
-  static const ParserErrorCode MULTIPLE_POSITIONAL_PARAMETER_GROUPS =
-      const ParserErrorCode('MULTIPLE_POSITIONAL_PARAMETER_GROUPS',
-          "Cannot have multiple groups of positional parameters in a single parameter list");
-
-  static const ParserErrorCode MULTIPLE_VARIABLES_IN_FOR_EACH =
-      const ParserErrorCode('MULTIPLE_VARIABLES_IN_FOR_EACH',
-          "A single loop variable must be declared in a for-each loop before the 'in', but {0} were found");
-
-  static const ParserErrorCode MULTIPLE_WITH_CLAUSES = const ParserErrorCode(
-      'MULTIPLE_WITH_CLAUSES',
-      "Each class definition can have at most one with clause");
-
-  static const ParserErrorCode NAMED_FUNCTION_EXPRESSION =
-      const ParserErrorCode(
-          'NAMED_FUNCTION_EXPRESSION', "Function expressions cannot be named");
-
-  static const ParserErrorCode NAMED_PARAMETER_OUTSIDE_GROUP =
-      const ParserErrorCode('NAMED_PARAMETER_OUTSIDE_GROUP',
-          "Named parameters must be enclosed in curly braces ('{' and '}')");
-
-  static const ParserErrorCode NATIVE_CLAUSE_IN_NON_SDK_CODE =
-      const ParserErrorCode('NATIVE_CLAUSE_IN_NON_SDK_CODE',
-          "Native clause can only be used in the SDK and code that is loaded through native extensions");
-
-  static const ParserErrorCode NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE =
-      const ParserErrorCode('NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE',
-          "Native functions can only be declared in the SDK and code that is loaded through native extensions");
-
-  static const ParserErrorCode NON_CONSTRUCTOR_FACTORY = const ParserErrorCode(
-      'NON_CONSTRUCTOR_FACTORY',
-      "Only constructors can be declared to be a 'factory'");
-
-  static const ParserErrorCode NON_IDENTIFIER_LIBRARY_NAME =
-      const ParserErrorCode('NON_IDENTIFIER_LIBRARY_NAME',
-          "The name of a library must be an identifier");
-
-  static const ParserErrorCode NON_PART_OF_DIRECTIVE_IN_PART =
-      const ParserErrorCode('NON_PART_OF_DIRECTIVE_IN_PART',
-          "The part-of directive must be the only directive in a part");
-
-  static const ParserErrorCode NON_STRING_LITERAL_AS_URI =
-      const ParserErrorCode(
-          'NON_STRING_LITERAL_AS_URI',
-          "The URI must be a string literal",
-          "Enclose the URI in either single or double quotes.");
-
-  static const ParserErrorCode NON_USER_DEFINABLE_OPERATOR =
-      const ParserErrorCode('NON_USER_DEFINABLE_OPERATOR',
-          "The operator '{0}' is not user definable");
-
-  static const ParserErrorCode NORMAL_BEFORE_OPTIONAL_PARAMETERS =
-      const ParserErrorCode('NORMAL_BEFORE_OPTIONAL_PARAMETERS',
-          "Normal parameters must occur before optional parameters");
-
-  static const ParserErrorCode POSITIONAL_AFTER_NAMED_ARGUMENT =
-      const ParserErrorCode('POSITIONAL_AFTER_NAMED_ARGUMENT',
-          "Positional arguments must occur before named arguments");
-
-  static const ParserErrorCode POSITIONAL_PARAMETER_OUTSIDE_GROUP =
-      const ParserErrorCode('POSITIONAL_PARAMETER_OUTSIDE_GROUP',
-          "Positional parameters must be enclosed in square brackets ('[' and ']')");
-
-  static const ParserErrorCode REDIRECTING_CONSTRUCTOR_WITH_BODY =
-      const ParserErrorCode('REDIRECTING_CONSTRUCTOR_WITH_BODY',
-          "Redirecting constructors cannot have a body");
-
-  static const ParserErrorCode REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR =
-      const ParserErrorCode('REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR',
-          "Only factory constructor can specify '=' redirection.");
-
-  static const ParserErrorCode SETTER_IN_FUNCTION = const ParserErrorCode(
-      'SETTER_IN_FUNCTION',
-      "Setters cannot be defined within methods or functions");
-
-  static const ParserErrorCode STATIC_AFTER_CONST = const ParserErrorCode(
-      'STATIC_AFTER_CONST',
-      "The modifier 'static' should be before the modifier 'const'");
-
-  static const ParserErrorCode STATIC_AFTER_FINAL = const ParserErrorCode(
-      'STATIC_AFTER_FINAL',
-      "The modifier 'static' should be before the modifier 'final'");
-
-  static const ParserErrorCode STATIC_AFTER_VAR = const ParserErrorCode(
-      'STATIC_AFTER_VAR',
-      "The modifier 'static' should be before the modifier 'var'");
-
-  static const ParserErrorCode STATIC_CONSTRUCTOR = const ParserErrorCode(
-      'STATIC_CONSTRUCTOR', "Constructors cannot be static");
-
-  static const ParserErrorCode STATIC_GETTER_WITHOUT_BODY =
-      const ParserErrorCode(
-          'STATIC_GETTER_WITHOUT_BODY', "A 'static' getter must have a body");
-
-  static const ParserErrorCode STATIC_OPERATOR =
-      const ParserErrorCode('STATIC_OPERATOR', "Operators cannot be static");
-
-  static const ParserErrorCode STATIC_SETTER_WITHOUT_BODY =
-      const ParserErrorCode(
-          'STATIC_SETTER_WITHOUT_BODY', "A 'static' setter must have a body");
-
-  static const ParserErrorCode STATIC_TOP_LEVEL_DECLARATION =
-      const ParserErrorCode('STATIC_TOP_LEVEL_DECLARATION',
-          "Top-level declarations cannot be declared to be 'static'");
-
-  static const ParserErrorCode SWITCH_HAS_CASE_AFTER_DEFAULT_CASE =
-      const ParserErrorCode('SWITCH_HAS_CASE_AFTER_DEFAULT_CASE',
-          "The 'default' case should be the last case in a switch statement");
-
-  static const ParserErrorCode SWITCH_HAS_MULTIPLE_DEFAULT_CASES =
-      const ParserErrorCode('SWITCH_HAS_MULTIPLE_DEFAULT_CASES',
-          "The 'default' case can only be declared once");
-
-  static const ParserErrorCode TOP_LEVEL_OPERATOR = const ParserErrorCode(
-      'TOP_LEVEL_OPERATOR', "Operators must be declared within a class");
-
-  static const ParserErrorCode TYPEDEF_IN_CLASS = const ParserErrorCode(
-      'TYPEDEF_IN_CLASS',
-      "Function type aliases cannot be declared inside classes");
-
-  static const ParserErrorCode UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP =
-      const ParserErrorCode('UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP',
-          "There is no '{0}' to open a parameter group");
-
-  static const ParserErrorCode UNEXPECTED_TOKEN =
-      const ParserErrorCode('UNEXPECTED_TOKEN', "Unexpected token '{0}'");
-
-  static const ParserErrorCode WITH_BEFORE_EXTENDS = const ParserErrorCode(
-      'WITH_BEFORE_EXTENDS',
-      "The extends clause must be before the with clause");
-
-  static const ParserErrorCode WITH_WITHOUT_EXTENDS = const ParserErrorCode(
-      'WITH_WITHOUT_EXTENDS',
-      "The with clause cannot be used without an extends clause");
-
-  static const ParserErrorCode WRONG_SEPARATOR_FOR_NAMED_PARAMETER =
-      const ParserErrorCode('WRONG_SEPARATOR_FOR_NAMED_PARAMETER',
-          "The default value of a named parameter should be preceeded by ':'");
-
-  static const ParserErrorCode WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER =
-      const ParserErrorCode('WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER',
-          "The default value of a positional parameter should be preceeded by '='");
-
-  static const ParserErrorCode WRONG_TERMINATOR_FOR_PARAMETER_GROUP =
-      const ParserErrorCode('WRONG_TERMINATOR_FOR_PARAMETER_GROUP',
-          "Expected '{0}' to close parameter group");
-
-  static const ParserErrorCode VAR_AND_TYPE = const ParserErrorCode(
-      'VAR_AND_TYPE',
-      "Variables cannot be declared using both 'var' and a type name; remove the 'var'");
-
-  static const ParserErrorCode VAR_AS_TYPE_NAME = const ParserErrorCode(
-      'VAR_AS_TYPE_NAME', "The keyword 'var' cannot be used as a type name");
-
-  static const ParserErrorCode VAR_CLASS = const ParserErrorCode(
-      'VAR_CLASS', "Classes cannot be declared to be 'var'");
-
-  static const ParserErrorCode VAR_ENUM =
-      const ParserErrorCode('VAR_ENUM', "Enums cannot be declared to be 'var'");
-
-  static const ParserErrorCode VAR_RETURN_TYPE = const ParserErrorCode(
-      'VAR_RETURN_TYPE', "The return type cannot be 'var'");
-
-  static const ParserErrorCode VAR_TYPEDEF = const ParserErrorCode(
-      'VAR_TYPEDEF', "Type aliases cannot be declared to be 'var'");
-
-  static const ParserErrorCode VOID_PARAMETER = const ParserErrorCode(
-      'VOID_PARAMETER', "Parameters cannot have a type of 'void'");
-
-  static const ParserErrorCode VOID_VARIABLE = const ParserErrorCode(
-      'VOID_VARIABLE', "Variables cannot have a type of 'void'");
-
-  /**
-   * Initialize a newly created error code to have the given [name]. The message
-   * associated with the error will be created from the given [message]
-   * template. The correction associated with the error will be created from the
-   * given [correction] template.
-   */
-  const ParserErrorCode(String name, String message, [String correction])
-      : super(name, message, correction);
-
-  @override
-  ErrorSeverity get errorSeverity => ErrorSeverity.ERROR;
-
-  @override
-  ErrorType get type => ErrorType.SYNTACTIC_ERROR;
-}
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index a24bd1e..26b997d 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -27,7 +27,6 @@
 import 'package:analyzer/src/generated/element_resolver.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error_verifier.dart';
-import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/static_type_analyzer.dart';
 import 'package:analyzer/src/generated/type_system.dart';
@@ -52,7 +51,7 @@
    * The class containing the AST nodes being visited, or `null` if we are not in the scope of
    * a class.
    */
-  ClassElement _enclosingClass;
+  ClassElementImpl _enclosingClass;
 
   /**
    * A flag indicating whether a surrounding member (compilation unit or class)
@@ -87,12 +86,17 @@
   LibraryElement _currentLibrary;
 
   /**
+   * The inheritance manager used to find overridden methods.
+   */
+  InheritanceManager _manager;
+
+  /**
    * Create a new instance of the [BestPracticesVerifier].
    *
    * @param errorReporter the error reporter
    */
-  BestPracticesVerifier(
-      this._errorReporter, TypeProvider typeProvider, this._currentLibrary,
+  BestPracticesVerifier(this._errorReporter, TypeProvider typeProvider,
+      this._currentLibrary, this._manager,
       {TypeSystem typeSystem})
       : _nullType = typeProvider.nullType,
         _futureNullType = typeProvider.futureNullType,
@@ -159,9 +163,9 @@
 
   @override
   Object visitClassDeclaration(ClassDeclaration node) {
-    ClassElement outerClass = _enclosingClass;
+    ClassElementImpl outerClass = _enclosingClass;
     bool wasInDeprecatedMember = inDeprecatedMember;
-    ClassElement element = node.element;
+    ClassElement element = AbstractClassElementImpl.getImpl(node.element);
     if (element != null && element.isDeprecated) {
       inDeprecatedMember = true;
     }
@@ -283,8 +287,10 @@
 
   @override
   Object visitMethodInvocation(MethodInvocation node) {
+    Expression realTarget = node.realTarget;
+    _checkForAbstractSuperMemberReference(realTarget, node.methodName);
     _checkForCanBeNullAfterNullAware(
-        node.realTarget, node.operator, null, node.methodName);
+        realTarget, node.operator, null, node.methodName);
     DartType staticInvokeType = node.staticInvokeType;
     if (staticInvokeType is InterfaceType) {
       MethodElement methodElement = staticInvokeType.lookUpMethod(
@@ -308,8 +314,10 @@
 
   @override
   Object visitPropertyAccess(PropertyAccess node) {
+    Expression realTarget = node.realTarget;
+    _checkForAbstractSuperMemberReference(realTarget, node.propertyName);
     _checkForCanBeNullAfterNullAware(
-        node.realTarget, node.operator, node.propertyName, null);
+        realTarget, node.operator, node.propertyName, null);
     return super.visitPropertyAccess(node);
   }
 
@@ -409,6 +417,34 @@
     return false;
   }
 
+  void _checkForAbstractSuperMemberReference(
+      Expression target, SimpleIdentifier name) {
+    if (target is SuperExpression) {
+      Element element = name.staticElement;
+      if (element is ExecutableElement && element.isAbstract) {
+        if (!_enclosingClass.hasNoSuchMethod) {
+          ExecutableElement concrete = null;
+          if (element.kind == ElementKind.METHOD) {
+            concrete = _enclosingClass.lookUpInheritedConcreteMethod(
+                element.displayName, _currentLibrary);
+          } else if (element.kind == ElementKind.GETTER) {
+            concrete = _enclosingClass.lookUpInheritedConcreteGetter(
+                element.displayName, _currentLibrary);
+          } else if (element.kind == ElementKind.SETTER) {
+            concrete = _enclosingClass.lookUpInheritedConcreteSetter(
+                element.displayName, _currentLibrary);
+          }
+          if (concrete == null) {
+            _errorReporter.reportTypeErrorForNode(
+                HintCode.ABSTRACT_SUPER_MEMBER_REFERENCE,
+                name,
+                [element.kind.displayName, name.name]);
+          }
+        }
+      }
+    }
+  }
+
   /**
    * This verifies that the passed expression can be assigned to its corresponding parameters.
    *
@@ -4291,7 +4327,7 @@
     }
     // Dart best practices
     unit.accept(new BestPracticesVerifier(
-        errorReporter, _context.typeProvider, _library,
+        errorReporter, _context.typeProvider, _library, _manager,
         typeSystem: _context.typeSystem));
     unit.accept(new OverrideVerifier(errorReporter, _manager));
     // Find to-do comments
@@ -5007,11 +5043,11 @@
 }
 
 /**
- * This enum holds one of four states of a field initialization state through a constructor
- * signature, not initialized, initialized in the field declaration, initialized in the field
- * formal, and finally, initialized in the initializers list.
+ * The four states of a field initialization state through a constructor
+ * signature, not initialized, initialized in the field declaration, initialized
+ * in the field formal, and finally, initialized in the initializers list.
  */
-class INIT_STATE extends Enum<INIT_STATE> {
+class INIT_STATE implements Comparable<INIT_STATE> {
   static const INIT_STATE NOT_INIT = const INIT_STATE('NOT_INIT', 0);
 
   static const INIT_STATE INIT_IN_DECLARATION =
@@ -5030,7 +5066,26 @@
     INIT_IN_INITIALIZERS
   ];
 
-  const INIT_STATE(String name, int ordinal) : super(name, ordinal);
+  /**
+   * The name of this init state.
+   */
+  final String name;
+
+  /**
+   * The ordinal value of the init state.
+   */
+  final int ordinal;
+
+  const INIT_STATE(this.name, this.ordinal);
+
+  @override
+  int get hashCode => ordinal;
+
+  @override
+  int compareTo(INIT_STATE other) => ordinal - other.ordinal;
+
+  @override
+  String toString() => name;
 }
 
 /**
@@ -5527,7 +5582,8 @@
 /**
  * Kind of the redirecting constructor.
  */
-class RedirectingConstructorKind extends Enum<RedirectingConstructorKind> {
+class RedirectingConstructorKind
+    implements Comparable<RedirectingConstructorKind> {
   static const RedirectingConstructorKind CONST =
       const RedirectingConstructorKind('CONST', 0);
 
@@ -5536,8 +5592,26 @@
 
   static const List<RedirectingConstructorKind> values = const [CONST, NORMAL];
 
-  const RedirectingConstructorKind(String name, int ordinal)
-      : super(name, ordinal);
+  /**
+   * The name of this redirecting constructor kind.
+   */
+  final String name;
+
+  /**
+   * The ordinal value of the redirecting constructor kind.
+   */
+  final int ordinal;
+
+  const RedirectingConstructorKind(this.name, this.ordinal);
+
+  @override
+  int get hashCode => ordinal;
+
+  @override
+  int compareTo(RedirectingConstructorKind other) => ordinal - other.ordinal;
+
+  @override
+  String toString() => name;
 }
 
 /**
@@ -7283,8 +7357,13 @@
           originalType is FunctionType &&
           originalType.typeFormals.isNotEmpty &&
           ts is StrongTypeSystemImpl) {
-        contextType = ts.inferGenericFunctionCall(typeProvider, originalType,
-            DartType.EMPTY_LIST, DartType.EMPTY_LIST, originalType.returnType, returnContextType);
+        contextType = ts.inferGenericFunctionCall(
+            typeProvider,
+            originalType,
+            DartType.EMPTY_LIST,
+            DartType.EMPTY_LIST,
+            originalType.returnType,
+            returnContextType);
       }
 
       InferenceContext.setType(node.argumentList, contextType);
diff --git a/pkg/analyzer/lib/src/generated/source.dart b/pkg/analyzer/lib/src/generated/source.dart
index 2fc6c2d..7f95c01 100644
--- a/pkg/analyzer/lib/src/generated/source.dart
+++ b/pkg/analyzer/lib/src/generated/source.dart
@@ -11,7 +11,6 @@
 import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/context/source.dart';
 import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/java_io.dart' show JavaFile;
 import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
@@ -688,7 +687,7 @@
  * The enumeration `SourceKind` defines the different kinds of sources that are
  * known to the analysis engine.
  */
-class SourceKind extends Enum<SourceKind> {
+class SourceKind implements Comparable<SourceKind> {
   /**
    * A source containing HTML. The HTML might or might not contain Dart scripts.
    */
@@ -716,7 +715,26 @@
 
   static const List<SourceKind> values = const [HTML, LIBRARY, PART, UNKNOWN];
 
-  const SourceKind(String name, int ordinal) : super(name, ordinal);
+  /**
+   * The name of this source kind.
+   */
+  final String name;
+
+  /**
+   * The ordinal value of the source kind.
+   */
+  final int ordinal;
+
+  const SourceKind(this.name, this.ordinal);
+
+  @override
+  int get hashCode => ordinal;
+
+  @override
+  int compareTo(SourceKind other) => ordinal - other.ordinal;
+
+  @override
+  String toString() => name;
 }
 
 /**
@@ -848,7 +866,7 @@
  * The enumeration `UriKind` defines the different kinds of URI's that are known to the
  * analysis engine. These are used to keep track of the kind of URI associated with a given source.
  */
-class UriKind extends Enum<UriKind> {
+class UriKind implements Comparable<UriKind> {
   /**
    * A 'dart:' URI.
    */
@@ -867,23 +885,37 @@
   static const List<UriKind> values = const [DART_URI, FILE_URI, PACKAGE_URI];
 
   /**
+   * The name of this URI kind.
+   */
+  final String name;
+
+  /**
+   * The ordinal value of the URI kind.
+   */
+  final int ordinal;
+
+  /**
    * The single character encoding used to identify this kind of URI.
    */
   final int encoding;
 
   /**
    * Initialize a newly created URI kind to have the given encoding.
-   *
-   * @param encoding the single character encoding used to identify this kind of URI.
    */
-  const UriKind(String name, int ordinal, this.encoding) : super(name, ordinal);
+  const UriKind(this.name, this.ordinal, this.encoding);
+
+  @override
+  int get hashCode => ordinal;
+
+  @override
+  int compareTo(UriKind other) => ordinal - other.ordinal;
+
+  @override
+  String toString() => name;
 
   /**
-   * Return the URI kind represented by the given encoding, or `null` if there is no kind with
-   * the given encoding.
-   *
-   * @param encoding the single character encoding used to identify the URI kind to be returned
-   * @return the URI kind represented by the given encoding
+   * Return the URI kind represented by the given [encoding], or `null` if there
+   * is no kind with the given encoding.
    */
   static UriKind fromEncoding(int encoding) {
     while (true) {
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index fafb7b9..4ebd9b3 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -1602,10 +1602,37 @@
       return type;
     }
 
-    FunctionElementImpl function = new FunctionElementImpl("", -1);
+    // TODO(jmesserly): feels like we should be able to do this with less code.
+
+    // Create fresh type formals. This avoids capture if we're inferring the
+    // constructor to the class from inside it.
+
+    // We build up a substitution for the type parameters,
+    // {variablesFresh/variables} then apply it.
+    var typeVars = <DartType>[];
+    var freshTypeVars = <DartType>[];
+    var freshVarElements = <TypeParameterElement>[];
+    for (int i = 0; i < cls.typeParameters.length; i++) {
+      var typeParamElement = cls.typeParameters[i];
+      var freshElement =
+          new TypeParameterElementImpl.synthetic(typeParamElement.name);
+      var freshTypeVar = new TypeParameterTypeImpl(freshElement);
+      freshElement.type = freshTypeVar;
+
+      typeVars.add(typeParamElement.type);
+      freshTypeVars.add(freshTypeVar);
+      freshVarElements.add(freshElement);
+
+      var bound = typeParamElement.bound ?? DynamicTypeImpl.instance;
+      freshElement.bound = bound.substitute2(freshTypeVars, typeVars);
+    }
+
+    type = type.substitute2(freshTypeVars, typeVars);
+
+    var function = new FunctionElementImpl("", -1);
     function.synthetic = true;
     function.returnType = type.returnType;
-    function.shareTypeParameters(cls.typeParameters);
+    function.typeParameters = freshVarElements;
     function.shareParameters(type.parameters);
     return function.type = new FunctionTypeImpl(function);
   }
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index 4899d9a..0488553 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -1640,12 +1640,8 @@
         // We already know L <: T2, for some L.
         // So update L to reflect the new constraint LUB(L, T1) <: T2
         //
-
-        // Heuristic: we intentionally ignore `dynamic` when doing inference.
-        if (!t1.isDynamic) {
-          bound.lower =
-              _typeSystem.getLeastUpperBound(_typeProvider, bound.lower, t1);
-        }
+        bound.lower =
+            _typeSystem.getLeastUpperBound(_typeProvider, bound.lower, t1);
         // Optimistically assume we will be able to satisfy the constraint.
         return true;
       }
diff --git a/pkg/analyzer/lib/src/generated/utilities_collection.dart b/pkg/analyzer/lib/src/generated/utilities_collection.dart
index cd39548..b1c5e88 100644
--- a/pkg/analyzer/lib/src/generated/utilities_collection.dart
+++ b/pkg/analyzer/lib/src/generated/utilities_collection.dart
@@ -34,17 +34,12 @@
 }
 
 /**
- * The class `BooleanArray` defines methods for operating on integers as if they were arrays
- * of booleans. These arrays can be indexed by either integers or by enumeration constants.
+ * Methods for operating on integers as if they were arrays of booleans. These
+ * arrays can be indexed by either integers or by enumeration constants.
  */
 class BooleanArray {
   /**
-   * Return the value of the element at the given index.
-   *
-   * @param array the array being accessed
-   * @param index the index of the element being accessed
-   * @return the value of the element at the given index
-   * @throws IndexOutOfBoundsException if the index is not between zero (0) and 31, inclusive
+   * Return the value of the element of the given [array] at the given [index].
    */
   static bool get(int array, int index) {
     _checkIndex(index);
@@ -53,22 +48,13 @@
 
   /**
    * Return the value of the element at the given index.
-   *
-   * @param array the array being accessed
-   * @param index the index of the element being accessed
-   * @return the value of the element at the given index
-   * @throws IndexOutOfBoundsException if the index is not between zero (0) and 31, inclusive
    */
+  @deprecated
   static bool getEnum(int array, Enum index) => get(array, index.ordinal);
 
   /**
-   * Set the value of the element at the given index to the given value.
-   *
-   * @param array the array being modified
-   * @param index the index of the element being set
-   * @param value the value to be assigned to the element
-   * @return the updated value of the array
-   * @throws IndexOutOfBoundsException if the index is not between zero (0) and 31, inclusive
+   * Set the value of the element of the given [array] at the given [index] to
+   * the given [value].
    */
   static int set(int array, int index, bool value) {
     _checkIndex(index);
@@ -81,21 +67,14 @@
 
   /**
    * Set the value of the element at the given index to the given value.
-   *
-   * @param array the array being modified
-   * @param index the index of the element being set
-   * @param value the value to be assigned to the element
-   * @return the updated value of the array
-   * @throws IndexOutOfBoundsException if the index is not between zero (0) and 31, inclusive
    */
+  @deprecated
   static int setEnum(int array, Enum index, bool value) =>
       set(array, index.ordinal, value);
 
   /**
-   * Throw an exception if the index is not within the bounds allowed for an integer-encoded array
-   * of boolean values.
-   *
-   * @throws IndexOutOfBoundsException if the index is not between zero (0) and 31, inclusive
+   * Throw an exception if the index is not within the bounds allowed for an
+   * integer-encoded array of boolean values.
    */
   static void _checkIndex(int index) {
     if (index < 0 || index > 30) {
diff --git a/pkg/analyzer/lib/src/generated/utilities_dart.dart b/pkg/analyzer/lib/src/generated/utilities_dart.dart
index 3c0ab8d..8dd40df 100644
--- a/pkg/analyzer/lib/src/generated/utilities_dart.dart
+++ b/pkg/analyzer/lib/src/generated/utilities_dart.dart
@@ -8,7 +8,6 @@
 import 'package:analyzer/dart/ast/token.dart' show Token;
 import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/src/dart/element/element.dart' show ElementImpl;
-import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/util/fast_uri.dart';
 
@@ -83,11 +82,11 @@
 }
 
 /**
- * The enumeration `ParameterKind` defines the different kinds of parameters. There are two
- * basic kinds of parameters: required and optional. Optional parameters are further divided into
- * two kinds: positional optional and named optional.
+ * The kinds of a parameter. There are two basic kinds of parameters: required
+ * and optional. Optional parameters are further divided into two kinds:
+ * positional optional and named optional.
  */
-class ParameterKind extends Enum<ParameterKind> {
+class ParameterKind implements Comparable<ParameterKind> {
   static const ParameterKind REQUIRED =
       const ParameterKind('REQUIRED', 0, false);
 
@@ -99,15 +98,31 @@
   static const List<ParameterKind> values = const [REQUIRED, POSITIONAL, NAMED];
 
   /**
+   * The name of this parameter.
+   */
+  final String name;
+
+  /**
+   * The ordinal value of the parameter.
+   */
+  final int ordinal;
+
+  /**
    * A flag indicating whether this is an optional parameter.
    */
   final bool isOptional;
 
   /**
    * Initialize a newly created kind with the given state.
-   *
-   * @param isOptional `true` if this is an optional parameter
    */
-  const ParameterKind(String name, int ordinal, this.isOptional)
-      : super(name, ordinal);
+  const ParameterKind(this.name, this.ordinal, this.isOptional);
+
+  @override
+  int get hashCode => ordinal;
+
+  @override
+  int compareTo(ParameterKind other) => ordinal - other.ordinal;
+
+  @override
+  String toString() => name;
 }
diff --git a/pkg/analyzer/lib/src/summary/link.dart b/pkg/analyzer/lib/src/summary/link.dart
index f085b614..c805aeb 100644
--- a/pkg/analyzer/lib/src/summary/link.dart
+++ b/pkg/analyzer/lib/src/summary/link.dart
@@ -189,10 +189,8 @@
       result.paramReference =
           typeParameterContext.typeParameterNestingLevel - element.nestingLevel;
     } else {
-      // Out-of-scope type parameters only occur in circumstances where they
-      // are irrelevant (i.e. when a type parameter is unused).  So we can
-      // safely convert them to `dynamic`.
-      result.reference = compilationUnit.addRawReference('dynamic');
+      throw new StateError('The type parameter $type (in ${element?.location}) '
+          'is out of scope on ${typeParameterContext?.location}.');
     }
     return result;
   } else if (type is FunctionType) {
@@ -363,6 +361,9 @@
   List<PropertyAccessorElementForLink> get accessors;
 
   @override
+  ClassElementForLink get asClass => this;
+
+  @override
   ConstructorElementForLink get asConstructor => unnamedConstructor;
 
   @override
@@ -985,6 +986,23 @@
   noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
 
   /**
+   * Return the class element for the constructor referred to by the given
+   * [index] in [UnlinkedUnit.references].  If the reference is unresolved,
+   * return [UndefinedElementForLink.instance].
+   */
+  ReferenceableElementForLink resolveConstructorClassRef(int index) {
+    LinkedReference linkedReference = _linkedUnit.references[index];
+    if (linkedReference.kind == ReferenceKind.classOrEnum) {
+      return resolveRef(index);
+    }
+    if (index < _unlinkedUnit.references.length) {
+      UnlinkedReference unlinkedReference = _unlinkedUnit.references[index];
+      return resolveRef(unlinkedReference.prefixReference);
+    }
+    return UndefinedElementForLink.instance;
+  }
+
+  /**
    * Return the element referred to by the given [index] in
    * [UnlinkedUnit.references].  If the reference is unresolved,
    * return [UndefinedElementForLink.instance].
@@ -2379,11 +2397,10 @@
     stack.length -= numNamed + numPositional;
     strPtr += numNamed;
     EntityRef ref = _getNextRef();
-    ConstructorElementForLink element =
-        unit.resolveRef(ref.reference).asConstructor;
+    ClassElementForLink_Class element =
+        unit.resolveConstructorClassRef(ref.reference).asClass;
     if (element != null) {
-      ClassElementForLink_Class enclosingClass = element.enclosingClass;
-      stack.add(enclosingClass.buildType((int i) {
+      stack.add(element.buildType((int i) {
         // Type argument explicitly specified.
         if (i < ref.typeArguments.length) {
           return unit.resolveTypeRef(
@@ -4359,6 +4376,11 @@
  */
 abstract class ReferenceableElementForLink implements Element {
   /**
+   * If this element is a class reference, return it. Otherwise return `null`.
+   */
+  ClassElementForLink get asClass => null;
+
+  /**
    * If this element can be used in a constructor invocation context,
    * return the associated constructor (which may be `this` or some
    * other element).  Otherwise return `null`.
diff --git a/pkg/analyzer/lib/src/summary/package_bundle_reader.dart b/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
index caa98d2..c60f8ba 100644
--- a/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
@@ -181,7 +181,8 @@
     // Constant expressions are always resolved in summaries.
     if (result == CONSTANT_EXPRESSION_RESOLVED &&
         target is ConstantEvaluationTarget) {
-      entry.setValue(result, true, TargetedResult.EMPTY_LIST);
+      entry.setValue(
+          result as ResultDescriptor<bool>, true, TargetedResult.EMPTY_LIST);
       return true;
     }
     // Provide results for Source.
@@ -200,23 +201,28 @@
           result == LIBRARY_ELEMENT) {
         LibraryElement libraryElement =
             resynthesizer.getLibraryElement(uriString);
-        entry.setValue(result, libraryElement, TargetedResult.EMPTY_LIST);
+        entry.setValue(result as ResultDescriptor<LibraryElement>,
+            libraryElement, TargetedResult.EMPTY_LIST);
         return true;
       } else if (result == READY_LIBRARY_ELEMENT2 ||
           result == READY_LIBRARY_ELEMENT6 ||
           result == READY_LIBRARY_ELEMENT7) {
-        entry.setValue(result, true, TargetedResult.EMPTY_LIST);
+        entry.setValue(
+            result as ResultDescriptor<bool>, true, TargetedResult.EMPTY_LIST);
         return true;
       } else if (result == MODIFICATION_TIME) {
-        entry.setValue(result, 0, TargetedResult.EMPTY_LIST);
+        entry.setValue(
+            result as ResultDescriptor<int>, 0, TargetedResult.EMPTY_LIST);
         return true;
       } else if (result == SOURCE_KIND) {
         if (_dataStore.linkedMap.containsKey(uriString)) {
-          entry.setValue(result, SourceKind.LIBRARY, TargetedResult.EMPTY_LIST);
+          entry.setValue(result as ResultDescriptor<SourceKind>,
+              SourceKind.LIBRARY, TargetedResult.EMPTY_LIST);
           return true;
         }
         if (_dataStore.unlinkedMap.containsKey(uriString)) {
-          entry.setValue(result, SourceKind.PART, TargetedResult.EMPTY_LIST);
+          entry.setValue(result as ResultDescriptor<SourceKind>,
+              SourceKind.PART, TargetedResult.EMPTY_LIST);
           return true;
         }
         return false;
@@ -228,7 +234,8 @@
               .map((libraryUriString) =>
                   context.sourceFactory.resolveUri(target, libraryUriString))
               .toList(growable: false);
-          entry.setValue(result, librarySources, TargetedResult.EMPTY_LIST);
+          entry.setValue(result as ResultDescriptor<List<Source>>,
+              librarySources, TargetedResult.EMPTY_LIST);
           return true;
         }
         return false;
@@ -237,7 +244,8 @@
         List<int> lineStarts = unlinkedUnit.lineStarts;
         if (lineStarts.isNotEmpty) {
           LineInfo lineInfo = new LineInfo(lineStarts);
-          entry.setValue(result, lineInfo, TargetedResult.EMPTY_LIST);
+          entry.setValue(result as ResultDescriptor<LineInfo>, lineInfo,
+              TargetedResult.EMPTY_LIST);
           return true;
         }
         return false;
@@ -254,7 +262,8 @@
           result == CREATED_RESOLVED_UNIT9 ||
           result == CREATED_RESOLVED_UNIT10 ||
           result == CREATED_RESOLVED_UNIT11) {
-        entry.setValue(result, true, TargetedResult.EMPTY_LIST);
+        entry.setValue(
+            result as ResultDescriptor<bool>, true, TargetedResult.EMPTY_LIST);
         return true;
       }
       if (result == COMPILATION_UNIT_ELEMENT) {
@@ -263,13 +272,15 @@
         CompilationUnitElement unit = resynthesizer.getElement(
             new ElementLocationImpl.con3(<String>[libraryUri, unitUri]));
         if (unit != null) {
-          entry.setValue(result, unit, TargetedResult.EMPTY_LIST);
+          entry.setValue(result as ResultDescriptor<CompilationUnitElement>,
+              unit, TargetedResult.EMPTY_LIST);
           return true;
         }
       }
     } else if (target is VariableElement) {
       if (result == INFERRED_STATIC_VARIABLE) {
-        entry.setValue(result, target, TargetedResult.EMPTY_LIST);
+        entry.setValue(result as ResultDescriptor<VariableElement>, target,
+            TargetedResult.EMPTY_LIST);
         return true;
       }
     }
diff --git a/pkg/analyzer/lib/src/summary/pub_summary.dart b/pkg/analyzer/lib/src/summary/pub_summary.dart
index 5891183..93e6aec 100644
--- a/pkg/analyzer/lib/src/summary/pub_summary.dart
+++ b/pkg/analyzer/lib/src/summary/pub_summary.dart
@@ -33,6 +33,12 @@
 import 'package:path/path.dart' as pathos;
 
 /**
+ * Return the raw string value of the variable with the given [name],
+ * or `null` of the variable is not defined.
+ */
+typedef String _GetDeclaredVariable(String name);
+
+/**
  * Unlinked and linked information about a [PubPackage].
  */
 class LinkedPubPackage {
@@ -84,6 +90,12 @@
   static const UNLINKED_SPEC_NAME = 'unlinked_spec.ds';
 
   /**
+   * If `true` (by default), then linking new bundles is allowed.
+   * Otherwise only using existing cached bundles can be used.
+   */
+  final bool allowLinking;
+
+  /**
    * See [PackageBundleAssembler.currentMajorVersion].
    */
   final int majorVersion;
@@ -126,7 +138,8 @@
   Completer _onUnlinkedCompleteCompleter;
 
   PubSummaryManager(this.resourceProvider, this.tempFileName,
-      {@visibleForTesting this.majorVersion:
+      {@visibleForTesting this.allowLinking: true,
+      @visibleForTesting this.majorVersion:
           PackageBundleAssembler.currentMajorVersion});
 
   /**
@@ -169,6 +182,7 @@
   List<LinkedPubPackage> getLinkedBundles(AnalysisContext context) {
 //    Stopwatch timer = new Stopwatch()..start();
 
+    _GetDeclaredVariable getDeclaredVariable = context.declaredVariables.get;
     SourceFactory sourceFactory = context.sourceFactory;
     _ListedPackages listedPackages = new _ListedPackages(sourceFactory);
 
@@ -195,8 +209,8 @@
     List<_LinkedNode> nodes = <_LinkedNode>[];
     Map<String, _LinkedNode> packageToNode = <String, _LinkedNode>{};
     unlinkedBundles.forEach((package, unlinked) {
-      _LinkedNode node = new _LinkedNode(
-          sdkBundle, listedPackages, package, unlinked, packageToNode);
+      _LinkedNode node = new _LinkedNode(sdkBundle, getDeclaredVariable,
+          listedPackages, package, unlinked, packageToNode);
       nodes.add(node);
       packageToNode[package.name] = node;
     });
@@ -211,28 +225,32 @@
       _readLinked(node, strong);
     }
 
-    // Fill the store with bundles.
-    // Append the linked SDK bundle.
-    // Append unlinked and (if read from a cache) linked package bundles.
-    SummaryDataStore store = new SummaryDataStore(const <String>[]);
-    store.addBundle(null, sdkBundle);
-    for (_LinkedNode node in nodes) {
-      store.addBundle(null, node.unlinked);
-      if (node.linked != null) {
-        store.addBundle(null, node.linked);
+    // Link new bundles, if allowed.
+    if (allowLinking) {
+      // Fill the store with bundles.
+      // Append the linked SDK bundle.
+      // Append unlinked and (if read from a cache) linked package bundles.
+      SummaryDataStore store = new SummaryDataStore(const <String>[]);
+      store.addBundle(null, sdkBundle);
+      for (_LinkedNode node in nodes) {
+        store.addBundle(null, node.unlinked);
+        if (node.linked != null) {
+          store.addBundle(null, node.linked);
+        }
       }
-    }
 
-    // Link each package node.
-    for (_LinkedNode node in nodes) {
-      if (!node.isEvaluated) {
-        new _LinkedWalker(listedPackages, store, strong).walk(node);
+      // Link each package node.
+      for (_LinkedNode node in nodes) {
+        if (!node.isEvaluated) {
+          new _LinkedWalker(getDeclaredVariable, listedPackages, store, strong)
+              .walk(node);
+        }
       }
-    }
 
-    // Write newly linked bundles.
-    for (_LinkedNode node in nodes) {
-      _writeLinked(node, strong);
+      // Write newly linked bundles.
+      for (_LinkedNode node in nodes) {
+        _writeLinked(node, strong);
+      }
     }
 
     // Create successfully linked packages.
@@ -240,7 +258,7 @@
     for (_LinkedNode node in nodes) {
       if (node.linked != null) {
         linkedPackages.add(new LinkedPubPackage(
-            node.package, node.unlinked, node.linked, node._linkedHash));
+            node.package, node.unlinked, node.linked, node.linkedHash));
       }
     }
 
@@ -604,6 +622,7 @@
  */
 class _LinkedNode extends Node<_LinkedNode> {
   final PackageBundle sdkBundle;
+  final _GetDeclaredVariable getDeclaredVariable;
   final _ListedPackages listedPackages;
   final PubPackage package;
   final PackageBundle unlinked;
@@ -616,30 +635,31 @@
   List<int> linkedNewBytes;
   PackageBundle linked;
 
-  _LinkedNode(this.sdkBundle, this.listedPackages, this.package, this.unlinked,
-      this.packageToNode);
+  _LinkedNode(this.sdkBundle, this.getDeclaredVariable, this.listedPackages,
+      this.package, this.unlinked, this.packageToNode);
 
   @override
   bool get isEvaluated => linked != null || failed;
 
   /**
    * Return the hash string that corresponds to this linked bundle in the
-   * context of its [sdkBundles] and transitive dependencies.  Return `null` if
+   * context of its [sdkBundle] and transitive dependencies.  Return `null` if
    * the hash computation fails, because for example the full transitive
    * dependencies cannot computed.
    */
   String get linkedHash {
     if (_linkedHash == null && transitiveDependencies != null) {
-      // Collect all unlinked API signatures.
+      ApiSignature signature = new ApiSignature();
+      // Add all unlinked API signatures.
       List<String> signatures = <String>[];
       signatures.add(sdkBundle.apiSignature);
       transitiveDependencies
           .map((node) => node.unlinked.apiSignature)
           .forEach(signatures.add);
       signatures.sort();
-      // Combine sorted unlinked API signatures into a single hash.
-      ApiSignature signature = new ApiSignature();
       signatures.forEach(signature.addString);
+      // Combine into a single hash.
+      _appendDeclaredVariables(signature);
       _linkedHash = signature.toHex();
     }
     return _linkedHash;
@@ -709,17 +729,47 @@
 
   @override
   String toString() => package.toString();
+
+  /**
+   * Append names and values of all referenced declared variables (even the
+   * ones without actually declared values) to the given [signature].
+   */
+  void _appendDeclaredVariables(ApiSignature signature) {
+    Set<String> nameSet = new Set<String>();
+    for (_LinkedNode node in transitiveDependencies) {
+      for (UnlinkedUnit unit in node.unlinked.unlinkedUnits) {
+        for (UnlinkedImport import in unit.imports) {
+          for (UnlinkedConfiguration configuration in import.configurations) {
+            nameSet.add(configuration.name);
+          }
+        }
+        for (UnlinkedExportPublic export in unit.publicNamespace.exports) {
+          for (UnlinkedConfiguration configuration in export.configurations) {
+            nameSet.add(configuration.name);
+          }
+        }
+      }
+    }
+    List<String> sortedNameList = nameSet.toList()..sort();
+    signature.addInt(sortedNameList.length);
+    for (String name in sortedNameList) {
+      signature.addString(name);
+      signature.addString(getDeclaredVariable(name) ?? '');
+    }
+  }
 }
 
 /**
  * Specialization of [DependencyWalker] for linking packages.
  */
 class _LinkedWalker extends DependencyWalker<_LinkedNode> {
+  final _GetDeclaredVariable getDeclaredVariable;
   final _ListedPackages listedPackages;
   final SummaryDataStore store;
   final bool strong;
 
-  _LinkedWalker(this.listedPackages, this.store, this.strong);
+  _LinkedWalker(
+      this.getDeclaredVariable, this.listedPackages, this.store, this.strong);
 
   @override
   void evaluate(_LinkedNode node) {
@@ -741,10 +791,7 @@
       return store.linkedMap[uri];
     }, (String uri) {
       return store.unlinkedMap[uri];
-    }, (String name) {
-      // TODO(scheglov) decide how to use declared variables in Pub
-      return null;
-    }, strong);
+    }, getDeclaredVariable, strong);
     // Assemble linked bundles and put them into the store.
     for (_LinkedNode node in scc) {
       PackageBundleAssembler assembler = new PackageBundleAssembler();
diff --git a/pkg/analyzer/lib/src/summary/summary_sdk.dart b/pkg/analyzer/lib/src/summary/summary_sdk.dart
index 8d13a55..5857d8b 100644
--- a/pkg/analyzer/lib/src/summary/summary_sdk.dart
+++ b/pkg/analyzer/lib/src/summary/summary_sdk.dart
@@ -39,7 +39,8 @@
   @override
   bool compute(CacheEntry entry, ResultDescriptor result) {
     if (result == TYPE_PROVIDER) {
-      entry.setValue(result, typeProvider, TargetedResult.EMPTY_LIST);
+      entry.setValue(result as ResultDescriptor<TypeProvider>, typeProvider,
+          TargetedResult.EMPTY_LIST);
       return true;
     }
     return super.compute(entry, result);
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index 3401fbe..01f9495 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -15,7 +15,6 @@
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/src/context/cache.dart';
-import 'package:analyzer/src/context/context.dart';
 import 'package:analyzer/src/dart/ast/ast.dart'
     show NamespaceDirectiveImpl, UriBasedDirectiveImpl;
 import 'package:analyzer/src/dart/ast/utilities.dart';
@@ -1871,22 +1870,11 @@
   void internalPerform() {
     LibraryElement coreLibrary = getRequiredInput(CORE_INPUT);
     LibraryElement asyncLibrary = getOptionalInput(ASYNC_INPUT);
-    if (asyncLibrary == null) {
-      Source asyncSource = context.sourceFactory.forUri(DartSdk.DART_ASYNC);
-      asyncLibrary = (context as AnalysisContextImpl)
-          .createMockAsyncLib(coreLibrary, asyncSource);
-    }
     Namespace coreNamespace = coreLibrary.publicNamespace;
     Namespace asyncNamespace = asyncLibrary.publicNamespace;
     //
     // Record outputs.
     //
-    if (!context.analysisOptions.enableAsync) {
-      AnalysisContextImpl contextImpl = context;
-      Source asyncSource = context.sourceFactory.forUri(DartSdk.DART_ASYNC);
-      asyncLibrary = contextImpl.createMockAsyncLib(coreLibrary, asyncSource);
-      asyncNamespace = asyncLibrary.publicNamespace;
-    }
     TypeProvider typeProvider =
         new TypeProviderImpl.forNamespaces(coreNamespace, asyncNamespace);
     (context as InternalAnalysisContext).typeProvider = typeProvider;
@@ -3172,7 +3160,7 @@
     TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
 
     unit.accept(new BestPracticesVerifier(
-        errorReporter, typeProvider, libraryElement,
+        errorReporter, typeProvider, libraryElement, inheritanceManager,
         typeSystem: typeSystem));
     unit.accept(new OverrideVerifier(errorReporter, inheritanceManager));
     // Find to-do comments.
@@ -4017,7 +4005,6 @@
     Parser parser = new Parser(_source, errorListener);
     AnalysisOptions options = context.analysisOptions;
     parser.enableAssertInitializer = options.enableAssertInitializer;
-    parser.parseAsync = options.enableAsync;
     parser.parseFunctionBodies =
         options.analyzeFunctionBodiesPredicate(_source);
     parser.parseGenericMethods = options.enableGenericMethods;
diff --git a/pkg/analyzer/lib/src/task/options.dart b/pkg/analyzer/lib/src/task/options.dart
index 5ed99dc..4047b3b 100644
--- a/pkg/analyzer/lib/src/task/options.dart
+++ b/pkg/analyzer/lib/src/task/options.dart
@@ -498,14 +498,6 @@
         context.analysisOptions = options;
       }
     }
-    if (feature == AnalyzerOptions.enableAsync) {
-      if (isFalse(value)) {
-        AnalysisOptionsImpl options =
-            new AnalysisOptionsImpl.from(context.analysisOptions);
-        options.enableAsync = false;
-        context.analysisOptions = options;
-      }
-    }
     if (feature == AnalyzerOptions.enableStrictCallChecks) {
       if (isTrue(value)) {
         AnalysisOptionsImpl options =
@@ -574,8 +566,6 @@
     if (boolValue != null) {
       if (feature == AnalyzerOptions.enableAssertInitializer) {
         options.enableAssertInitializer = boolValue;
-      } else if (feature == AnalyzerOptions.enableAsync) {
-        options.enableAsync = boolValue;
       } else if (feature == AnalyzerOptions.enableInitializingFormalAccess) {
         options.enableInitializingFormalAccess = boolValue;
       } else if (feature == AnalyzerOptions.enableSuperMixins) {
diff --git a/pkg/analyzer/lib/src/task/strong/ast_properties.dart b/pkg/analyzer/lib/src/task/strong/ast_properties.dart
index 52f27f1..0f93ada 100644
--- a/pkg/analyzer/lib/src/task/strong/ast_properties.dart
+++ b/pkg/analyzer/lib/src/task/strong/ast_properties.dart
@@ -10,6 +10,7 @@
 import 'package:analyzer/analyzer.dart';
 import 'package:analyzer/dart/element/type.dart';
 
+const String _implicitAssignmentCast = '_implicitAssignmentCast';
 const String _implicitCast = '_implicitCast';
 const String _hasImplicitCasts = '_hasImplicitCasts';
 const String _isDynamicInvoke = '_isDynamicInvoke';
@@ -37,6 +38,17 @@
   node.setProperty(_implicitCast, type);
 }
 
+/// If this op-assign has an implicit cast on the assignment, returns the type
+/// it is coerced to, otherwise returns null.
+DartType getImplicitAssignmentCast(Expression node) {
+  return node.getProperty/*<DartType>*/(_implicitAssignmentCast);
+}
+
+/// Sets the result of [getImplicitAssignmentCast] for this node.
+void setImplicitAssignmentCast(Expression node, DartType type) {
+  node.setProperty(_implicitAssignmentCast, type);
+}
+
 /// True if this node is a dynamic operation that requires dispatch and/or
 /// checking at runtime.
 bool isDynamicInvoke(Expression node) {
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index 1183ce3..b32ff6e 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -13,7 +13,6 @@
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/error/codes.dart' show StrongModeCode;
 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
@@ -187,9 +186,7 @@
         // so no need to insert an error for this here.
         continue;
       }
-      DartType expectedType = _elementType(element);
-      if (expectedType == null) expectedType = DynamicTypeImpl.instance;
-      checkArgument(arg, expectedType);
+      checkArgument(arg, _elementType(element));
     }
   }
 
@@ -197,7 +194,7 @@
     if (expr is ParenthesizedExpression) {
       checkAssignment(expr.expression, type);
     } else {
-      _checkDowncast(expr, type);
+      _checkImplicitCast(expr, type);
     }
   }
 
@@ -410,7 +407,7 @@
             sequenceInterface.instantiate([DynamicTypeImpl.instance]);
 
         if (rules.isSubtypeOf(sequenceType, iterableType)) {
-          _recordImplicitCast(node.iterable, iterableType, sequenceType);
+          _recordImplicitCast(node.iterable, sequenceType, from: iterableType);
           elementType = DynamicTypeImpl.instance;
         }
       }
@@ -420,7 +417,7 @@
       if (elementType != null) {
         // Insert a cast from the sequence's element type to the loop variable's
         // if needed.
-        _checkDowncast(loopVariable, _getDefiniteType(loopVariable),
+        _checkImplicitCast(loopVariable, _getDefiniteType(loopVariable),
             from: elementType);
       }
     }
@@ -578,7 +575,7 @@
 
   @override
   void visitPostfixExpression(PostfixExpression node) {
-    _checkUnary(node, node.staticElement);
+    _checkUnary(node.operand, node.operator, node.staticElement);
     node.visitChildren(this);
   }
 
@@ -592,7 +589,7 @@
     if (node.operator.type == TokenType.BANG) {
       checkBoolean(node.operand);
     } else {
-      _checkUnary(node, node.staticElement);
+      _checkUnary(node.operand, node.operator, node.staticElement);
     }
     node.visitChildren(this);
   }
@@ -700,72 +697,75 @@
       assert(functionType.namedParameterTypes.isEmpty);
       assert(functionType.optionalParameterTypes.isEmpty);
 
-      // Check the LHS type.
+      // Refine the return type.
       var rhsType = _getDefiniteType(expr.rightHandSide);
       var lhsType = _getDefiniteType(expr.leftHandSide);
       var returnType = rules.refineBinaryExpressionType(
           typeProvider, lhsType, op, rhsType, functionType.returnType);
 
-      if (!rules.isSubtypeOf(returnType, lhsType)) {
-        final numType = typeProvider.numType;
-        // TODO(jmesserly): this seems to duplicate logic in StaticTypeAnalyzer.
-        // Try to fix up the numerical case if possible.
-        if (rules.isSubtypeOf(lhsType, numType) &&
-            rules.isSubtypeOf(lhsType, rhsType)) {
-          // This is also slightly different from spec, but allows us to keep
-          // compound operators in the int += num and num += dynamic cases.
-          _recordImplicitCast(expr.rightHandSide, rhsType, lhsType);
-        } else {
-          // TODO(jmesserly): this results in a duplicate error, because
-          // ErrorVerifier also reports it.
-          _recordMessage(expr, StrongModeCode.STATIC_TYPE_ERROR,
-              [expr, returnType, lhsType]);
-        }
-      } else {
-        // Check the RHS type.
-        //
-        // This is only needed if we didn't already need a cast, and avoids
-        // emitting two messages for the same expression.
-        _checkDowncast(expr.rightHandSide, paramTypes.first);
-      }
+      // Check the argument for an implicit cast.
+      _checkImplicitCast(expr.rightHandSide, paramTypes[0], from: rhsType);
+
+      // Check the return type for an implicit cast.
+      //
+      // If needed, mark the assignment to indicate a down cast when we assign
+      // back to it. So these two implicit casts are equivalent:
+      //
+      //     y = /*implicit cast*/(y + 42);
+      //     /*implicit assignment cast*/y += 42;
+      //
+      _checkImplicitCast(expr.leftHandSide, lhsType,
+          from: returnType, opAssign: true);
     }
   }
 
-  /// Records a [DownCast] of [expr] from [from] to [to], if there is one.
+  /// Returns true if we need an implicit cast of [expr] from [from] type to
+  /// [to] type, otherwise returns false.
   ///
   /// If [from] is omitted, uses the static type of [expr].
-  ///
-  /// If [expr] does not require a downcast because it is not related to [to]
-  /// or is already a subtype of it, does nothing.
-  void _checkDowncast(Expression expr, DartType to, {DartType from}) {
-    if (from == null) {
-      from = _getDefiniteType(expr);
-    }
+  bool _needsImplicitCast(Expression expr, DartType to, {DartType from}) {
+    from ??= _getDefiniteType(expr);
 
-    if (!_checkNonNullAssignment(expr, to, from)) return;
+    if (!_checkNonNullAssignment(expr, to, from)) return false;
 
     // We can use anything as void.
-    if (to.isVoid) return;
+    if (to.isVoid) return false;
 
     // fromT <: toT, no coercion needed.
-    if (rules.isSubtypeOf(from, to)) return;
+    if (rules.isSubtypeOf(from, to)) return false;
 
     // Note: a function type is never assignable to a class per the Dart
     // spec - even if it has a compatible call method.  We disallow as
     // well for consistency.
     if (from is FunctionType && rules.getCallMethodType(to) != null) {
-      return;
+      return false;
     }
 
     // Downcast if toT <: fromT
     if (rules.isSubtypeOf(to, from)) {
-      _recordImplicitCast(expr, from, to);
-      return;
+      return true;
     }
 
     // Anything else is an illegal sideways cast.
     // However, these will have been reported already in error_verifier, so we
     // don't need to report them again.
+    return false;
+  }
+
+  /// Checks if an implicit cast of [expr] from [from] type to [to] type is
+  /// needed, and if so records it.
+  ///
+  /// If [from] is omitted, uses the static type of [expr].
+  ///
+  /// If [expr] does not require an implicit cast because it is not related to
+  /// [to] or is already a subtype of it, does nothing.
+  void _checkImplicitCast(Expression expr, DartType to,
+      {DartType from, bool opAssign: false}) {
+    from ??= _getDefiniteType(expr);
+
+    if (_needsImplicitCast(expr, to, from: from)) {
+      _recordImplicitCast(expr, to, from: from, opAssign: opAssign);
+    }
   }
 
   void _checkFieldAccess(AstNode node, AstNode target, SimpleIdentifier field) {
@@ -909,19 +909,39 @@
     }
   }
 
-  void _checkUnary(
-      /*PrefixExpression|PostfixExpression*/ node,
-      Element element) {
-    var op = node.operator;
-    if (op.isUserDefinableOperator ||
-        op.type == TokenType.PLUS_PLUS ||
-        op.type == TokenType.MINUS_MINUS) {
+  void _checkUnary(Expression operand, Token op, MethodElement element) {
+    bool isIncrementAssign =
+        op.type == TokenType.PLUS_PLUS || op.type == TokenType.MINUS_MINUS;
+    if (op.isUserDefinableOperator || isIncrementAssign) {
       if (element == null) {
-        _recordDynamicInvoke(node, node.operand);
+        _recordDynamicInvoke(operand.parent, operand);
+      } else if (isIncrementAssign) {
+        // For ++ and --, even if it is not dynamic, we still need to check
+        // that the user defined method accepts an `int` as the RHS.
+        //
+        // We assume Analyzer has done this already (in ErrorVerifier).
+        //
+        // However, we also need to check the return type.
+
+        // Refine the return type.
+        var functionType = element.type;
+        var rhsType = typeProvider.intType;
+        var lhsType = _getDefiniteType(operand);
+        var returnType = rules.refineBinaryExpressionType(typeProvider, lhsType,
+            TokenType.PLUS, rhsType, functionType.returnType);
+
+        // Skip the argument check - `int` cannot be downcast.
+        //
+        // Check the return type for an implicit cast.
+        //
+        // If needed, mark the assignment to indicate a down cast when we assign
+        // back to it. So these two implicit casts are equivalent:
+        //
+        //     y = /*implicit cast*/(y + 1);
+        //     /*implicit assignment cast*/y++;
+        //
+        _checkImplicitCast(operand, lhsType, from: returnType, opAssign: true);
       }
-      // For ++ and --, even if it is not dynamic, we still need to check
-      // that the user defined method accepts an `int` as the RHS.
-      // We assume Analyzer has done this already.
     }
   }
 
@@ -1022,61 +1042,49 @@
     if (target != null) setIsDynamicInvoke(target, true);
   }
 
-  /// Records an implicit cast for the [expression] from [fromType] to [toType].
+  /// Records an implicit cast for the [expr] from [from] to [to].
   ///
   /// This will emit the appropriate error/warning/hint message as well as mark
   /// the AST node.
-  void _recordImplicitCast(
-      Expression expression, DartType fromType, DartType toType) {
-    // toT <:_R fromT => to <: fromT
-    // NB: classes with call methods are subtypes of function
-    // types, but the function type is not assignable to the class
-    assert(toType.isSubtypeOf(fromType));
+  void _recordImplicitCast(Expression expr, DartType to,
+      {DartType from, bool opAssign: false}) {
+    assert(rules.isSubtypeOf(to, from));
 
     // Inference "casts":
-    if (expression is Literal || expression is FunctionExpression) {
+    if (expr is Literal || expr is FunctionExpression) {
       // fromT should be an exact type - this will almost certainly fail at
       // runtime.
-      _recordMessage(expression, StrongModeCode.STATIC_TYPE_ERROR,
-          [expression, fromType, toType]);
+      _recordMessage(expr, StrongModeCode.STATIC_TYPE_ERROR, [expr, from, to]);
       return;
     }
 
-    if (expression is InstanceCreationExpression) {
-      ConstructorElement e = expression.staticElement;
+    if (expr is InstanceCreationExpression) {
+      ConstructorElement e = expr.staticElement;
       if (e == null || !e.isFactory) {
         // fromT should be an exact type - this will almost certainly fail at
         // runtime.
 
-        _recordMessage(expression, StrongModeCode.STATIC_TYPE_ERROR,
-            [expression, fromType, toType]);
+        _recordMessage(
+            expr, StrongModeCode.STATIC_TYPE_ERROR, [expr, from, to]);
         return;
       }
     }
 
-    if (isKnownFunction(expression)) {
-      _recordMessage(expression, StrongModeCode.STATIC_TYPE_ERROR,
-          [expression, fromType, toType]);
+    if (isKnownFunction(expr)) {
+      _recordMessage(expr, StrongModeCode.STATIC_TYPE_ERROR, [expr, from, to]);
       return;
     }
 
-    // TODO(vsm): Change this to an assert when we have generic methods and
-    // fix TypeRules._coerceTo to disallow implicit sideways casts.
-    bool downCastComposite = false;
-    if (!rules.isSubtypeOf(toType, fromType)) {
-      assert(toType.isSubtypeOf(fromType) || fromType.isAssignableTo(toType));
-      downCastComposite = true;
-    }
-
     // Composite cast: these are more likely to fail.
-    if (!rules.isGroundType(toType)) {
+    bool downCastComposite = false;
+    if (!rules.isGroundType(to)) {
       // This cast is (probably) due to our different treatment of dynamic.
       // It may be more likely to fail at runtime.
-      if (fromType is InterfaceType) {
+      if (from is InterfaceType) {
         // For class types, we'd like to allow non-generic down casts, e.g.,
         // Iterable<T> to List<T>.  The intuition here is that raw (generic)
         // casts are problematic, and we should complain about those.
-        var typeArgs = fromType.typeArguments;
+        var typeArgs = from.typeArguments;
         downCastComposite =
             typeArgs.isEmpty || typeArgs.any((t) => t.isDynamic);
       } else {
@@ -1084,21 +1092,25 @@
       }
     }
 
-    var parent = expression.parent;
+    var parent = expr.parent;
     ErrorCode errorCode;
     if (downCastComposite) {
       errorCode = StrongModeCode.DOWN_CAST_COMPOSITE;
-    } else if (fromType.isDynamic) {
+    } else if (from.isDynamic) {
       errorCode = StrongModeCode.DYNAMIC_CAST;
-    } else if (parent is VariableDeclaration &&
-        parent.initializer == expression) {
+    } else if (parent is VariableDeclaration && parent.initializer == expr) {
       errorCode = StrongModeCode.ASSIGNMENT_CAST;
     } else {
-      errorCode = StrongModeCode.DOWN_CAST_IMPLICIT;
+      errorCode = opAssign
+          ? StrongModeCode.DOWN_CAST_IMPLICIT_ASSIGN
+          : StrongModeCode.DOWN_CAST_IMPLICIT;
     }
-
-    _recordMessage(expression, errorCode, [fromType, toType]);
-    setImplicitCast(expression, toType);
+    _recordMessage(expr, errorCode, [from, to]);
+    if (opAssign) {
+      setImplicitAssignmentCast(expr, to);
+    } else {
+      setImplicitCast(expr, to);
+    }
     _hasImplicitCasts = true;
   }
 
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 5a98fbf..6521345 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 0.29.0-alpha.0
+version: 0.29.0-alpha.1
 author: Dart Team <misc@dartlang.org>
 description: Static analyzer for Dart.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
diff --git a/pkg/analyzer/test/enum_test.dart b/pkg/analyzer/test/enum_test.dart
deleted file mode 100644
index 6996ee0..0000000
--- a/pkg/analyzer/test/enum_test.dart
+++ /dev/null
@@ -1,210 +0,0 @@
-// 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.
-
-library analyzer.test.enum_test;
-
-import 'dart:mirrors';
-
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/error/error.dart';
-import 'package:analyzer/src/dart/element/element.dart';
-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/source.dart';
-import 'package:analyzer/src/generated/utilities_dart.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-import 'package:unittest/unittest.dart';
-
-import 'utils.dart';
-
-void main() {
-  initializeTestEnvironment();
-  defineReflectiveTests(EnumTest);
-}
-
-@reflectiveTest
-class EnumTest {
-  void test_AnalysisLevel() {
-    new EnumTester<AnalysisLevel>()
-      ..check_getters()
-      ..check_explicit_values();
-  }
-
-  void test_CacheState() {
-    new EnumTester<CacheState>()
-      ..check_getters()
-      ..check_explicit_values();
-  }
-
-  void test_ElementKind() {
-    new EnumTester<ElementKind>()
-      ..check_getters()
-      ..check_explicit_values();
-  }
-
-  void test_ErrorProperty() {
-    new EnumTester<ErrorProperty>()
-      ..check_getters()
-      ..check_explicit_values();
-  }
-
-  void test_ErrorSeverity() {
-    new EnumTester<ErrorSeverity>()
-      ..check_getters()
-      ..check_explicit_values();
-  }
-
-  void test_ErrorType() {
-    new EnumTester<ErrorType>()
-      ..check_getters()
-      ..check_explicit_values();
-  }
-
-  void test_INIT_STATE() {
-    new EnumTester<INIT_STATE>()
-      ..check_getters()
-      ..check_explicit_values();
-  }
-
-  void test_Modifier() {
-    new EnumTester<Modifier>(
-        ignoreGetters: ["persistedValues", "transientValues"])
-      ..check_getters()
-      ..check_explicit_values();
-  }
-
-  void test_ParameterKind() {
-    new EnumTester<ParameterKind>()
-      ..check_getters()
-      ..check_explicit_values();
-  }
-
-  void test_RedirectingConstructorKind() {
-    new EnumTester<RedirectingConstructorKind>()
-      ..check_getters()
-      ..check_explicit_values();
-  }
-
-  void test_SourceKind() {
-    new EnumTester<SourceKind>()
-      ..check_getters()
-      ..check_explicit_values();
-  }
-
-  void test_UriKind() {
-    new EnumTester<UriKind>()
-      ..check_getters()
-      ..check_explicit_values();
-  }
-}
-
-/**
- * Helper class for testing invariants of enumerated types.
- */
-class EnumTester<C extends Enum> {
-  /**
-   * Set of getter names which should be ignored when looking for getters
-   * representing enum values.
-   */
-  Set<String> _ignoreGetters = new Set<String>();
-
-  EnumTester({List<String> ignoreGetters}) {
-    // Always ignore a getter called "values".
-    _ignoreGetters.add('values');
-
-    if (ignoreGetters != null) {
-      for (String getterName in ignoreGetters) {
-        _ignoreGetters.add(getterName);
-      }
-    }
-  }
-
-  /**
-   * Get a map from getter name to the value returned by the getter, for all
-   * static getters in [C] whose name isn't in [_ignoreGetters].
-   */
-  Map<String, C> get _getters {
-    Map<String, C> result = <String, C>{};
-    ClassMirror reflectedClass = reflectClass(C);
-    reflectedClass.staticMembers.forEach((Symbol symbol, MethodMirror method) {
-      if (!method.isGetter) {
-        return;
-      }
-      String name = MirrorSystem.getName(symbol);
-      if (_ignoreGetters.contains(name)) {
-        return;
-      }
-      C value = reflectedClass.getField(symbol).reflectee as C;
-      result[name] = value;
-    });
-    return result;
-  }
-
-  /**
-   * Check invariants on the list of enum values accessible via the static
-   * getter "values".
-   */
-  void check_explicit_values() {
-    ClassMirror reflectedClass = reflectClass(C);
-    List<C> values = reflectedClass.getField(#values).reflectee as List<C>;
-    Map<C, int> reverseMap = <C, int>{};
-
-    // Check that "values" is a list of values of type C, with no duplicates.
-    expect(values, isList);
-    for (int i = 0; i < values.length; i++) {
-      C value = values[i];
-      expect(value, new isInstanceOf<C>(), reason: 'values[$i]');
-      if (reverseMap.containsKey(value)) {
-        fail('values[$i] and values[${reverseMap[value]}] both equal $value');
-      }
-      reverseMap[value] = i;
-    }
-
-    // Check that the set of values in the "values" list matches the set of
-    // values accessible via static fields.
-    expect(reverseMap.keys.toSet(), equals(_getters.values.toSet()));
-
-    // Make sure the order of the list matches the ordinal numbers.
-    for (int i = 0; i < values.length; i++) {
-      expect(values[i].ordinal, equals(i), reason: 'values[$i].ordinal');
-    }
-  }
-
-  /**
-   * Check invariants on the set of enum values accessible via the static
-   * getters defined in the class [C] (with the exception of a getter called
-   * "values").
-   */
-  void check_getters() {
-    Map<int, String> ordinals = <int, String>{};
-    int numValues = 0;
-
-    _getters.forEach((String name, C value) {
-      String reason = 'getter: $name';
-      ++numValues;
-
-      // Check the type of the value
-      expect(value, new isInstanceOf<C>(), reason: reason);
-
-      // Check that the name of the getter matches the name stored in the enum.
-      expect(value.name, equals(name), reason: reason);
-
-      // Check that there are no duplicate ordinals.
-      if (ordinals.containsKey(value.ordinal)) {
-        fail(
-            'Getters $name and ${ordinals[value.ordinal]} have ordinal value ${value.ordinal}');
-      }
-      ordinals[value.ordinal] = name;
-    });
-
-    // Check that the set of ordinals runs from 0 to N-1, where N is the number
-    // of enumerated values.
-    Set<int> expectedOrdinals = new Set<int>();
-    for (int i = 0; i < numValues; i++) {
-      expectedOrdinals.add(i);
-    }
-    expect(ordinals.keys.toSet(), equals(expectedOrdinals));
-  }
-}
diff --git a/pkg/analyzer/test/generated/analysis_context_factory.dart b/pkg/analyzer/test/generated/analysis_context_factory.dart
index 78c62e9..272e26e 100644
--- a/pkg/analyzer/test/generated/analysis_context_factory.dart
+++ b/pkg/analyzer/test/generated/analysis_context_factory.dart
@@ -90,8 +90,7 @@
       ResourceProvider resourceProvider]) {
     resourceProvider ??= PhysicalResourceProvider.INSTANCE;
     DartSdk sdk = new _AnalysisContextFactory_initContextWithCore(
-        resourceProvider, '/fake/sdk',
-        enableAsync: context.analysisOptions.enableAsync);
+        resourceProvider, '/fake/sdk');
     List<UriResolver> resolvers = <UriResolver>[
       new DartUriResolver(sdk),
       new ResourceUriResolver(resourceProvider)
@@ -184,104 +183,94 @@
     //
     // dart:async
     //
-    Source asyncSource;
-    LibraryElementImpl asyncLibrary;
-    if (context.analysisOptions.enableAsync) {
-      asyncLibrary = new LibraryElementImpl.forNode(
-          coreContext, AstFactory.libraryIdentifier2(["dart", "async"]));
-      CompilationUnitElementImpl asyncUnit =
-          new CompilationUnitElementImpl("async.dart");
-      asyncSource = sourceFactory.forUri(DartSdk.DART_ASYNC);
-      coreContext.setContents(asyncSource, "");
-      asyncUnit.librarySource = asyncUnit.source = asyncSource;
-      asyncLibrary.definingCompilationUnit = asyncUnit;
-      // Future
-      ClassElementImpl futureElement =
-          ElementFactory.classElement2("Future", ["T"]);
-      futureElement.enclosingElement = asyncUnit;
-      //   factory Future.value([value])
-      ConstructorElementImpl futureConstructor =
-          ElementFactory.constructorElement2(futureElement, "value");
-      futureConstructor.parameters = <ParameterElement>[
-        ElementFactory.positionalParameter2("value", provider.dynamicType)
-      ];
-      futureConstructor.factory = true;
-      futureElement.constructors = <ConstructorElement>[futureConstructor];
-      //   Future then(onValue(T value), { Function onError });
-      TypeDefiningElement futureThenR = DynamicElementImpl.instance;
-      if (context.analysisOptions.strongMode) {
-        futureThenR = ElementFactory.typeParameterWithType('R');
-      }
-      FunctionElementImpl thenOnValue = ElementFactory.functionElement3(
-          'onValue',
-          DynamicElementImpl.instance,
-          [futureElement.typeParameters[0]],
-          null);
-      thenOnValue.synthetic = true;
-
-      DartType futureRType = futureElement.type.instantiate([futureThenR.type]);
-      MethodElementImpl thenMethod = ElementFactory
-          .methodElementWithParameters(futureElement, "then", futureRType, [
-        ElementFactory.requiredParameter2("onValue", thenOnValue.type),
-        ElementFactory.namedParameter2("onError", provider.functionType)
-      ]);
-      if (!futureThenR.type.isDynamic) {
-        thenMethod.typeParameters = <TypeParameterElement>[futureThenR];
-      }
-      thenOnValue.enclosingElement = thenMethod;
-      thenOnValue.type = new FunctionTypeImpl(thenOnValue);
-      (thenMethod.parameters[0] as ParameterElementImpl).type =
-          thenOnValue.type;
-      thenMethod.type = new FunctionTypeImpl(thenMethod);
-
-      futureElement.methods = <MethodElement>[thenMethod];
-      // Completer
-      ClassElementImpl completerElement =
-          ElementFactory.classElement2("Completer", ["T"]);
-      ConstructorElementImpl completerConstructor =
-          ElementFactory.constructorElement2(completerElement, null);
-      completerElement.constructors = <ConstructorElement>[
-        completerConstructor
-      ];
-      // StreamSubscription
-      ClassElementImpl streamSubscriptionElement =
-          ElementFactory.classElement2("StreamSubscription", ["T"]);
-      // Stream
-      ClassElementImpl streamElement =
-          ElementFactory.classElement2("Stream", ["T"]);
-      streamElement.constructors = <ConstructorElement>[
-        ElementFactory.constructorElement2(streamElement, null)
-      ];
-      DartType returnType = streamSubscriptionElement.type
-          .instantiate(streamElement.type.typeArguments);
-      FunctionElementImpl listenOnData = ElementFactory.functionElement3(
-          'onData',
-          VoidTypeImpl.instance.element,
-          <TypeDefiningElement>[streamElement.typeParameters[0]],
-          null);
-      listenOnData.synthetic = true;
-      List<DartType> parameterTypes = <DartType>[
-        listenOnData.type,
-      ];
-      // TODO(brianwilkerson) This is missing the optional parameters.
-      MethodElementImpl listenMethod =
-          ElementFactory.methodElement('listen', returnType, parameterTypes);
-      streamElement.methods = <MethodElement>[listenMethod];
-      listenMethod.type = new FunctionTypeImpl(listenMethod);
-
-      FunctionElementImpl listenParamFunction = parameterTypes[0].element;
-      listenParamFunction.enclosingElement = listenMethod;
-      listenParamFunction.type = new FunctionTypeImpl(listenParamFunction);
-      ParameterElementImpl listenParam = listenMethod.parameters[0];
-      listenParam.type = listenParamFunction.type;
-
-      asyncUnit.types = <ClassElement>[
-        completerElement,
-        futureElement,
-        streamElement,
-        streamSubscriptionElement
-      ];
+    LibraryElementImpl asyncLibrary = new LibraryElementImpl.forNode(
+        coreContext, AstFactory.libraryIdentifier2(["dart", "async"]));
+    CompilationUnitElementImpl asyncUnit =
+        new CompilationUnitElementImpl("async.dart");
+    Source asyncSource = sourceFactory.forUri(DartSdk.DART_ASYNC);
+    coreContext.setContents(asyncSource, "");
+    asyncUnit.librarySource = asyncUnit.source = asyncSource;
+    asyncLibrary.definingCompilationUnit = asyncUnit;
+    // Future
+    ClassElementImpl futureElement =
+        ElementFactory.classElement2("Future", ["T"]);
+    futureElement.enclosingElement = asyncUnit;
+    //   factory Future.value([value])
+    ConstructorElementImpl futureConstructor =
+        ElementFactory.constructorElement2(futureElement, "value");
+    futureConstructor.parameters = <ParameterElement>[
+      ElementFactory.positionalParameter2("value", provider.dynamicType)
+    ];
+    futureConstructor.factory = true;
+    futureElement.constructors = <ConstructorElement>[futureConstructor];
+    //   Future then(onValue(T value), { Function onError });
+    TypeDefiningElement futureThenR = DynamicElementImpl.instance;
+    if (context.analysisOptions.strongMode) {
+      futureThenR = ElementFactory.typeParameterWithType('R');
     }
+    FunctionElementImpl thenOnValue = ElementFactory.functionElement3('onValue',
+        DynamicElementImpl.instance, [futureElement.typeParameters[0]], null);
+    thenOnValue.synthetic = true;
+
+    DartType futureRType = futureElement.type.instantiate([futureThenR.type]);
+    MethodElementImpl thenMethod = ElementFactory
+        .methodElementWithParameters(futureElement, "then", futureRType, [
+      ElementFactory.requiredParameter2("onValue", thenOnValue.type),
+      ElementFactory.namedParameter2("onError", provider.functionType)
+    ]);
+    if (!futureThenR.type.isDynamic) {
+      thenMethod.typeParameters = <TypeParameterElement>[futureThenR];
+    }
+    thenOnValue.enclosingElement = thenMethod;
+    thenOnValue.type = new FunctionTypeImpl(thenOnValue);
+    (thenMethod.parameters[0] as ParameterElementImpl).type = thenOnValue.type;
+    thenMethod.type = new FunctionTypeImpl(thenMethod);
+
+    futureElement.methods = <MethodElement>[thenMethod];
+    // Completer
+    ClassElementImpl completerElement =
+        ElementFactory.classElement2("Completer", ["T"]);
+    ConstructorElementImpl completerConstructor =
+        ElementFactory.constructorElement2(completerElement, null);
+    completerElement.constructors = <ConstructorElement>[completerConstructor];
+    // StreamSubscription
+    ClassElementImpl streamSubscriptionElement =
+        ElementFactory.classElement2("StreamSubscription", ["T"]);
+    // Stream
+    ClassElementImpl streamElement =
+        ElementFactory.classElement2("Stream", ["T"]);
+    streamElement.constructors = <ConstructorElement>[
+      ElementFactory.constructorElement2(streamElement, null)
+    ];
+    DartType returnType = streamSubscriptionElement.type
+        .instantiate(streamElement.type.typeArguments);
+    FunctionElementImpl listenOnData = ElementFactory.functionElement3(
+        'onData',
+        VoidTypeImpl.instance.element,
+        <TypeDefiningElement>[streamElement.typeParameters[0]],
+        null);
+    listenOnData.synthetic = true;
+    List<DartType> parameterTypes = <DartType>[
+      listenOnData.type,
+    ];
+    // TODO(brianwilkerson) This is missing the optional parameters.
+    MethodElementImpl listenMethod =
+        ElementFactory.methodElement('listen', returnType, parameterTypes);
+    streamElement.methods = <MethodElement>[listenMethod];
+    listenMethod.type = new FunctionTypeImpl(listenMethod);
+
+    FunctionElementImpl listenParamFunction = parameterTypes[0].element;
+    listenParamFunction.enclosingElement = listenMethod;
+    listenParamFunction.type = new FunctionTypeImpl(listenParamFunction);
+    ParameterElementImpl listenParam = listenMethod.parameters[0];
+    listenParam.type = listenParamFunction.type;
+
+    asyncUnit.types = <ClassElement>[
+      completerElement,
+      futureElement,
+      streamElement,
+      streamSubscriptionElement
+    ];
     //
     // dart:html
     //
@@ -564,18 +553,14 @@
 }
 
 class _AnalysisContextFactory_initContextWithCore extends FolderBasedDartSdk {
-  final bool enableAsync;
   _AnalysisContextFactory_initContextWithCore(
-      ResourceProvider resourceProvider, String sdkPath,
-      {this.enableAsync: true})
+      ResourceProvider resourceProvider, String sdkPath)
       : super(resourceProvider, resourceProvider.getFolder(sdkPath));
 
   @override
   LibraryMap initialLibraryMap(bool useDart2jsPaths) {
     LibraryMap map = new LibraryMap();
-    if (enableAsync) {
-      _addLibrary(map, DartSdk.DART_ASYNC, false, "async.dart");
-    }
+    _addLibrary(map, DartSdk.DART_ASYNC, false, "async.dart");
     _addLibrary(map, DartSdk.DART_CORE, false, "core.dart");
     _addLibrary(map, DartSdk.DART_HTML, false, "html_dartium.dart");
     _addLibrary(map, AnalysisContextFactory._DART_MATH, false, "math.dart");
diff --git a/pkg/analyzer/test/generated/element_resolver_test.dart b/pkg/analyzer/test/generated/element_resolver_test.dart
index a562940..e911f73 100644
--- a/pkg/analyzer/test/generated/element_resolver_test.dart
+++ b/pkg/analyzer/test/generated/element_resolver_test.dart
@@ -23,14 +23,283 @@
 
 import '../utils.dart';
 import 'analysis_context_factory.dart';
+import 'resolver_test_case.dart';
 import 'test_support.dart';
 
 main() {
   initializeTestEnvironment();
+  defineReflectiveTests(ElementResolverCodeTest);
   defineReflectiveTests(ElementResolverTest);
 }
 
 @reflectiveTest
+class ElementResolverCodeTest extends ResolverTestCase {
+  void test_annotation_class_namedConstructor() {
+    addNamedSource(
+        '/a.dart',
+        r'''
+class A {
+  const A.named();
+}
+''');
+    _validateAnnotation('', '@A.named()', (SimpleIdentifier name1,
+        SimpleIdentifier name2,
+        SimpleIdentifier name3,
+        Element annotationElement) {
+      expect(name1, isNotNull);
+      expect(name1.staticElement, new isInstanceOf<ClassElement>());
+      expect(name1.staticElement.displayName, 'A');
+      expect(name2, isNotNull);
+      expect(name2.staticElement, new isInstanceOf<ConstructorElement>());
+      expect(name2.staticElement.displayName, 'named');
+      expect(name3, isNull);
+      if (annotationElement is ConstructorElement) {
+        expect(annotationElement, same(name2.staticElement));
+        expect(annotationElement.enclosingElement, name1.staticElement);
+        expect(annotationElement.displayName, 'named');
+        expect(annotationElement.parameters, isEmpty);
+      } else {
+        fail('Expected "annotationElement" is ConstructorElement, '
+            'but (${annotationElement?.runtimeType}) $annotationElement found.');
+      }
+    });
+  }
+
+  void test_annotation_class_prefixed_namedConstructor() {
+    addNamedSource(
+        '/a.dart',
+        r'''
+class A {
+  const A.named();
+}
+''');
+    _validateAnnotation('as p', '@p.A.named()', (SimpleIdentifier name1,
+        SimpleIdentifier name2,
+        SimpleIdentifier name3,
+        Element annotationElement) {
+      expect(name1, isNotNull);
+      expect(name1.staticElement, new isInstanceOf<PrefixElement>());
+      expect(name1.staticElement.displayName, 'p');
+      expect(name2, isNotNull);
+      expect(name2.staticElement, new isInstanceOf<ClassElement>());
+      expect(name2.staticElement.displayName, 'A');
+      expect(name3, isNotNull);
+      expect(name3.staticElement, new isInstanceOf<ConstructorElement>());
+      expect(name3.staticElement.displayName, 'named');
+      if (annotationElement is ConstructorElement) {
+        expect(annotationElement, same(name3.staticElement));
+        expect(annotationElement.enclosingElement, name2.staticElement);
+        expect(annotationElement.displayName, 'named');
+        expect(annotationElement.parameters, isEmpty);
+      } else {
+        fail('Expected "annotationElement" is ConstructorElement, '
+            'but (${annotationElement?.runtimeType}) $annotationElement found.');
+      }
+    });
+  }
+
+  void test_annotation_class_prefixed_staticConstField() {
+    addNamedSource(
+        '/a.dart',
+        r'''
+class A {
+  static const V = 0;
+}
+''');
+    _validateAnnotation('as p', '@p.A.V', (SimpleIdentifier name1,
+        SimpleIdentifier name2,
+        SimpleIdentifier name3,
+        Element annotationElement) {
+      expect(name1, isNotNull);
+      expect(name1.staticElement, new isInstanceOf<PrefixElement>());
+      expect(name1.staticElement.displayName, 'p');
+      expect(name2, isNotNull);
+      expect(name2.staticElement, new isInstanceOf<ClassElement>());
+      expect(name2.staticElement.displayName, 'A');
+      expect(name3, isNotNull);
+      expect(name3.staticElement, new isInstanceOf<PropertyAccessorElement>());
+      expect(name3.staticElement.displayName, 'V');
+      if (annotationElement is PropertyAccessorElement) {
+        expect(annotationElement, same(name3.staticElement));
+        expect(annotationElement.enclosingElement, name2.staticElement);
+        expect(annotationElement.displayName, 'V');
+      } else {
+        fail('Expected "annotationElement" is PropertyAccessorElement, '
+            'but (${annotationElement?.runtimeType}) $annotationElement found.');
+      }
+    });
+  }
+
+  void test_annotation_class_prefixed_unnamedConstructor() {
+    addNamedSource(
+        '/a.dart',
+        r'''
+class A {
+  const A();
+}
+''');
+    _validateAnnotation('as p', '@p.A', (SimpleIdentifier name1,
+        SimpleIdentifier name2,
+        SimpleIdentifier name3,
+        Element annotationElement) {
+      expect(name1, isNotNull);
+      expect(name1.staticElement, new isInstanceOf<PrefixElement>());
+      expect(name1.staticElement.displayName, 'p');
+      expect(name2, isNotNull);
+      expect(name2.staticElement, new isInstanceOf<ClassElement>());
+      expect(name2.staticElement.displayName, 'A');
+      expect(name3, isNull);
+      if (annotationElement is ConstructorElement) {
+        expect(annotationElement.enclosingElement, name2.staticElement);
+        expect(annotationElement.displayName, '');
+        expect(annotationElement.parameters, isEmpty);
+      } else {
+        fail('Expected "annotationElement" is ConstructorElement, '
+            'but (${annotationElement?.runtimeType}) $annotationElement found.');
+      }
+    });
+  }
+
+  void test_annotation_class_staticConstField() {
+    addNamedSource(
+        '/a.dart',
+        r'''
+class A {
+  static const V = 0;
+}
+''');
+    _validateAnnotation('', '@A.V', (SimpleIdentifier name1,
+        SimpleIdentifier name2,
+        SimpleIdentifier name3,
+        Element annotationElement) {
+      expect(name1, isNotNull);
+      expect(name1.staticElement, new isInstanceOf<ClassElement>());
+      expect(name1.staticElement.displayName, 'A');
+      expect(name2, isNotNull);
+      expect(name2.staticElement, new isInstanceOf<PropertyAccessorElement>());
+      expect(name2.staticElement.displayName, 'V');
+      expect(name3, isNull);
+      if (annotationElement is PropertyAccessorElement) {
+        expect(annotationElement, same(name2.staticElement));
+        expect(annotationElement.enclosingElement, name1.staticElement);
+        expect(annotationElement.displayName, 'V');
+      } else {
+        fail('Expected "annotationElement" is PropertyAccessorElement, '
+            'but (${annotationElement?.runtimeType}) $annotationElement found.');
+      }
+    });
+  }
+
+  void test_annotation_class_unnamedConstructor() {
+    addNamedSource(
+        '/a.dart',
+        r'''
+class A {
+  const A();
+}
+''');
+    _validateAnnotation('', '@A', (SimpleIdentifier name1,
+        SimpleIdentifier name2,
+        SimpleIdentifier name3,
+        Element annotationElement) {
+      expect(name1, isNotNull);
+      expect(name1.staticElement, new isInstanceOf<ClassElement>());
+      expect(name1.staticElement.displayName, 'A');
+      expect(name2, isNull);
+      expect(name3, isNull);
+      if (annotationElement is ConstructorElement) {
+        expect(annotationElement.enclosingElement, name1.staticElement);
+        expect(annotationElement.displayName, '');
+        expect(annotationElement.parameters, isEmpty);
+      } else {
+        fail('Expected "annotationElement" is ConstructorElement, '
+            'but (${annotationElement?.runtimeType}) $annotationElement found.');
+      }
+    });
+  }
+
+  void test_annotation_topLevelVariable() {
+    addNamedSource(
+        '/a.dart',
+        r'''
+const V = 0;
+''');
+    _validateAnnotation('', '@V', (SimpleIdentifier name1,
+        SimpleIdentifier name2,
+        SimpleIdentifier name3,
+        Element annotationElement) {
+      expect(name1, isNotNull);
+      expect(name1.staticElement, new isInstanceOf<PropertyAccessorElement>());
+      expect(name1.staticElement.displayName, 'V');
+      expect(name2, isNull);
+      expect(name3, isNull);
+      if (annotationElement is PropertyAccessorElement) {
+        expect(annotationElement, same(name1.staticElement));
+        expect(annotationElement.enclosingElement,
+            new isInstanceOf<CompilationUnitElement>());
+        expect(annotationElement.displayName, 'V');
+      } else {
+        fail('Expected "annotationElement" is PropertyAccessorElement, '
+            'but (${annotationElement?.runtimeType}) $annotationElement found.');
+      }
+    });
+  }
+
+  void test_annotation_topLevelVariable_prefixed() {
+    addNamedSource(
+        '/a.dart',
+        r'''
+const V = 0;
+''');
+    _validateAnnotation('as p', '@p.V', (SimpleIdentifier name1,
+        SimpleIdentifier name2,
+        SimpleIdentifier name3,
+        Element annotationElement) {
+      expect(name1, isNotNull);
+      expect(name1.staticElement, new isInstanceOf<PrefixElement>());
+      expect(name1.staticElement.displayName, 'p');
+      expect(name2, isNotNull);
+      expect(name2.staticElement, new isInstanceOf<PropertyAccessorElement>());
+      expect(name2.staticElement.displayName, 'V');
+      expect(name3, isNull);
+      if (annotationElement is PropertyAccessorElement) {
+        expect(annotationElement, same(name2.staticElement));
+        expect(annotationElement.enclosingElement,
+            new isInstanceOf<CompilationUnitElement>());
+        expect(annotationElement.displayName, 'V');
+      } else {
+        fail('Expected "annotationElement" is PropertyAccessorElement, '
+            'but (${annotationElement?.runtimeType}) $annotationElement found.');
+      }
+    });
+  }
+
+  void _validateAnnotation(
+      String annotationPrefix,
+      String annotationText,
+      validator(SimpleIdentifier name1, SimpleIdentifier name2,
+          SimpleIdentifier name3, Element annotationElement)) {
+    CompilationUnit unit = resolveSource('''
+import 'a.dart' $annotationPrefix;
+$annotationText
+class C {}
+''');
+    var clazz = unit.declarations.single as ClassDeclaration;
+    Annotation annotation = clazz.metadata.single;
+    Identifier name = annotation.name;
+    Element annotationElement = annotation.element;
+    if (name is SimpleIdentifier) {
+      validator(name, null, annotation.constructorName, annotationElement);
+    } else if (name is PrefixedIdentifier) {
+      validator(name.prefix, name.identifier, annotation.constructorName,
+          annotationElement);
+    } else {
+      fail('Uknown "name": ${name?.runtimeType} $name');
+    }
+  }
+}
+
+@reflectiveTest
 class ElementResolverTest extends EngineTestCase {
   /**
    * The error listener to which errors will be reported.
diff --git a/pkg/analyzer/test/generated/hint_code_test.dart b/pkg/analyzer/test/generated/hint_code_test.dart
index 750ef78..bbec137 100644
--- a/pkg/analyzer/test/generated/hint_code_test.dart
+++ b/pkg/analyzer/test/generated/hint_code_test.dart
@@ -65,6 +65,71 @@
     });
   }
 
+  void test_abstractSuperMemberReference_getter() {
+    Source source = addSource(r'''
+abstract class A {
+  int get test;
+}
+class B extends A {
+  int get test {
+    super.test;
+    return 0;
+  }
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [HintCode.ABSTRACT_SUPER_MEMBER_REFERENCE]);
+    verify([source]);
+  }
+
+  void test_abstractSuperMemberReference_method_invocation() {
+    Source source = addSource(r'''
+abstract class A {
+  void test();
+}
+class B extends A {
+  void test() {
+    super.test();
+  }
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [HintCode.ABSTRACT_SUPER_MEMBER_REFERENCE]);
+    verify([source]);
+  }
+
+  void test_abstractSuperMemberReference_method_reference() {
+    Source source = addSource(r'''
+abstract class A {
+  void test();
+}
+class B extends A {
+  void test() {
+    super.test;
+  }
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [HintCode.ABSTRACT_SUPER_MEMBER_REFERENCE]);
+    verify([source]);
+  }
+
+  void test_abstractSuperMemberReference_setter() {
+    Source source = addSource(r'''
+abstract class A {
+  void set test(int v);
+}
+class B extends A {
+  void set test(int v){
+    super.test = 0;
+  }
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [HintCode.ABSTRACT_SUPER_MEMBER_REFERENCE]);
+    verify([source]);
+  }
+
   void test_argumentTypeNotAssignable_functionType() {
     Source source = addSource(r'''
 m() {
@@ -1859,6 +1924,23 @@
     verify([source]);
   }
 
+  void test_mustCallSuper_fromInterface() {
+    Source source = addSource(r'''
+import 'package:meta/meta.dart';
+class A {
+  @mustCallSuper
+  void a() {}
+}
+class C implements A {
+  @override
+  void a() {}
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, []);
+    verify([source]);
+  }
+
   void test_mustCallSuper_indirect() {
     Source source = addSource(r'''
 import 'package:meta/meta.dart';
@@ -1882,7 +1964,7 @@
     verify([source]);
   }
 
-  void test_mustCallSuper_OK() {
+  void test_mustCallSuper_overridden() {
     Source source = addSource(r'''
 import 'package:meta/meta.dart';
 class A {
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index 21eb70a..6dd2519 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -36,6 +36,85 @@
     verify([source]);
   }
 
+  void test_abstractSuperMemberReference_superHasNoSuchMethod() {
+    Source source = addSource('''
+abstract class A {
+  int m();
+  noSuchMethod(_) => 42;
+}
+
+class B extends A {
+  int m() => super.m();
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_abstractSuperMemberReference_superSuperHasConcrete_getter() {
+    Source source = addSource('''
+abstract class A {
+  int get m => 0;
+}
+
+abstract class B extends A {
+  int get m;
+}
+
+class C extends B {
+  int get m => super.m;
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_abstractSuperMemberReference_superSuperHasConcrete_method() {
+    Source source = addSource('''
+void main() {
+  print(new C().m());
+}
+
+abstract class A {
+  int m() => 0;
+}
+
+abstract class B extends A {
+  int m();
+}
+
+class C extends B {
+  int m() => super.m();
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_abstractSuperMemberReference_superSuperHasConcrete_setter() {
+    Source source = addSource('''
+abstract class A {
+  void set m(int v) {}
+}
+
+abstract class B extends A {
+  void set m(int v);
+}
+
+class C extends B {
+  void set m(int v) {
+    super.m = 0;
+  }
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   void test_ambiguousExport() {
     Source source = addSource(r'''
 library L;
@@ -3164,6 +3243,23 @@
     verify([source]);
   }
 
+  void test_invocationOfNonFunction_functionTypeTypeParameter() {
+    Source source = addSource(r'''
+typedef void Action<T>(T x);
+class C<T, U extends Action<T>> {
+  T value;
+  U action;
+  C(this.value, [this.action]);
+  void act() {
+    action(value);
+  }
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   void test_invocationOfNonFunction_getter() {
     Source source = addSource(r'''
 class A {
diff --git a/pkg/analyzer/test/generated/package_test.dart b/pkg/analyzer/test/generated/package_test.dart
index 6133166..d138acd 100644
--- a/pkg/analyzer/test/generated/package_test.dart
+++ b/pkg/analyzer/test/generated/package_test.dart
@@ -171,7 +171,7 @@
     DartSdk sdk = new MockSdk();
     AnalysisOptionsImpl options1 = new AnalysisOptionsImpl();
     AnalysisOptionsImpl options2 = new AnalysisOptionsImpl();
-    options2.enableAsync = !options1.enableAsync;
+    options2.enableGenericMethods = !options1.enableGenericMethods;
     PackageDescription first = new PackageDescription(packageId, sdk, options1);
     PackageDescription second =
         new PackageDescription(packageId, sdk, options2);
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index cfea45d..fa7e4e6 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -336,7 +336,21 @@
         BinaryExpression, expression.condition);
   }
 
-  void test_conditionalExpression_precedence_nullableType() {
+  void test_conditionalExpression_precedence_nullableType_as() {
+    enableNnbd = true;
+    Expression expression = parseExpression('x as String ? (x + y) : z');
+    expect(expression, isNotNull);
+    expect(expression, new isInstanceOf<ConditionalExpression>());
+    ConditionalExpression conditional = expression;
+    Expression condition = conditional.condition;
+    expect(condition, new isInstanceOf<AsExpression>());
+    Expression thenExpression = conditional.thenExpression;
+    expect(thenExpression, new isInstanceOf<ParenthesizedExpression>());
+    Expression elseExpression = conditional.elseExpression;
+    expect(elseExpression, new isInstanceOf<SimpleIdentifier>());
+  }
+
+  void test_conditionalExpression_precedence_nullableType_is() {
     enableNnbd = true;
     Expression expression = parseExpression('x is String ? (x + y) : z');
     expect(expression, isNotNull);
@@ -573,114 +587,6 @@
  */
 @reflectiveTest
 class ErrorParserTest extends ParserTestCase {
-  void fail_expectedListOrMapLiteral() {
-    // It isn't clear that this test can ever pass. The parser is currently
-    // create a synthetic list literal in this case, but isSynthetic() isn't
-    // overridden for ListLiteral. The problem is that the synthetic list
-    // literals that are being created are not always zero length (because they
-    // could have type parameters), which violates the contract of
-    // isSynthetic().
-    createParser('1');
-    TypedLiteral literal = parser.parseListOrMapLiteral(null);
-    expectNotNullIfNoErrors(literal);
-    listener
-        .assertErrorsWithCodes([ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL]);
-    expect(literal.isSynthetic, isTrue);
-  }
-
-  void fail_illegalAssignmentToNonAssignable_superAssigned() {
-    // TODO(brianwilkerson) When this test starts to pass, remove the test
-    // test_illegalAssignmentToNonAssignable_superAssigned.
-    parseExpression(
-        "super = x;", [ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE]);
-  }
-
-  void fail_invalidCommentReference__new_nonIdentifier() {
-    // This test fails because the method parseCommentReference returns null.
-    createParser('');
-    CommentReference reference = parser.parseCommentReference('new 42', 0);
-    expectNotNullIfNoErrors(reference);
-    listener.assertErrorsWithCodes([ParserErrorCode.INVALID_COMMENT_REFERENCE]);
-  }
-
-  void fail_invalidCommentReference__new_tooMuch() {
-    createParser('');
-    CommentReference reference = parser.parseCommentReference('new a.b.c.d', 0);
-    expectNotNullIfNoErrors(reference);
-    listener.assertErrorsWithCodes([ParserErrorCode.INVALID_COMMENT_REFERENCE]);
-  }
-
-  void fail_invalidCommentReference__nonNew_nonIdentifier() {
-    // This test fails because the method parseCommentReference returns null.
-    createParser('');
-    CommentReference reference = parser.parseCommentReference('42', 0);
-    expectNotNullIfNoErrors(reference);
-    listener.assertErrorsWithCodes([ParserErrorCode.INVALID_COMMENT_REFERENCE]);
-  }
-
-  void fail_invalidCommentReference__nonNew_tooMuch() {
-    createParser('');
-    CommentReference reference = parser.parseCommentReference('a.b.c.d', 0);
-    expectNotNullIfNoErrors(reference);
-    listener.assertErrorsWithCodes([ParserErrorCode.INVALID_COMMENT_REFERENCE]);
-  }
-
-  void fail_missingClosingParenthesis() {
-    // It is possible that it is not possible to generate this error (that it's
-    // being reported in code that cannot actually be reached), but that hasn't
-    // been proven yet.
-    createParser('(int a, int b ;');
-    FormalParameterList list = parser.parseFormalParameterList();
-    expectNotNullIfNoErrors(list);
-    listener
-        .assertErrorsWithCodes([ParserErrorCode.MISSING_CLOSING_PARENTHESIS]);
-  }
-
-  void fail_missingFunctionParameters_local_nonVoid_block() {
-    // The parser does not recognize this as a function declaration, so it tries
-    // to parse it as an expression statement. It isn't clear what the best
-    // error message is in this case.
-    ParserTestCase.parseStatement(
-        "int f { return x;}", [ParserErrorCode.MISSING_FUNCTION_PARAMETERS]);
-  }
-
-  void fail_missingFunctionParameters_local_nonVoid_expression() {
-    // The parser does not recognize this as a function declaration, so it tries
-    // to parse it as an expression statement. It isn't clear what the best
-    // error message is in this case.
-    ParserTestCase.parseStatement(
-        "int f => x;", [ParserErrorCode.MISSING_FUNCTION_PARAMETERS]);
-  }
-
-  void fail_namedFunctionExpression() {
-    createParser('f() {}');
-    Expression expression = parser.parsePrimaryExpression();
-    expectNotNullIfNoErrors(expression);
-    listener.assertErrorsWithCodes([ParserErrorCode.NAMED_FUNCTION_EXPRESSION]);
-    expect(expression, new isInstanceOf<FunctionExpression>());
-  }
-
-  void fail_unexpectedToken_invalidPostfixExpression() {
-    // Note: this might not be the right error to produce, but some error should
-    // be produced
-    parseExpression("f()++", [ParserErrorCode.UNEXPECTED_TOKEN]);
-  }
-
-  void fail_varAndType_local() {
-    // This is currently reporting EXPECTED_TOKEN for a missing semicolon, but
-    // this would be a better error message.
-    ParserTestCase.parseStatement("var int x;", [ParserErrorCode.VAR_AND_TYPE]);
-  }
-
-  void fail_varAndType_parameter() {
-    // This is currently reporting EXPECTED_TOKEN for a missing semicolon, but
-    // this would be a better error message.
-    createParser('(var int x)');
-    FormalParameterList list = parser.parseFormalParameterList();
-    expectNotNullIfNoErrors(list);
-    listener.assertErrorsWithCodes([ParserErrorCode.VAR_AND_TYPE]);
-  }
-
   void test_abstractClassMember_constructor() {
     createParser('abstract C.c();');
     ClassMember member = parser.parseClassMember('C');
@@ -1041,42 +947,6 @@
     listener.assertErrorsWithCodes([ParserErrorCode.EMPTY_ENUM_BODY]);
   }
 
-  void test_enableAsync_false_1() {
-    parseAsync = false;
-    createParser('foo() async {}');
-    FunctionDeclarationStatement statement =
-        parser.parseFunctionDeclarationStatement();
-    expectNotNullIfNoErrors(statement);
-    listener.assertErrorsWithCodes([ParserErrorCode.ASYNC_NOT_SUPPORTED]);
-    FunctionExpression expr = statement.functionDeclaration.functionExpression;
-    expect(expr.body.isAsynchronous, isTrue);
-    expect(expr.body.isGenerator, isFalse);
-  }
-
-  void test_enableAsync_false_2() {
-    parseAsync = false;
-    createParser('foo() async => 0;');
-    FunctionDeclarationStatement statement =
-        parser.parseFunctionDeclarationStatement();
-    expectNotNullIfNoErrors(statement);
-    listener.assertErrorsWithCodes([ParserErrorCode.ASYNC_NOT_SUPPORTED]);
-    FunctionExpression expr = statement.functionDeclaration.functionExpression;
-    expect(expr.body.isAsynchronous, isTrue);
-    expect(expr.body.isGenerator, isFalse);
-  }
-
-  void test_enableAsync_false_3() {
-    parseAsync = false;
-    createParser('foo() sync* {}');
-    FunctionDeclarationStatement statement =
-        parser.parseFunctionDeclarationStatement();
-    expectNotNullIfNoErrors(statement);
-    listener.assertErrorsWithCodes([ParserErrorCode.ASYNC_NOT_SUPPORTED]);
-    FunctionExpression expr = statement.functionDeclaration.functionExpression;
-    expect(expr.body.isAsynchronous, isFalse);
-    expect(expr.body.isGenerator, isTrue);
-  }
-
   void test_enumInClass() {
     ParserTestCase.parseCompilationUnit(
         r'''
@@ -1183,6 +1053,22 @@
         [new AnalysisError(null, 2, 1, ParserErrorCode.MISSING_IDENTIFIER)]);
   }
 
+  @failingTest
+  void test_expectedListOrMapLiteral() {
+    // It isn't clear that this test can ever pass. The parser is currently
+    // create a synthetic list literal in this case, but isSynthetic() isn't
+    // overridden for ListLiteral. The problem is that the synthetic list
+    // literals that are being created are not always zero length (because they
+    // could have type parameters), which violates the contract of
+    // isSynthetic().
+    createParser('1');
+    TypedLiteral literal = parser.parseListOrMapLiteral(null);
+    expectNotNullIfNoErrors(literal);
+    listener
+        .assertErrorsWithCodes([ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL]);
+    expect(literal.isSynthetic, isTrue);
+  }
+
   void test_expectedStringLiteral() {
     createParser('1');
     StringLiteral literal = parser.parseStringLiteral();
@@ -1532,7 +1418,7 @@
 
   void test_illegalAssignmentToNonAssignable_superAssigned() {
     // TODO(brianwilkerson) When the test
-    // fail_illegalAssignmentToNonAssignable_superAssigned starts to pass,
+    // test_illegalAssignmentToNonAssignable_superAssigned_failing starts to pass,
     // remove this test (there should only be one error generated, but we're
     // keeping this test until that time so that we can catch other forms of
     // regressions).
@@ -1542,6 +1428,14 @@
     ]);
   }
 
+  @failingTest
+  void test_illegalAssignmentToNonAssignable_superAssigned_failing() {
+    // TODO(brianwilkerson) When this test starts to pass, remove the test
+    // test_illegalAssignmentToNonAssignable_superAssigned.
+    parseExpression(
+        "super = x;", [ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE]);
+  }
+
   void test_implementsBeforeExtends() {
     ParserTestCase.parseCompilationUnit("class A implements B extends C {}",
         [ParserErrorCode.IMPLEMENTS_BEFORE_EXTENDS]);
@@ -1574,12 +1468,46 @@
   }
 
   void test_invalidCodePoint() {
-    createParser("'\\uD900'");
+    createParser("'\\u{110000}'");
     StringLiteral literal = parser.parseStringLiteral();
     expectNotNullIfNoErrors(literal);
     listener.assertErrorsWithCodes([ParserErrorCode.INVALID_CODE_POINT]);
   }
 
+  @failingTest
+  void test_invalidCommentReference__new_nonIdentifier() {
+    // This test fails because the method parseCommentReference returns null.
+    createParser('');
+    CommentReference reference = parser.parseCommentReference('new 42', 0);
+    expectNotNullIfNoErrors(reference);
+    listener.assertErrorsWithCodes([ParserErrorCode.INVALID_COMMENT_REFERENCE]);
+  }
+
+  @failingTest
+  void test_invalidCommentReference__new_tooMuch() {
+    createParser('');
+    CommentReference reference = parser.parseCommentReference('new a.b.c.d', 0);
+    expectNotNullIfNoErrors(reference);
+    listener.assertErrorsWithCodes([ParserErrorCode.INVALID_COMMENT_REFERENCE]);
+  }
+
+  @failingTest
+  void test_invalidCommentReference__nonNew_nonIdentifier() {
+    // This test fails because the method parseCommentReference returns null.
+    createParser('');
+    CommentReference reference = parser.parseCommentReference('42', 0);
+    expectNotNullIfNoErrors(reference);
+    listener.assertErrorsWithCodes([ParserErrorCode.INVALID_COMMENT_REFERENCE]);
+  }
+
+  @failingTest
+  void test_invalidCommentReference__nonNew_tooMuch() {
+    createParser('');
+    CommentReference reference = parser.parseCommentReference('a.b.c.d', 0);
+    expectNotNullIfNoErrors(reference);
+    listener.assertErrorsWithCodes([ParserErrorCode.INVALID_COMMENT_REFERENCE]);
+  }
+
   void test_invalidHexEscape_invalidDigit() {
     createParser("'\\x0 a'");
     StringLiteral literal = parser.parseStringLiteral();
@@ -1860,6 +1788,18 @@
         "class A class B {}", [ParserErrorCode.MISSING_CLASS_BODY]);
   }
 
+  @failingTest
+  void test_missingClosingParenthesis() {
+    // It is possible that it is not possible to generate this error (that it's
+    // being reported in code that cannot actually be reached), but that hasn't
+    // been proven yet.
+    createParser('(int a, int b ;');
+    FormalParameterList list = parser.parseFormalParameterList();
+    expectNotNullIfNoErrors(list);
+    listener
+        .assertErrorsWithCodes([ParserErrorCode.MISSING_CLOSING_PARENTHESIS]);
+  }
+
   void test_missingConstFinalVarOrType_static() {
     ParserTestCase.parseCompilationUnit("class A { static f; }",
         [ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE]);
@@ -1913,6 +1853,24 @@
     listener.assertErrorsWithCodes([ParserErrorCode.MISSING_FUNCTION_BODY]);
   }
 
+  @failingTest
+  void test_missingFunctionParameters_local_nonVoid_block() {
+    // The parser does not recognize this as a function declaration, so it tries
+    // to parse it as an expression statement. It isn't clear what the best
+    // error message is in this case.
+    ParserTestCase.parseStatement(
+        "int f { return x;}", [ParserErrorCode.MISSING_FUNCTION_PARAMETERS]);
+  }
+
+  @failingTest
+  void test_missingFunctionParameters_local_nonVoid_expression() {
+    // The parser does not recognize this as a function declaration, so it tries
+    // to parse it as an expression statement. It isn't clear what the best
+    // error message is in this case.
+    ParserTestCase.parseStatement(
+        "int f => x;", [ParserErrorCode.MISSING_FUNCTION_PARAMETERS]);
+  }
+
   void test_missingFunctionParameters_local_void_block() {
     ParserTestCase.parseStatement(
         "void f { return x;}", [ParserErrorCode.MISSING_FUNCTION_PARAMETERS]);
@@ -2191,6 +2149,15 @@
         [ParserErrorCode.MULTIPLE_WITH_CLAUSES]);
   }
 
+  @failingTest
+  void test_namedFunctionExpression() {
+    createParser('f() {}');
+    Expression expression = parser.parsePrimaryExpression();
+    expectNotNullIfNoErrors(expression);
+    listener.assertErrorsWithCodes([ParserErrorCode.NAMED_FUNCTION_EXPRESSION]);
+    expect(expression, new isInstanceOf<FunctionExpression>());
+  }
+
   void test_namedParameterOutsideGroup() {
     createParser('(a, b : 0)');
     FormalParameterList list = parser.parseFormalParameterList();
@@ -2243,6 +2210,39 @@
         .assertErrorsWithCodes([ParserErrorCode.NON_USER_DEFINABLE_OPERATOR]);
   }
 
+  void test_nullableTypeInExtends() {
+    enableNnbd = true;
+    createParser('extends B?');
+    ExtendsClause clause = parser.parseExtendsClause();
+    expectNotNullIfNoErrors(clause);
+    listener.assertErrorsWithCodes([ParserErrorCode.NULLABLE_TYPE_IN_EXTENDS]);
+  }
+
+  void test_nullableTypeInImplements() {
+    enableNnbd = true;
+    createParser('implements I?');
+    ImplementsClause clause = parser.parseImplementsClause();
+    expectNotNullIfNoErrors(clause);
+    listener
+        .assertErrorsWithCodes([ParserErrorCode.NULLABLE_TYPE_IN_IMPLEMENTS]);
+  }
+
+  void test_nullableTypeInWith() {
+    enableNnbd = true;
+    createParser('with M?');
+    WithClause clause = parser.parseWithClause();
+    expectNotNullIfNoErrors(clause);
+    listener.assertErrorsWithCodes([ParserErrorCode.NULLABLE_TYPE_IN_WITH]);
+  }
+
+  void test_nullableTypeParameter() {
+    enableNnbd = true;
+    createParser('T?');
+    TypeParameter parameter = parser.parseTypeParameter();
+    expectNotNullIfNoErrors(parameter);
+    listener.assertErrorsWithCodes([ParserErrorCode.NULLABLE_TYPE_PARAMETER]);
+  }
+
   void test_optionalAfterNormalParameters_named() {
     ParserTestCase.parseCompilationUnit(
         "f({a}, b) {}", [ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS]);
@@ -2534,6 +2534,13 @@
         "String s = (null));", [ParserErrorCode.UNEXPECTED_TOKEN]);
   }
 
+  @failingTest
+  void test_unexpectedToken_invalidPostfixExpression() {
+    // Note: this might not be the right error to produce, but some error should
+    // be produced
+    parseExpression("f()++", [ParserErrorCode.UNEXPECTED_TOKEN]);
+  }
+
   void test_unexpectedToken_returnInExpressionFuntionBody() {
     ParserTestCase.parseCompilationUnit(
         "f() => return null;", [ParserErrorCode.UNEXPECTED_TOKEN]);
@@ -2641,6 +2648,23 @@
         "class C { var int x; }", [ParserErrorCode.VAR_AND_TYPE]);
   }
 
+  @failingTest
+  void test_varAndType_local() {
+    // This is currently reporting EXPECTED_TOKEN for a missing semicolon, but
+    // this would be a better error message.
+    ParserTestCase.parseStatement("var int x;", [ParserErrorCode.VAR_AND_TYPE]);
+  }
+
+  @failingTest
+  void test_varAndType_parameter() {
+    // This is currently reporting EXPECTED_TOKEN for a missing semicolon, but
+    // this would be a better error message.
+    createParser('(var int x)');
+    FormalParameterList list = parser.parseFormalParameterList();
+    expectNotNullIfNoErrors(list);
+    listener.assertErrorsWithCodes([ParserErrorCode.VAR_AND_TYPE]);
+  }
+
   void test_varAndType_topLevelVariable() {
     ParserTestCase
         .parseCompilationUnit("var int x;", [ParserErrorCode.VAR_AND_TYPE]);
@@ -2888,7 +2912,6 @@
     //
     parser = new Parser(source, listener);
     parser.enableAssertInitializer = enableAssertInitializer;
-    parser.parseAsync = parseAsync;
     parser.parseGenericMethods = enableGenericMethods;
     parser.parseGenericMethodComments = enableGenericMethodComments;
     parser.parseFunctionBodies = parseFunctionBodies;
@@ -3025,18 +3048,6 @@
  */
 @reflectiveTest
 class RecoveryParserTest extends ParserTestCase {
-  void fail_incomplete_returnType() {
-    ParserTestCase.parseCompilationUnit(r'''
-Map<Symbol, convertStringToSymbolMap(Map<String, dynamic> map) {
-  if (map == null) return null;
-  Map<Symbol, dynamic> result = new Map<Symbol, dynamic>();
-  map.forEach((name, value) {
-    result[new Symbol(name)] = value;
-  });
-  return result;
-}''');
-  }
-
   void test_additiveExpression_missing_LHS() {
     BinaryExpression expression =
         parseExpression("+ y", [ParserErrorCode.MISSING_IDENTIFIER]);
@@ -3577,6 +3588,19 @@
         [ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER]);
   }
 
+  @failingTest
+  void test_incomplete_returnType() {
+    ParserTestCase.parseCompilationUnit(r'''
+Map<Symbol, convertStringToSymbolMap(Map<String, dynamic> map) {
+  if (map == null) return null;
+  Map<Symbol, dynamic> result = new Map<Symbol, dynamic>();
+  map.forEach((name, value) {
+    result[new Symbol(name)] = value;
+  });
+  return result;
+}''');
+  }
+
   void test_incomplete_topLevelFunction() {
     ParserTestCase.parseCompilationUnit(
         "foo();", [ParserErrorCode.MISSING_FUNCTION_BODY]);
@@ -4228,56 +4252,6 @@
  */
 @reflectiveTest
 class SimpleParserTest extends ParserTestCase {
-  void fail_parseAwaitExpression_inSync() {
-    // This test requires better error recovery than we currently have. In
-    // particular, we need to be able to distinguish between an await expression
-    // in the wrong context, and the use of 'await' as an identifier.
-    createParser('m() { return await x + await y; }');
-    MethodDeclaration method = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(method);
-    listener.assertNoErrors();
-    FunctionBody body = method.body;
-    EngineTestCase.assertInstanceOf(
-        (obj) => obj is BlockFunctionBody, BlockFunctionBody, body);
-    Statement statement = (body as BlockFunctionBody).block.statements[0];
-    EngineTestCase.assertInstanceOf(
-        (obj) => obj is ReturnStatement, ReturnStatement, statement);
-    Expression expression = (statement as ReturnStatement).expression;
-    EngineTestCase.assertInstanceOf(
-        (obj) => obj is BinaryExpression, BinaryExpression, expression);
-    EngineTestCase.assertInstanceOf((obj) => obj is AwaitExpression,
-        AwaitExpression, (expression as BinaryExpression).leftOperand);
-    EngineTestCase.assertInstanceOf((obj) => obj is AwaitExpression,
-        AwaitExpression, (expression as BinaryExpression).rightOperand);
-  }
-
-  void fail_parseCommentReference_this() {
-    // This fails because we are returning null from the method and asserting
-    // that the return value is not null.
-    createParser('');
-    CommentReference reference = parser.parseCommentReference('this', 5);
-    expectNotNullIfNoErrors(reference);
-    listener.assertNoErrors();
-    SimpleIdentifier identifier = EngineTestCase.assertInstanceOf(
-        (obj) => obj is SimpleIdentifier,
-        SimpleIdentifier,
-        reference.identifier);
-    expect(identifier.token, isNotNull);
-    expect(identifier.name, "a");
-    expect(identifier.offset, 5);
-  }
-
-  void fail_parseStatement_functionDeclaration_noReturnType_typeParameters() {
-    enableGenericMethods = true;
-    createParser('f<E>(a, b) {};');
-    Statement statement = parser.parseStatement2();
-    expectNotNullIfNoErrors(statement);
-    listener.assertNoErrors();
-    expect(statement, new isInstanceOf<FunctionDeclarationStatement>());
-    FunctionDeclarationStatement declaration = statement;
-    expect(declaration.functionDeclaration, isNotNull);
-  }
-
   void test_computeStringValue_emptyInterpolationPrefix() {
     expect(_computeStringValue("'''", true, false), "");
   }
@@ -5152,6 +5126,30 @@
         statement);
   }
 
+  @failingTest
+  void test_parseAwaitExpression_inSync() {
+    // This test requires better error recovery than we currently have. In
+    // particular, we need to be able to distinguish between an await expression
+    // in the wrong context, and the use of 'await' as an identifier.
+    createParser('m() { return await x + await y; }');
+    MethodDeclaration method = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(method);
+    listener.assertNoErrors();
+    FunctionBody body = method.body;
+    EngineTestCase.assertInstanceOf(
+        (obj) => obj is BlockFunctionBody, BlockFunctionBody, body);
+    Statement statement = (body as BlockFunctionBody).block.statements[0];
+    EngineTestCase.assertInstanceOf(
+        (obj) => obj is ReturnStatement, ReturnStatement, statement);
+    Expression expression = (statement as ReturnStatement).expression;
+    EngineTestCase.assertInstanceOf(
+        (obj) => obj is BinaryExpression, BinaryExpression, expression);
+    EngineTestCase.assertInstanceOf((obj) => obj is AwaitExpression,
+        AwaitExpression, (expression as BinaryExpression).leftOperand);
+    EngineTestCase.assertInstanceOf((obj) => obj is AwaitExpression,
+        AwaitExpression, (expression as BinaryExpression).rightOperand);
+  }
+
   void test_parseBitwiseAndExpression_normal() {
     createParser('x & y');
     Expression expression = parser.parseBitwiseAndExpression();
@@ -6822,6 +6820,23 @@
     expect(nextToken.type, TokenType.EOF);
   }
 
+  @failingTest
+  void test_parseCommentReference_this() {
+    // This fails because we are returning null from the method and asserting
+    // that the return value is not null.
+    createParser('');
+    CommentReference reference = parser.parseCommentReference('this', 5);
+    expectNotNullIfNoErrors(reference);
+    listener.assertNoErrors();
+    SimpleIdentifier identifier = EngineTestCase.assertInstanceOf(
+        (obj) => obj is SimpleIdentifier,
+        SimpleIdentifier,
+        reference.identifier);
+    expect(identifier.token, isNotNull);
+    expect(identifier.name, "a");
+    expect(identifier.offset, 5);
+  }
+
   void test_parseCommentReferences_multiLine() {
     DocumentationCommentToken token = new DocumentationCommentToken(
         TokenType.MULTI_LINE_COMMENT, "/** xxx [a] yyy [bb] zzz */", 3);
@@ -10115,6 +10130,27 @@
     expect(expression.argumentList, isNotNull);
   }
 
+  void test_parseInstanceCreationExpression_type_typeParameters_nullable() {
+    enableNnbd = true;
+    Token token = TokenFactory.tokenFromKeyword(Keyword.NEW);
+    createParser('A<B?>()');
+    InstanceCreationExpression expression =
+        parser.parseInstanceCreationExpression(token);
+    expectNotNullIfNoErrors(expression);
+    listener.assertNoErrors();
+    expect(expression.keyword, token);
+    ConstructorName name = expression.constructorName;
+    expect(name, isNotNull);
+    TypeName type = name.type;
+    expect(type, isNotNull);
+    expect(name.period, isNull);
+    expect(name.name, isNull);
+    expect(expression.argumentList, isNotNull);
+    NodeList<TypeName> arguments = type.typeArguments.arguments;
+    expect(arguments, hasLength(1));
+    expect(arguments[0].question, isNotNull);
+  }
+
   void test_parseLibraryDirective() {
     createParser('library l;');
     LibraryDirective directive =
@@ -11562,6 +11598,19 @@
     expect(asExpression.type, isNotNull);
   }
 
+  void test_parseRelationalExpression_as_nullable() {
+    enableNnbd = true;
+    createParser('x as Y?)');
+    Expression expression = parser.parseRelationalExpression();
+    expectNotNullIfNoErrors(expression);
+    listener.assertNoErrors();
+    expect(expression, new isInstanceOf<AsExpression>());
+    AsExpression asExpression = expression;
+    expect(asExpression.expression, isNotNull);
+    expect(asExpression.asOperator, isNotNull);
+    expect(asExpression.type, isNotNull);
+  }
+
   void test_parseRelationalExpression_is() {
     createParser('x is y');
     Expression expression = parser.parseRelationalExpression();
@@ -11575,6 +11624,20 @@
     expect(isExpression.type, isNotNull);
   }
 
+  void test_parseRelationalExpression_is_nullable() {
+    enableNnbd = true;
+    createParser('x is y?)');
+    Expression expression = parser.parseRelationalExpression();
+    expectNotNullIfNoErrors(expression);
+    listener.assertNoErrors();
+    expect(expression, new isInstanceOf<IsExpression>());
+    IsExpression isExpression = expression;
+    expect(isExpression.expression, isNotNull);
+    expect(isExpression.isOperator, isNotNull);
+    expect(isExpression.notOperator, isNull);
+    expect(isExpression.type, isNotNull);
+  }
+
   void test_parseRelationalExpression_isNot() {
     createParser('x is! y');
     Expression expression = parser.parseRelationalExpression();
@@ -11787,6 +11850,18 @@
         isNotNull);
   }
 
+  @failingTest
+  void test_parseStatement_functionDeclaration_noReturnType_typeParameters() {
+    enableGenericMethods = true;
+    createParser('f<E>(a, b) {};');
+    Statement statement = parser.parseStatement2();
+    expectNotNullIfNoErrors(statement);
+    listener.assertNoErrors();
+    expect(statement, new isInstanceOf<FunctionDeclarationStatement>());
+    FunctionDeclarationStatement declaration = statement;
+    expect(declaration.functionDeclaration, isNotNull);
+  }
+
   void test_parseStatement_functionDeclaration_returnType() {
     // TODO(brianwilkerson) Implement more tests for this method.
     createParser('int f(a, b) {};');
@@ -12693,6 +12768,20 @@
     expect(parameter.name, isNotNull);
   }
 
+  void test_parseTypeParameter_bounded_nullable() {
+    enableNnbd = true;
+    createParser('A extends B?');
+    TypeParameter parameter = parser.parseTypeParameter();
+    expectNotNullIfNoErrors(parameter);
+    listener.assertNoErrors();
+    expect(parameter.bound, isNotNull);
+    expect(parameter.extendsKeyword, isNotNull);
+    expect(parameter.name, isNotNull);
+    TypeName bound = parameter.bound;
+    expect(bound, isNotNull);
+    expect(bound.question, isNotNull);
+  }
+
   void test_parseTypeParameter_simple() {
     createParser('A');
     TypeParameter parameter = parser.parseTypeParameter();
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index 6c089fa..1abacd6 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -12,7 +12,6 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
-import 'package:analyzer/src/context/context.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/error/codes.dart';
@@ -37,7 +36,6 @@
   initializeTestEnvironment();
   defineReflectiveTests(AnalysisDeltaTest);
   defineReflectiveTests(ChangeSetTest);
-  defineReflectiveTests(DisableAsyncTestCase);
   defineReflectiveTests(EnclosedScopeTest);
   defineReflectiveTests(ErrorResolverTest);
   defineReflectiveTests(LibraryImportScopeTest);
@@ -143,51 +141,6 @@
 }
 
 @reflectiveTest
-class DisableAsyncTestCase extends ResolverTestCase {
-  @override
-  void setUp() {
-    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
-    options.enableAsync = false;
-    resetWithOptions(options);
-  }
-
-  void test_resolve() {
-    Source source = addSource(r'''
-class C {
-  foo() {
-    bar();
-  }
-  bar() {
-    //
-  }
-}''');
-    computeLibrarySourceErrors(source);
-    assertErrors(source, []);
-  }
-
-  void test_resolve_async() {
-    Source source = addSource(r'''
-class C {
-  Future foo() async {
-    await bar();
-    return null;
-  }
-  Future bar() {
-    return new Future.delayed(new Duration(milliseconds: 10));
-  }
-}''');
-    computeLibrarySourceErrors(source);
-    assertErrors(source, [
-      StaticWarningCode.UNDEFINED_CLASS,
-      StaticWarningCode.UNDEFINED_CLASS,
-      StaticWarningCode.UNDEFINED_CLASS,
-      StaticWarningCode.UNDEFINED_CLASS,
-      ParserErrorCode.ASYNC_NOT_SUPPORTED
-    ]);
-  }
-}
-
-@reflectiveTest
 class EnclosedScopeTest extends ResolverTestCase {
   void test_define_duplicate() {
     Scope rootScope = new _RootScope();
@@ -2551,79 +2504,6 @@
     expect(provider.typeType, same(typeType));
   }
 
-  void test_creation_no_async() {
-    //
-    // Create a mock library element with the types expected to be in dart:core.
-    // We cannot use either ElementFactory or TestTypeProvider (which uses
-    // ElementFactory) because we side-effect the elements in ways that would
-    // break other tests.
-    //
-    InterfaceType objectType = _classElement("Object", null).type;
-    InterfaceType boolType = _classElement("bool", objectType).type;
-    InterfaceType numType = _classElement("num", objectType).type;
-    InterfaceType doubleType = _classElement("double", numType).type;
-    InterfaceType functionType = _classElement("Function", objectType).type;
-    InterfaceType intType = _classElement("int", numType).type;
-    InterfaceType iterableType =
-        _classElement("Iterable", objectType, ["T"]).type;
-    InterfaceType listType = _classElement("List", objectType, ["E"]).type;
-    InterfaceType mapType = _classElement("Map", objectType, ["K", "V"]).type;
-    InterfaceType stackTraceType = _classElement("StackTrace", objectType).type;
-    InterfaceType stringType = _classElement("String", objectType).type;
-    InterfaceType symbolType = _classElement("Symbol", objectType).type;
-    InterfaceType typeType = _classElement("Type", objectType).type;
-    CompilationUnitElementImpl coreUnit =
-        new CompilationUnitElementImpl("core.dart");
-    coreUnit.types = <ClassElement>[
-      boolType.element,
-      doubleType.element,
-      functionType.element,
-      intType.element,
-      iterableType.element,
-      listType.element,
-      mapType.element,
-      objectType.element,
-      stackTraceType.element,
-      stringType.element,
-      symbolType.element,
-      typeType.element
-    ];
-    AnalysisContext context = AnalysisEngine.instance.createAnalysisContext();
-    LibraryElementImpl coreLibrary = new LibraryElementImpl.forNode(
-        context, AstFactory.libraryIdentifier2(["dart.core"]));
-    coreLibrary.definingCompilationUnit = coreUnit;
-
-    Source asyncSource = new NonExistingSource(
-        'async.dart', Uri.parse('dart:async'), UriKind.DART_URI);
-    LibraryElementImpl mockAsyncLib = (context as AnalysisContextImpl)
-        .createMockAsyncLib(coreLibrary, asyncSource);
-    expect(mockAsyncLib.source, same(asyncSource));
-    expect(mockAsyncLib.definingCompilationUnit.source, same(asyncSource));
-    expect(mockAsyncLib.publicNamespace, isNotNull);
-
-    //
-    // Create a type provider and ensure that it can return the expected types.
-    //
-    TypeProviderImpl provider = new TypeProviderImpl(coreLibrary, mockAsyncLib);
-    expect(provider.boolType, same(boolType));
-    expect(provider.bottomType, isNotNull);
-    expect(provider.doubleType, same(doubleType));
-    expect(provider.dynamicType, isNotNull);
-    expect(provider.functionType, same(functionType));
-    InterfaceType mockFutureType = mockAsyncLib.getType('Future').type;
-    expect(provider.futureType, same(mockFutureType));
-    expect(provider.intType, same(intType));
-    expect(provider.listType, same(listType));
-    expect(provider.mapType, same(mapType));
-    expect(provider.objectType, same(objectType));
-    expect(provider.stackTraceType, same(stackTraceType));
-    expect(provider.stringType, same(stringType));
-    expect(provider.symbolType, same(symbolType));
-    InterfaceType mockStreamType = mockAsyncLib.getType('Stream').type;
-    expect(provider.streamType, same(mockStreamType));
-    expect(provider.typeType, same(typeType));
-  }
-
   ClassElement _classElement(String typeName, InterfaceType superclassType,
       [List<String> parameterNames]) {
     ClassElementImpl element =
diff --git a/pkg/analyzer/test/instrumentation/instrumentation_test.dart b/pkg/analyzer/test/instrumentation/instrumentation_test.dart
index 8386ee7..e6cafc0 100644
--- a/pkg/analyzer/test/instrumentation/instrumentation_test.dart
+++ b/pkg/analyzer/test/instrumentation/instrumentation_test.dart
@@ -165,6 +165,9 @@
   StringBuffer priorityChannel = new StringBuffer();
 
   @override
+  String get sessionId => '';
+
+  @override
   void log(String message) {
     normalChannel.writeln(message);
   }
diff --git a/pkg/analyzer/test/src/context/builder_test.dart b/pkg/analyzer/test/src/context/builder_test.dart
index 3ba56ac..6de0ec6 100644
--- a/pkg/analyzer/test/src/context/builder_test.dart
+++ b/pkg/analyzer/test/src/context/builder_test.dart
@@ -135,7 +135,6 @@
     AnalysisOptionsImpl defaultOptions = new AnalysisOptionsImpl();
     defaultOptions.dart2jsHint = !defaultOptions.dart2jsHint;
     defaultOptions.enableAssertMessage = !defaultOptions.enableAssertMessage;
-    defaultOptions.enableAsync = !defaultOptions.enableAsync;
     defaultOptions.enableGenericMethods = !defaultOptions.enableGenericMethods;
     defaultOptions.enableStrictCallChecks =
         !defaultOptions.enableStrictCallChecks;
@@ -498,7 +497,7 @@
     defaultOptions.enableGenericMethods = true;
     builder.defaultOptions = defaultOptions;
     AnalysisOptionsImpl expected = new AnalysisOptionsImpl();
-    expected.enableAsync = true;
+    expected.enableSuperMixins = true;
     expected.enableGenericMethods = true;
     String path = '/some/directory/path';
     String filePath = '$path/${AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE}';
@@ -506,7 +505,8 @@
         filePath,
         '''
 analyzer:
-  enableAsync : true
+  language:
+    enableSuperMixins : true
 ''');
 
     AnalysisEngine engine = AnalysisEngine.instance;
@@ -515,7 +515,9 @@
     try {
       _TestOptionsProcessor processor = new _TestOptionsProcessor();
       processor.expectedOptions = <String, Object>{
-        'analyzer': {'enableAsync': true}
+        'analyzer': {
+          'language': {'enableSuperMixins': true}
+        }
       };
       (plugin.optionsProcessorExtensionPoint as ExtensionPointImpl)
           .add(processor);
@@ -566,14 +568,15 @@
 
   void test_getAnalysisOptions_noDefault_overrides() {
     AnalysisOptionsImpl expected = new AnalysisOptionsImpl();
-    expected.enableAsync = true;
+    expected.enableSuperMixins = true;
     String path = '/some/directory/path';
     String filePath = '$path/${AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE}';
     resourceProvider.newFile(
         filePath,
         '''
 analyzer:
-  enableAsync : true
+  language:
+    enableSuperMixins : true
 ''');
 
     AnalysisContext context = AnalysisEngine.instance.createAnalysisContext();
@@ -643,7 +646,6 @@
     expect(actual.cacheSize, expected.cacheSize);
     expect(actual.dart2jsHint, expected.dart2jsHint);
     expect(actual.enableAssertMessage, expected.enableAssertMessage);
-    expect(actual.enableAsync, expected.enableAsync);
     expect(actual.enableStrictCallChecks, expected.enableStrictCallChecks);
     expect(actual.enableGenericMethods, expected.enableGenericMethods);
     expect(actual.enableSuperMixins, expected.enableSuperMixins);
diff --git a/pkg/analyzer/test/src/context/cache_test.dart b/pkg/analyzer/test/src/context/cache_test.dart
index 914a674b..d6af6ce 100644
--- a/pkg/analyzer/test/src/context/cache_test.dart
+++ b/pkg/analyzer/test/src/context/cache_test.dart
@@ -58,8 +58,8 @@
 
   test_flush() {
     AnalysisTarget target = new TestSource();
-    ResultDescriptor resultA = new ResultDescriptor('A', null);
-    ResultDescriptor resultB = new ResultDescriptor('B', null);
+    ResultDescriptor<String> resultA = new ResultDescriptor<String>('A', null);
+    ResultDescriptor<String> resultB = new ResultDescriptor<String>('B', null);
     CacheEntry entry = new CacheEntry(target);
     cache.put(entry);
     // put values
@@ -124,7 +124,8 @@
   }
 
   void test_getState_hasEntry_valid() {
-    ResultDescriptor result = new ResultDescriptor('result', -1);
+    ResultDescriptor<String> result =
+        new ResultDescriptor<String>('result', null);
     AnalysisTarget target = new TestSource();
     CacheEntry entry = new CacheEntry(target);
     cache.put(entry);
@@ -139,7 +140,7 @@
   }
 
   void test_getValue_hasEntry_valid() {
-    ResultDescriptor result = new ResultDescriptor('result', -1);
+    ResultDescriptor<int> result = new ResultDescriptor<int>('result', -1);
     AnalysisTarget target = new TestSource();
     CacheEntry entry = new CacheEntry(target);
     cache.put(entry);
@@ -182,9 +183,9 @@
     cache.put(entry1);
     cache.put(entry2);
     cache.put(entry3);
-    ResultDescriptor result1 = new ResultDescriptor('result1', -1);
-    ResultDescriptor result2 = new ResultDescriptor('result2', -2);
-    ResultDescriptor result3 = new ResultDescriptor('result3', -3);
+    ResultDescriptor<int> result1 = new ResultDescriptor<int>('result1', -1);
+    ResultDescriptor<int> result2 = new ResultDescriptor<int>('result2', -2);
+    ResultDescriptor<int> result3 = new ResultDescriptor<int>('result3', -3);
     // set results, all of them are VALID
     entry1.setValue(result1, 111, TargetedResult.EMPTY_LIST);
     entry2.setValue(result2, 222, [new TargetedResult(target1, result1)]);
@@ -207,8 +208,8 @@
     AnalysisTarget target = new TestSource('/a.dart');
     CacheEntry entry = new CacheEntry(target);
     cache.put(entry);
-    ResultDescriptor result1 = new ResultDescriptor('result1', -1);
-    ResultDescriptor result2 = new ResultDescriptor('result2', -2);
+    ResultDescriptor<int> result1 = new ResultDescriptor<int>('result1', -1);
+    ResultDescriptor<int> result2 = new ResultDescriptor<int>('result2', -2);
     // set results, all of them are VALID
     entry.setValue(result1, 111, TargetedResult.EMPTY_LIST);
     entry.setValue(result2, 222, [new TargetedResult(target, result1)]);
@@ -258,8 +259,10 @@
 @reflectiveTest
 class CacheEntryTest extends AbstractCacheTest {
   test_dispose() {
-    ResultDescriptor descriptor1 = new ResultDescriptor('result1', -1);
-    ResultDescriptor descriptor2 = new ResultDescriptor('result2', -2);
+    ResultDescriptor<int> descriptor1 =
+        new ResultDescriptor<int>('result1', -1);
+    ResultDescriptor<int> descriptor2 =
+        new ResultDescriptor<int>('result2', -2);
     AnalysisTarget target1 = new TestSource('1.dart');
     AnalysisTarget target2 = new TestSource('2.dart');
     TargetedResult result1 = new TargetedResult(target1, descriptor1);
@@ -300,7 +303,7 @@
 
   test_fixExceptionState_noError_exception() {
     AnalysisTarget target = new TestSource();
-    ResultDescriptor result = new ResultDescriptor('test', null);
+    ResultDescriptor<int> result = new ResultDescriptor<int>('test', null);
     CacheEntry entry = new CacheEntry(target);
     cache.put(entry);
     // set one result to ERROR
@@ -324,8 +327,8 @@
 
   test_flush() {
     AnalysisTarget target = new TestSource();
-    ResultDescriptor resultA = new ResultDescriptor('A', null);
-    ResultDescriptor resultB = new ResultDescriptor('B', null);
+    ResultDescriptor<String> resultA = new ResultDescriptor<String>('A', null);
+    ResultDescriptor<String> resultB = new ResultDescriptor<String>('B', null);
     CacheEntry entry = new CacheEntry(target);
     cache.put(entry);
     // put values
@@ -359,13 +362,17 @@
   }
 
   test_getValue_flushResults() {
-    ResultCachingPolicy cachingPolicy = new SimpleResultCachingPolicy(2, 2);
-    ResultDescriptor descriptor1 =
-        new ResultDescriptor('result1', null, cachingPolicy: cachingPolicy);
-    ResultDescriptor descriptor2 =
-        new ResultDescriptor('result2', null, cachingPolicy: cachingPolicy);
-    ResultDescriptor descriptor3 =
-        new ResultDescriptor('result3', null, cachingPolicy: cachingPolicy);
+    ResultCachingPolicy<int> cachingPolicy =
+        new SimpleResultCachingPolicy<int>(2, 2);
+    ResultDescriptor<int> descriptor1 = new ResultDescriptor<int>(
+        'result1', null,
+        cachingPolicy: cachingPolicy);
+    ResultDescriptor<int> descriptor2 = new ResultDescriptor<int>(
+        'result2', null,
+        cachingPolicy: cachingPolicy);
+    ResultDescriptor<int> descriptor3 = new ResultDescriptor<int>(
+        'result3', null,
+        cachingPolicy: cachingPolicy);
     AnalysisTarget target = new TestSource();
     CacheEntry entry = new CacheEntry(target);
     cache.put(entry);
@@ -406,7 +413,8 @@
 
   test_invalidateAllInformation() {
     AnalysisTarget target = new TestSource();
-    ResultDescriptor result = new ResultDescriptor('test', null);
+    ResultDescriptor<String> result =
+        new ResultDescriptor<String>('test', null);
     CacheEntry entry = new CacheEntry(target);
     cache.put(entry);
     entry.setValue(result, 'value', TargetedResult.EMPTY_LIST);
@@ -417,9 +425,9 @@
 
   test_setErrorState() {
     AnalysisTarget target = new TestSource();
-    ResultDescriptor result1 = new ResultDescriptor('res1', 1);
-    ResultDescriptor result2 = new ResultDescriptor('res2', 2);
-    ResultDescriptor result3 = new ResultDescriptor('res3', 3);
+    ResultDescriptor<int> result1 = new ResultDescriptor<int>('res1', 1);
+    ResultDescriptor<int> result2 = new ResultDescriptor<int>('res2', 2);
+    ResultDescriptor<int> result3 = new ResultDescriptor<int>('res3', 3);
     // prepare some good state
     CacheEntry entry = new CacheEntry(target);
     cache.put(entry);
@@ -446,10 +454,10 @@
     CacheEntry entry2 = new CacheEntry(target2);
     cache.put(entry1);
     cache.put(entry2);
-    ResultDescriptor result1 = new ResultDescriptor('result1', -1);
-    ResultDescriptor result2 = new ResultDescriptor('result2', -2);
-    ResultDescriptor result3 = new ResultDescriptor('result3', -3);
-    ResultDescriptor result4 = new ResultDescriptor('result4', -4);
+    ResultDescriptor<int> result1 = new ResultDescriptor<int>('result1', -1);
+    ResultDescriptor<int> result2 = new ResultDescriptor<int>('result2', -2);
+    ResultDescriptor<int> result3 = new ResultDescriptor<int>('result3', -3);
+    ResultDescriptor<int> result4 = new ResultDescriptor<int>('result4', -4);
     // set results, all of them are VALID
     entry1.setValue(result1, 111, TargetedResult.EMPTY_LIST);
     entry2.setValue(result2, 222, [new TargetedResult(target1, result1)]);
@@ -508,7 +516,7 @@
 
   test_setState_error() {
     AnalysisTarget target = new TestSource();
-    ResultDescriptor result = new ResultDescriptor('test', null);
+    ResultDescriptor<int> result = new ResultDescriptor<int>('test', null);
     CacheEntry entry = new CacheEntry(target);
     cache.put(entry);
     entry.setValue(result, 42, TargetedResult.EMPTY_LIST);
@@ -523,7 +531,7 @@
 
   test_setState_flushed() {
     AnalysisTarget target = new TestSource();
-    ResultDescriptor result = new ResultDescriptor('test', 1);
+    ResultDescriptor<int> result = new ResultDescriptor<int>('test', 1);
     CacheEntry entry = new CacheEntry(target);
     cache.put(entry);
     // set VALID
@@ -538,7 +546,7 @@
 
   test_setState_inProcess() {
     AnalysisTarget target = new TestSource();
-    ResultDescriptor result = new ResultDescriptor('test', 1);
+    ResultDescriptor<int> result = new ResultDescriptor<int>('test', 1);
     CacheEntry entry = new CacheEntry(target);
     cache.put(entry);
     // set VALID
@@ -553,7 +561,7 @@
 
   test_setState_invalid() {
     AnalysisTarget target = new TestSource();
-    ResultDescriptor result = new ResultDescriptor('test', 1);
+    ResultDescriptor<int> result = new ResultDescriptor<int>('test', 1);
     CacheEntry entry = new CacheEntry(target);
     cache.put(entry);
     // set VALID
@@ -581,7 +589,7 @@
     CacheEntry entry2 = new CacheEntry(target2);
     cache.put(entry1);
     cache.put(entry2);
-    ResultDescriptor result = new ResultDescriptor('result', -1);
+    ResultDescriptor<int> result = new ResultDescriptor<int>('result', -1);
     // Set each result as VALID with a dependency on on the other.
     entry1.setValue(result, 100, [new TargetedResult(target2, result)]);
     entry2.setValue(result, 200, [new TargetedResult(target1, result)]);
@@ -611,10 +619,10 @@
     AnalysisTarget target = new TestSource();
     CacheEntry entry = new CacheEntry(target);
     cache.put(entry);
-    ResultDescriptor result1 = new ResultDescriptor('result1', -1);
-    ResultDescriptor result2 = new ResultDescriptor('result2', -2);
-    ResultDescriptor result3 = new ResultDescriptor('result3', -3);
-    ResultDescriptor result4 = new ResultDescriptor('result4', -4);
+    ResultDescriptor<int> result1 = new ResultDescriptor<int>('result1', -1);
+    ResultDescriptor<int> result2 = new ResultDescriptor<int>('result2', -2);
+    ResultDescriptor<int> result3 = new ResultDescriptor<int>('result3', -3);
+    ResultDescriptor<int> result4 = new ResultDescriptor<int>('result4', -4);
     // set results, all of them are VALID
     entry.setValue(result1, 111, TargetedResult.EMPTY_LIST);
     entry.setValue(result2, 222, [new TargetedResult(target, result1)]);
@@ -647,7 +655,7 @@
     CacheEntry entry = new CacheEntry(target);
     entry.explicitlyAdded = true;
     cache.put(entry);
-    ResultDescriptor result = new ResultDescriptor('result1', -1);
+    ResultDescriptor<int> result = new ResultDescriptor<int>('result1', -1);
     // set results, all of them are VALID
     entry.setValue(result, 111, TargetedResult.EMPTY_LIST);
     expect(entry.getState(result), CacheState.VALID);
@@ -664,9 +672,9 @@
     CacheEntry entry2 = new CacheEntry(target2);
     cache.put(entry1);
     cache.put(entry2);
-    ResultDescriptor result1 = new ResultDescriptor('result1', -1);
-    ResultDescriptor result2 = new ResultDescriptor('result2', -2);
-    ResultDescriptor result3 = new ResultDescriptor('result3', -3);
+    ResultDescriptor<int> result1 = new ResultDescriptor<int>('result1', -1);
+    ResultDescriptor<int> result2 = new ResultDescriptor<int>('result2', -2);
+    ResultDescriptor<int> result3 = new ResultDescriptor<int>('result3', -3);
     // set results, all of them are VALID
     entry1.setValue(result1, 111, TargetedResult.EMPTY_LIST);
     entry2.setValue(result2, 222, [new TargetedResult(target1, result1)]);
@@ -687,9 +695,9 @@
     Source target = new TestSource('/test.dart');
     CacheEntry entry = new CacheEntry(target);
     cache.put(entry);
-    ResultDescriptor result1 = new ResultDescriptor('result1', -1);
-    ResultDescriptor result2 = new ResultDescriptor('result2', -2);
-    ResultDescriptor result3 = new ResultDescriptor('result3', -3);
+    ResultDescriptor<int> result1 = new ResultDescriptor<int>('result1', -1);
+    ResultDescriptor<int> result2 = new ResultDescriptor<int>('result2', -2);
+    ResultDescriptor<int> result3 = new ResultDescriptor<int>('result3', -3);
     // set results, all of them are VALID
     entry.setValue(result1, 111, TargetedResult.EMPTY_LIST);
     entry.setValue(result2, 222, [new TargetedResult(target, result1)]);
@@ -734,7 +742,8 @@
 
   test_setValue() {
     AnalysisTarget target = new TestSource();
-    ResultDescriptor result = new ResultDescriptor('test', null);
+    ResultDescriptor<String> result =
+        new ResultDescriptor<String>('test', null);
     String value = 'value';
     CacheEntry entry = new CacheEntry(target);
     cache.put(entry);
@@ -744,13 +753,17 @@
   }
 
   test_setValue_flushResults() {
-    ResultCachingPolicy cachingPolicy = new SimpleResultCachingPolicy(2, 2);
-    ResultDescriptor descriptor1 =
-        new ResultDescriptor('result1', null, cachingPolicy: cachingPolicy);
-    ResultDescriptor descriptor2 =
-        new ResultDescriptor('result2', null, cachingPolicy: cachingPolicy);
-    ResultDescriptor descriptor3 =
-        new ResultDescriptor('result3', null, cachingPolicy: cachingPolicy);
+    ResultCachingPolicy<int> cachingPolicy =
+        new SimpleResultCachingPolicy<int>(2, 2);
+    ResultDescriptor<int> descriptor1 = new ResultDescriptor<int>(
+        'result1', null,
+        cachingPolicy: cachingPolicy);
+    ResultDescriptor<int> descriptor2 = new ResultDescriptor<int>(
+        'result2', null,
+        cachingPolicy: cachingPolicy);
+    ResultDescriptor<int> descriptor3 = new ResultDescriptor<int>(
+        'result3', null,
+        cachingPolicy: cachingPolicy);
     AnalysisTarget target = new TestSource();
     CacheEntry entry = new CacheEntry(target);
     cache.put(entry);
@@ -772,12 +785,13 @@
   }
 
   test_setValue_flushResults_keepForPrioritySources() {
-    ResultCachingPolicy cachingPolicy = new SimpleResultCachingPolicy(2, 2);
-    ResultDescriptor newResult(String name) =>
-        new ResultDescriptor(name, null, cachingPolicy: cachingPolicy);
-    ResultDescriptor descriptor1 = newResult('result1');
-    ResultDescriptor descriptor2 = newResult('result2');
-    ResultDescriptor descriptor3 = newResult('result3');
+    ResultCachingPolicy<int> cachingPolicy =
+        new SimpleResultCachingPolicy<int>(2, 2);
+    ResultDescriptor<int> newResult(String name) =>
+        new ResultDescriptor<int>(name, null, cachingPolicy: cachingPolicy);
+    ResultDescriptor<int> descriptor1 = newResult('result1');
+    ResultDescriptor<int> descriptor2 = newResult('result2');
+    ResultDescriptor<int> descriptor3 = newResult('result3');
     TestSource source1 = new TestSource('/a.dart');
     TestSource source2 = new TestSource('/b.dart');
     TestSource source3 = new TestSource('/c.dart');
@@ -812,8 +826,8 @@
     AnalysisTarget target = new TestSource();
     CacheEntry entry = new CacheEntry(target);
     cache.put(entry);
-    ResultDescriptor result1 = new ResultDescriptor('result1', -1);
-    ResultDescriptor result2 = new ResultDescriptor('result2', -2);
+    ResultDescriptor<int> result1 = new ResultDescriptor<int>('result1', -1);
+    ResultDescriptor<int> result2 = new ResultDescriptor<int>('result2', -2);
     // set results, all of them are VALID
     entry.setValue(result1, 111, TargetedResult.EMPTY_LIST);
     entry.setValue(result2, 222, [new TargetedResult(target, result1)]);
@@ -836,8 +850,8 @@
     CacheEntry entry2 = new CacheEntry(target2);
     cache.put(entry1);
     cache.put(entry2);
-    ResultDescriptor result1 = new ResultDescriptor('result1', -1);
-    ResultDescriptor result2 = new ResultDescriptor('result2', -2);
+    ResultDescriptor<int> result1 = new ResultDescriptor<int>('result1', -1);
+    ResultDescriptor<int> result2 = new ResultDescriptor<int>('result2', -2);
     // set results, all of them are VALID
     entry2.setValue(result2, 222, [new TargetedResult(target1, result1)]);
     entry1.setValue(result1, 111, TargetedResult.EMPTY_LIST);
@@ -855,9 +869,9 @@
     AnalysisTarget target = new TestSource();
     CacheEntry entry = new CacheEntry(target);
     cache.put(entry);
-    ResultDescriptor result1 = new ResultDescriptor('result1', -1);
-    ResultDescriptor result2 = new ResultDescriptor('result2', -2);
-    ResultDescriptor result3 = new ResultDescriptor('result3', -3);
+    ResultDescriptor<int> result1 = new ResultDescriptor<int>('result1', -1);
+    ResultDescriptor<int> result2 = new ResultDescriptor<int>('result2', -2);
+    ResultDescriptor<int> result3 = new ResultDescriptor<int>('result3', -3);
     // set results, all of them are VALID
     entry.setValue(result1, 111, TargetedResult.EMPTY_LIST);
     entry.setValue(result2, 222, [new TargetedResult(target, result1)]);
@@ -890,7 +904,7 @@
 
   test_toString_nonEmpty() {
     AnalysisTarget target = new TestSource();
-    ResultDescriptor result = new ResultDescriptor('test', null);
+    ResultDescriptor<int> result = new ResultDescriptor<int>('test', null);
     CacheEntry entry = new CacheEntry(target);
     cache.put(entry);
     entry.setValue(result, 42, TargetedResult.EMPTY_LIST);
@@ -1246,8 +1260,10 @@
     when(context.analysisCache).thenReturn(cache);
     // configure
     // prepare entries
-    ResultDescriptor descriptor1 = new ResultDescriptor('result1', -1);
-    ResultDescriptor descriptor2 = new ResultDescriptor('result2', -2);
+    ResultDescriptor<int> descriptor1 =
+        new ResultDescriptor<int>('result1', -1);
+    ResultDescriptor<int> descriptor2 =
+        new ResultDescriptor<int>('result2', -2);
     AnalysisTarget target1 = new TestSource('1.dart');
     AnalysisTarget target2 = new TestSource('2.dart');
     TargetedResult result1 = new TargetedResult(target1, descriptor1);
diff --git a/pkg/analyzer/test/src/context/mock_sdk.dart b/pkg/analyzer/test/src/context/mock_sdk.dart
index 91b4e5e..b864e53 100644
--- a/pkg/analyzer/test/src/context/mock_sdk.dart
+++ b/pkg/analyzer/test/src/context/mock_sdk.dart
@@ -221,6 +221,7 @@
 class List<E> implements Iterable<E> {
   List();
   void add(E value) {}
+  void addAll(Iterable<E> iterable) {}
   E operator [](int index) => null;
   void operator []=(int index, E value) {}
   Iterator<E> get iterator => null;
diff --git a/pkg/analyzer/test/src/dart/element/element_test.dart b/pkg/analyzer/test/src/dart/element/element_test.dart
index 97a687a..a1f72b8 100644
--- a/pkg/analyzer/test/src/dart/element/element_test.dart
+++ b/pkg/analyzer/test/src/dart/element/element_test.dart
@@ -2755,15 +2755,17 @@
     expect(typeA.getMethod(methodName), same(methodM));
   }
 
-  void test_getMethod_parameterized() {
+  void test_getMethod_parameterized_doesNotUseTypeParameter() {
     //
-    // class A<E> { E m(E p) {} }
+    // class A<E> { void m() {} }
+    // class B {}
     //
     ClassElementImpl classA = ElementFactory.classElement2("A", ["E"]);
+    InterfaceType typeB = ElementFactory.classElement2("B").type;
     DartType typeE = classA.type.typeArguments[0];
     String methodName = "m";
     MethodElementImpl methodM =
-        ElementFactory.methodElement(methodName, typeE, [typeE]);
+        ElementFactory.methodElement(methodName, typeB, []);
     classA.methods = <MethodElement>[methodM];
     methodM.type = new FunctionTypeImpl(methodM);
     //
@@ -2775,10 +2777,8 @@
     MethodElement method = typeAI.getMethod(methodName);
     expect(method, isNotNull);
     FunctionType methodType = method.type;
-    expect(methodType.returnType, same(typeI));
-    List<DartType> parameterTypes = methodType.normalParameterTypes;
-    expect(parameterTypes, hasLength(1));
-    expect(parameterTypes[0], same(typeI));
+    expect(methodType.typeParameters, [same(typeE.element)]);
+    expect(methodType.typeArguments, [same(typeI)]);
   }
 
   void test_getMethod_parameterized_flushCached_whenVersionChanges() {
@@ -2806,6 +2806,34 @@
     expect(typeAI.methods.single, isNot(same(method)));
   }
 
+  void test_getMethod_parameterized_usesTypeParameter() {
+    //
+    // class A<E> { E m(E p) {} }
+    //
+    ClassElementImpl classA = ElementFactory.classElement2("A", ["E"]);
+    DartType typeE = classA.type.typeArguments[0];
+    String methodName = "m";
+    MethodElementImpl methodM =
+        ElementFactory.methodElement(methodName, typeE, [typeE]);
+    classA.methods = <MethodElement>[methodM];
+    methodM.type = new FunctionTypeImpl(methodM);
+    //
+    // A<I>
+    //
+    InterfaceType typeI = ElementFactory.classElement2("I").type;
+    InterfaceTypeImpl typeAI = new InterfaceTypeImpl(classA);
+    typeAI.typeArguments = <DartType>[typeI];
+    MethodElement method = typeAI.getMethod(methodName);
+    expect(method, isNotNull);
+    FunctionType methodType = method.type;
+    expect(methodType.typeParameters, [same(typeE.element)]);
+    expect(methodType.typeArguments, [same(typeI)]);
+    expect(methodType.returnType, same(typeI));
+    List<DartType> parameterTypes = methodType.normalParameterTypes;
+    expect(parameterTypes, hasLength(1));
+    expect(parameterTypes[0], same(typeI));
+  }
+
   void test_getMethod_unimplemented() {
     //
     // class A {}
diff --git a/pkg/analyzer/test/src/summary/pub_summary_test.dart b/pkg/analyzer/test/src/summary/pub_summary_test.dart
index 4ecf074..62804a3 100644
--- a/pkg/analyzer/test/src/summary/pub_summary_test.dart
+++ b/pkg/analyzer/test/src/summary/pub_summary_test.dart
@@ -174,6 +174,14 @@
     }
   }
 
+  test_getLinkedBundles_cached_declaredVariables_export() async {
+    await _testImpl_getLinkedBundles_cached_declaredVariables('export');
+  }
+
+  test_getLinkedBundles_cached_declaredVariables_import() async {
+    await _testImpl_getLinkedBundles_cached_declaredVariables('import');
+  }
+
   test_getLinkedBundles_cached_differentSdk() async {
     String pathA = '$CACHE/aaa';
     resourceProvider.newFile(
@@ -1258,9 +1266,10 @@
   }
 
   void _createManager(
-      {int majorVersion: PackageBundleAssembler.currentMajorVersion}) {
+      {bool allowLinking: true,
+      int majorVersion: PackageBundleAssembler.currentMajorVersion}) {
     manager = new PubSummaryManager(resourceProvider, '_.temp',
-        majorVersion: majorVersion);
+        allowLinking: allowLinking, majorVersion: majorVersion);
   }
 
   LinkedPubPackage _getLinkedPackage(
@@ -1269,6 +1278,87 @@
         .singleWhere((linkedPackage) => linkedPackage.package.name == name);
   }
 
+  _testImpl_getLinkedBundles_cached_declaredVariables(
+      String importOrExport) async {
+    String pathA = '$CACHE/aaa/lib';
+    resourceProvider.newFile('$pathA/foo.dart', 'class A {}');
+    resourceProvider.newFile('$pathA/foo_io.dart', 'class A {}');
+    resourceProvider.newFile('$pathA/foo_html.dart', 'class A {}');
+    resourceProvider.newFile(
+        '$pathA/user.dart',
+        '''
+$importOrExport 'foo.dart'
+  if (dart.library.io) 'foo_io.dart'
+  if (dart.library.html) 'foo_html.dart';
+''');
+    // Configure packages resolution.
+    Folder libFolderA = resourceProvider.newFolder(pathA);
+    context.sourceFactory = new SourceFactory(<UriResolver>[
+      sdkResolver,
+      resourceResolver,
+      new PackageMapUriResolver(resourceProvider, {
+        'aaa': [libFolderA],
+      })
+    ]);
+
+    void _assertDependencyInUser(PackageBundle bundle, String shortName) {
+      for (var i = 0; i < bundle.linkedLibraryUris.length; i++) {
+        if (bundle.linkedLibraryUris[i].endsWith('user.dart')) {
+          LinkedLibrary library = bundle.linkedLibraries[i];
+          expect(library.dependencies.map((d) => d.uri),
+              unorderedEquals(['', 'dart:core', shortName]));
+          return;
+        }
+      }
+      fail('Not found user.dart in $bundle');
+    }
+
+    // Session 1.
+    // Create the linked bundle and cache it in a file.
+    {
+      // Ensure unlinked bundles.
+      manager.getUnlinkedBundles(context);
+      await manager.onUnlinkedComplete;
+
+      // Now we should be able to get the linked bundle.
+      List<LinkedPubPackage> linkedPackages = manager.getLinkedBundles(context);
+      expect(linkedPackages, hasLength(1));
+    }
+
+    // Session 2.
+    // Recreate manager and don't allow it to perform new linking.
+    // Set a declared variable, which is not used in the package.
+    // We still can get the cached linked bundle.
+    {
+      context.declaredVariables.define('not.used.variable', 'baz');
+      _createManager(allowLinking: false);
+      List<LinkedPubPackage> linkedPackages = manager.getLinkedBundles(context);
+      expect(linkedPackages, hasLength(1));
+      _assertDependencyInUser(linkedPackages.single.linked, 'foo.dart');
+    }
+
+    // Session 3.
+    // Recreate manager and don't allow it to perform new linking.
+    // Set the value of a referenced declared variable.
+    // So, we cannot use the previously cached linked bundle.
+    {
+      context.declaredVariables.define('dart.library.io', 'does-not-matter');
+      _createManager(allowLinking: false);
+      List<LinkedPubPackage> linkedPackages = manager.getLinkedBundles(context);
+      expect(linkedPackages, isEmpty);
+    }
+
+    // Session 4.
+    // Enable new linking, and configure to use 'foo_html.dart'.
+    {
+      context.declaredVariables.define('dart.library.html', 'true');
+      _createManager();
+      List<LinkedPubPackage> linkedPackages = manager.getLinkedBundles(context);
+      expect(linkedPackages, hasLength(1));
+      _assertDependencyInUser(linkedPackages.single.linked, 'foo_html.dart');
+    }
+  }
+
   static PackageBundle _getBundleByPackageName(
       Map<PubPackage, PackageBundle> bundles, String name) {
     PubPackage package =
diff --git a/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart b/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
index 99d8ba9..126abe5 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
@@ -692,18 +692,6 @@
 
   @override
   @failingTest
-  test_const_invokeConstructor_named_unresolved() {
-    super.test_const_invokeConstructor_named_unresolved();
-  }
-
-  @override
-  @failingTest
-  test_const_invokeConstructor_named_unresolved3() {
-    super.test_const_invokeConstructor_named_unresolved3();
-  }
-
-  @override
-  @failingTest
   test_instantiateToBounds_boundRefersToLaterTypeArgument() {
     // TODO(paulberry): this is failing due to dartbug.com/27072.
     super.test_instantiateToBounds_boundRefersToLaterTypeArgument();
@@ -732,12 +720,6 @@
   test_syntheticFunctionType_withArguments() {
     super.test_syntheticFunctionType_withArguments();
   }
-
-  @override
-  @failingTest
-  test_unused_type_parameter() {
-    super.test_unused_type_parameter();
-  }
 }
 
 /**
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index bb75baf..aeebef5 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -522,7 +522,9 @@
         expect(o.atSign.lexeme, r.atSign.lexeme, reason: desc);
         Identifier rName = r.name;
         Identifier oName = o.name;
-        if (oName is PrefixedIdentifier && o.constructorName != null) {
+        if (oName is PrefixedIdentifier &&
+            o.constructorName != null &&
+            o.element != null) {
           // E.g. `@prefix.cls.ctor`.  This gets resynthesized as `@cls.ctor`,
           // with `cls.ctor` represented as a PrefixedIdentifier.
           expect(rName, new isInstanceOf<PrefixedIdentifier>(), reason: desc);
@@ -541,7 +543,9 @@
         compareConstAstLists(
             r.arguments?.arguments, o.arguments?.arguments, desc);
         Element expectedElement = o.element;
-        if (oName is PrefixedIdentifier && o.constructorName != null) {
+        if (oName is PrefixedIdentifier &&
+            o.constructorName != null &&
+            o.element != null) {
           // Due to dartbug.com/25706, [o.element] incorrectly points to the
           // class rather than the named constructor.  Hack around this.
           // TODO(paulberry): when dartbug.com/25706 is fixed, remove this.
@@ -639,10 +643,14 @@
 
   void compareElementAnnotations(ElementAnnotationImpl resynthesized,
       ElementAnnotationImpl original, String desc) {
-    expect(resynthesized.element, isNotNull, reason: desc);
-    expect(resynthesized.element.kind, original.element.kind, reason: desc);
-    expect(resynthesized.element.location, original.element.location,
-        reason: desc);
+    if (original.element == null) {
+      expect(resynthesized.element, isNull);
+    } else {
+      expect(resynthesized.element, isNotNull, reason: desc);
+      expect(resynthesized.element.kind, original.element.kind, reason: desc);
+      expect(resynthesized.element.location, original.element.location,
+          reason: desc);
+    }
     expect(resynthesized.compilationUnit, isNotNull, reason: desc);
     expect(resynthesized.compilationUnit.location,
         original.compilationUnit.location,
@@ -976,8 +984,8 @@
     expect(resynthesized.name, original.name, reason: desc);
   }
 
-  void compareTypeParameterElements(TypeParameterElementImpl resynthesized,
-      TypeParameterElementImpl original, String desc) {
+  void compareTypeParameterElements(TypeParameterElement resynthesized,
+      TypeParameterElement original, String desc) {
     compareElements(resynthesized, original, desc);
     compareTypes(resynthesized.type, original.type, desc);
     compareTypes(resynthesized.bound, original.bound, '$desc bound');
@@ -4456,6 +4464,51 @@
     checkLibrary('f() {} g() {}');
   }
 
+  test_unresolved_annotation_namedConstructorCall_noClass() {
+    checkLibrary('@foo.bar() class C {}');
+  }
+
+  test_unresolved_annotation_namedConstructorCall_noConstructor() {
+    checkLibrary('@String.foo() class C {}');
+  }
+
+  test_unresolved_annotation_prefixedIdentifier_badPrefix() {
+    checkLibrary('@foo.bar class C {}');
+  }
+
+  test_unresolved_annotation_prefixedIdentifier_noDeclaration() {
+    checkLibrary('import "dart:async" as foo; @foo.bar class C {}');
+  }
+
+  test_unresolved_annotation_prefixedNamedConstructorCall_badPrefix() {
+    checkLibrary('@foo.bar.baz() class C {}');
+  }
+
+  test_unresolved_annotation_prefixedNamedConstructorCall_noClass() {
+    checkLibrary('import "dart:async" as foo; @foo.bar.baz() class C {}');
+  }
+
+  @failingTest // See dartbug.com/25706
+  test_unresolved_annotation_prefixedNamedConstructorCall_noConstructor() {
+    checkLibrary('import "dart:async" as foo; @foo.Future.bar() class C {}');
+  }
+
+  test_unresolved_annotation_prefixedUnnamedConstructorCall_badPrefix() {
+    checkLibrary('@foo.bar() class C {}');
+  }
+
+  test_unresolved_annotation_prefixedUnnamedConstructorCall_noClass() {
+    checkLibrary('import "dart:async" as foo; @foo.bar() class C {}');
+  }
+
+  test_unresolved_annotation_simpleIdentifier() {
+    checkLibrary('@foo class C {}');
+  }
+
+  test_unresolved_annotation_unnamedConstructorCall_noClass() {
+    checkLibrary('@foo() class C {}');
+  }
+
   test_unresolved_export() {
     allowMissingFiles = true;
     checkLibrary("export 'foo.dart';", allowErrors: true);
diff --git a/pkg/analyzer/test/src/summary/summarize_ast_strong_test.dart b/pkg/analyzer/test/src/summary/summarize_ast_strong_test.dart
index 5146687..95e0ff8 100644
--- a/pkg/analyzer/test/src/summary/summarize_ast_strong_test.dart
+++ b/pkg/analyzer/test/src/summary/summarize_ast_strong_test.dart
@@ -129,10 +129,4 @@
   test_syntheticFunctionType_inGenericFunction() {
     super.test_syntheticFunctionType_inGenericFunction();
   }
-
-  @override
-  @failingTest
-  test_unused_type_parameter() {
-    super.test_unused_type_parameter();
-  }
 }
diff --git a/pkg/analyzer/test/src/summary/summarize_ast_test.dart b/pkg/analyzer/test/src/summary/summarize_ast_test.dart
index 439b801f..b17b6da 100644
--- a/pkg/analyzer/test/src/summary/summarize_ast_test.dart
+++ b/pkg/analyzer/test/src/summary/summarize_ast_test.dart
@@ -116,12 +116,6 @@
   test_syntheticFunctionType_inGenericFunction() {
     super.test_syntheticFunctionType_inGenericFunction();
   }
-
-  @override
-  @failingTest
-  test_unused_type_parameter() {
-    super.test_unused_type_parameter();
-  }
 }
 
 /**
diff --git a/pkg/analyzer/test/src/summary/summary_common.dart b/pkg/analyzer/test/src/summary/summary_common.dart
index 5abf015..7d90d0a 100644
--- a/pkg/analyzer/test/src/summary/summary_common.dart
+++ b/pkg/analyzer/test/src/summary/summary_common.dart
@@ -8091,8 +8091,7 @@
     // The type that is inferred for C.f's parameter g is "() -> void".
     // Since the associated element for that function type is B.f's parameter g,
     // and B has a type parameter, the inferred type will record a type
-    // parameter.  However, since that type parameter is irrelevant, the summary
-    // should encode it as `dynamic`.
+    // parameter.
     UnlinkedClass c = serializeClassText('''
 abstract class B<T> {
   void f(void g());
@@ -8109,7 +8108,7 @@
     EntityRef typeRef = getTypeRefForSlot(g.inferredTypeSlot);
     checkLinkedTypeRef(typeRef, null, null, 'f',
         expectedKind: ReferenceKind.method, numTypeArguments: 1);
-    checkLinkedDynamicTypeRef(typeRef.typeArguments[0]);
+    checkParamTypeRef(typeRef.typeArguments[0], 1);
   }
 
   test_inferred_type_keeps_leading_dynamic() {
@@ -9955,10 +9954,9 @@
   }
 
   test_unused_type_parameter() {
-    if (skipFullyLinkedData) {
+    if (!strongMode || skipFullyLinkedData) {
       return;
     }
-    // Unused type parameters get converted to `dynamic`.
     UnlinkedVariable variable = serializeVariableText('''
 class C<T> {
   void f() {}
@@ -9969,7 +9967,7 @@
     EntityRef type =
         getTypeRefForSlot(variable.initializer.inferredReturnTypeSlot);
     expect(type.typeArguments, hasLength(1));
-    checkLinkedTypeRef(type.typeArguments[0], null, null, 'dynamic');
+    checkLinkedTypeRef(type.typeArguments[0], 'dart:core', 'dart:core', 'int');
   }
 
   test_variable() {
diff --git a/pkg/analyzer/test/src/summary/test_all.dart b/pkg/analyzer/test/src/summary/test_all.dart
index f4987f4..ba099c7 100644
--- a/pkg/analyzer/test/src/summary/test_all.dart
+++ b/pkg/analyzer/test/src/summary/test_all.dart
@@ -10,7 +10,6 @@
 import 'api_signature_test.dart' as api_signature_test;
 import 'flat_buffers_test.dart' as flat_buffers_test;
 import 'in_summary_source_test.dart' as in_summary_source_test;
-import 'index_unit_test.dart' as index_unit_test;
 import 'linker_test.dart' as linker_test;
 import 'name_filter_test.dart' as name_filter_test;
 import 'package_bundle_reader_test.dart' as package_bundle_reader_test;
@@ -27,7 +26,6 @@
     api_signature_test.main();
     flat_buffers_test.main();
     in_summary_source_test.main();
-    index_unit_test.main();
     linker_test.main();
     name_filter_test.main();
     package_bundle_reader_test.main();
diff --git a/pkg/analyzer/test/src/task/dart_test.dart b/pkg/analyzer/test/src/task/dart_test.dart
index f9ebf8c..403467e 100644
--- a/pkg/analyzer/test/src/task/dart_test.dart
+++ b/pkg/analyzer/test/src/task/dart_test.dart
@@ -15,7 +15,7 @@
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/engine.dart'
-    show AnalysisOptions, AnalysisOptionsImpl, CacheState;
+    show AnalysisOptionsImpl, CacheState;
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -33,7 +33,6 @@
 import '../../generated/test_support.dart';
 import '../../utils.dart';
 import '../context/abstract_context.dart';
-import '../context/mock_sdk.dart';
 
 main() {
   initializeTestEnvironment();
@@ -45,7 +44,6 @@
   defineReflectiveTests(BuildPublicNamespaceTaskTest);
   defineReflectiveTests(BuildSourceExportClosureTaskTest);
   defineReflectiveTests(BuildTypeProviderTaskTest);
-  defineReflectiveTests(BuildTypeProviderTaskTest_noAsync);
   defineReflectiveTests(ComputeConstantDependenciesTaskTest);
   defineReflectiveTests(ComputeConstantValueTaskTest);
   defineReflectiveTests(ComputeInferableStaticVariableDependenciesTaskTest);
@@ -1128,29 +1126,6 @@
 }
 
 @reflectiveTest
-class BuildTypeProviderTaskTest_noAsync extends _AbstractDartTaskTest {
-  DartSdk createDartSdk() => new MockSdk(dartAsync: false);
-
-  void prepareAnalysisContext([AnalysisOptions options]) {
-    AnalysisOptionsImpl newOptions = new AnalysisOptionsImpl();
-    newOptions.enableAsync = false;
-    super.prepareAnalysisContext(newOptions);
-  }
-
-  test_perform_noAsync() {
-    expect(context, isNotNull);
-    computeResult(AnalysisContextTarget.request, TYPE_PROVIDER,
-        matcher: isBuildTypeProviderTask);
-    // validate
-    TypeProvider typeProvider = outputs[TYPE_PROVIDER];
-    expect(typeProvider, isNotNull);
-    expect(typeProvider.boolType, isNotNull);
-    expect(typeProvider.intType, isNotNull);
-    expect(typeProvider.futureType, isNotNull);
-  }
-}
-
-@reflectiveTest
 class ComputeConstantDependenciesTaskTest extends _AbstractDartTaskTest {
   Annotation findClassAnnotation(CompilationUnit unit, String className) {
     for (CompilationUnitMember member in unit.declarations) {
@@ -3196,45 +3171,6 @@
     expect(outputs[UNITS], hasLength(1));
   }
 
-  test_perform_enableAsync_false() {
-    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
-    options.enableAsync = false;
-    prepareAnalysisContext(options);
-    _performParseTask(r'''
-import 'dart:async';
-class B {void foo() async {}}''');
-    expect(outputs, hasLength(11));
-    expect(outputs[EXPLICITLY_IMPORTED_LIBRARIES], hasLength(1));
-    expect(outputs[EXPORTED_LIBRARIES], hasLength(0));
-    _assertHasCore(outputs[IMPORTED_LIBRARIES], 2);
-    expect(outputs[INCLUDED_PARTS], hasLength(0));
-    expect(outputs[LIBRARY_SPECIFIC_UNITS], hasLength(1));
-    expect(outputs[PARSE_ERRORS], hasLength(1));
-    expect(outputs[PARSED_UNIT], isNotNull);
-    expect(outputs[REFERENCED_NAMES], isNotNull);
-    expect(outputs[REFERENCED_SOURCES], hasLength(3));
-    expect(outputs[SOURCE_KIND], SourceKind.LIBRARY);
-    expect(outputs[UNITS], hasLength(1));
-  }
-
-  test_perform_enableAsync_true() {
-    _performParseTask(r'''
-import 'dart:async';
-class B {void foo() async {}}''');
-    expect(outputs, hasLength(11));
-    expect(outputs[EXPLICITLY_IMPORTED_LIBRARIES], hasLength(1));
-    expect(outputs[EXPORTED_LIBRARIES], hasLength(0));
-    _assertHasCore(outputs[IMPORTED_LIBRARIES], 2);
-    expect(outputs[INCLUDED_PARTS], hasLength(0));
-    expect(outputs[LIBRARY_SPECIFIC_UNITS], hasLength(1));
-    expect(outputs[PARSE_ERRORS], hasLength(0));
-    expect(outputs[PARSED_UNIT], isNotNull);
-    expect(outputs[REFERENCED_NAMES], isNotNull);
-    expect(outputs[REFERENCED_SOURCES], hasLength(3));
-    expect(outputs[SOURCE_KIND], SourceKind.LIBRARY);
-    expect(outputs[UNITS], hasLength(1));
-  }
-
   test_perform_flushTokenStream() {
     _performParseTask(r'''
 class Test {}
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 84f3f63..12388d0 100644
--- a/pkg/analyzer/test/src/task/dart_work_manager_test.dart
+++ b/pkg/analyzer/test/src/task/dart_work_manager_test.dart
@@ -357,11 +357,13 @@
     when(context.aboutToComputeResult(anyObject, CONTAINING_LIBRARIES))
         .thenInvoke((CacheEntry entry, ResultDescriptor result) {
       if (entry.target == part1) {
-        entry.setValue(result, <Source>[library1, library2], []);
+        entry.setValue(result as ResultDescriptor<List<Source>>,
+            <Source>[library1, library2], []);
         return true;
       }
       if (entry.target == part2) {
-        entry.setValue(result, <Source>[library2], []);
+        entry.setValue(
+            result as ResultDescriptor<List<Source>>, <Source>[library2], []);
         return true;
       }
       return false;
diff --git a/pkg/analyzer/test/src/task/driver_test.dart b/pkg/analyzer/test/src/task/driver_test.dart
index 14620f7..35ff657 100644
--- a/pkg/analyzer/test/src/task/driver_test.dart
+++ b/pkg/analyzer/test/src/task/driver_test.dart
@@ -187,7 +187,8 @@
 
   test_createWorkOrderForResult_valid() {
     AnalysisTarget target = new TestSource();
-    ResultDescriptor result = new ResultDescriptor('result', null);
+    ResultDescriptor<String> result =
+        new ResultDescriptor<String>('result', null);
     context
         .getCacheEntry(target)
         .setValue(result, '', TargetedResult.EMPTY_LIST);
@@ -479,7 +480,8 @@
   _createWorkOrderForTarget(
       bool complete, bool priorityTarget, bool priorityResult) {
     AnalysisTarget target = new TestSource();
-    ResultDescriptor result = new ResultDescriptor('result', null);
+    ResultDescriptor<String> result =
+        new ResultDescriptor<String>('result', null);
     TaskDescriptor descriptor = new TaskDescriptor(
         'task',
         (context, target) => new TestAnalysisTask(context, target),
diff --git a/pkg/analyzer/test/src/task/options_test.dart b/pkg/analyzer/test/src/task/options_test.dart
index def44fd..8e50dc0 100644
--- a/pkg/analyzer/test/src/task/options_test.dart
+++ b/pkg/analyzer/test/src/task/options_test.dart
@@ -54,23 +54,6 @@
     expect(analysisOptions.strongMode, false);
   }
 
-  test_configure_enableAsync() {
-    configureContext('''
-analyzer:
-  language:
-''');
-    expect(analysisOptions.enableAsync, true);
-  }
-
-  test_configure_enableAsync_false() {
-    configureContext('''
-analyzer:
-  language:
-    enableAsync: false
-''');
-    expect(analysisOptions.enableAsync, false);
-  }
-
   test_configure_enableGenericMethods() {
     expect(analysisOptions.enableGenericMethods, false);
     configureContext('''
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart
index ae8ba3a..ef9b1eb 100644
--- a/pkg/analyzer/test/src/task/strong/checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -265,12 +265,15 @@
   D operator +(D d) => null;
 }
 
+class SubA extends A {}
+class SubSubA extends SubA {}
+
 foo() => new A();
 
 test() {
   int x = 0;
   x += 5;
-  /*error:STATIC_TYPE_ERROR*/x += /*error:INVALID_ASSIGNMENT*/3.14;
+  x += /*error:INVALID_ASSIGNMENT*/3.14;
 
   double y = 0.0;
   y += 5;
@@ -281,12 +284,12 @@
   z += 3.14;
 
   x = /*info:DOWN_CAST_IMPLICIT*/x + z;
-  x += /*info:DOWN_CAST_IMPLICIT*/z;
+  /*info:DOWN_CAST_IMPLICIT_ASSIGN*/x += z;
   y = y + z;
   y += z;
 
   dynamic w = 42;
-  x += /*info:DYNAMIC_CAST*/w;
+  /*info:DOWN_CAST_IMPLICIT_ASSIGN*/x += /*info:DYNAMIC_CAST*/w;
   y += /*info:DYNAMIC_CAST*/w;
   z += /*info:DYNAMIC_CAST*/w;
 
@@ -302,7 +305,7 @@
   a += b;
   a += /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/a;
   a -= b;
-  /*error:STATIC_TYPE_ERROR*/b -= /*error:INVALID_ASSIGNMENT*/b;
+  b -= /*error:INVALID_ASSIGNMENT*/b;
   a <<= b;
   a >>= b;
   a &= b;
@@ -310,6 +313,10 @@
   a |= b;
   /*info:DYNAMIC_INVOKE*/c += b;
 
+  SubA sa;
+  /*info:DOWN_CAST_IMPLICIT_ASSIGN*/sa += b;
+  SubSubA ssa = /*info:ASSIGNMENT_CAST,info:DOWN_CAST_IMPLICIT_ASSIGN*/sa += b;
+
   var d = new D();
   a[b] += d;
   a[/*info:DYNAMIC_CAST*/c] += d;
@@ -373,6 +380,20 @@
     ''');
   }
 
+  void test_compoundAssignment_returnsDynamic() {
+    checkFile(r'''
+class Foo {
+  operator +(other) => null;
+}
+
+main() {
+  var foo = new Foo();
+  foo = /*info:DYNAMIC_CAST*/foo + 1;
+  /*info:DYNAMIC_CAST*/foo += 1;
+}
+    ''');
+  }
+
   void test_constructorInvalid() {
     // Regression test for https://github.com/dart-lang/sdk/issues/26695
     checkFile('''
@@ -3845,11 +3866,14 @@
   A operator -(int x) => null;
   A operator -() => null;
 }
+class B extends A {}
+class C extends B {}
 
 foo() => new A();
 
 test() {
   A a = new A();
+  B b = new B();
   var c = foo();
   dynamic d;
 
@@ -3871,6 +3895,17 @@
   a--;
   (/*info:DYNAMIC_INVOKE*/d++);
   (/*info:DYNAMIC_INVOKE*/d--);
+
+  ++/*info:DOWN_CAST_IMPLICIT_ASSIGN*/b;
+  --/*info:DOWN_CAST_IMPLICIT_ASSIGN*/b;
+  /*info:DOWN_CAST_IMPLICIT_ASSIGN*/b++;
+  /*info:DOWN_CAST_IMPLICIT_ASSIGN*/b--;
+
+  takesC(C c) => null;
+  takesC(/*info:DOWN_CAST_IMPLICIT*/++/*info:DOWN_CAST_IMPLICIT_ASSIGN*/b);
+  takesC(/*info:DOWN_CAST_IMPLICIT*/--/*info:DOWN_CAST_IMPLICIT_ASSIGN*/b);
+  takesC(/*info:DOWN_CAST_IMPLICIT,info:DOWN_CAST_IMPLICIT_ASSIGN*/b++);
+  takesC(/*info:DOWN_CAST_IMPLICIT,info:DOWN_CAST_IMPLICIT_ASSIGN*/b--);
 }''');
   }
 
diff --git a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
index e9ccb34..4928bd5 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -700,6 +700,17 @@
     expect(unit.topLevelVariables[0].type.toString(), 'C<int>');
   }
 
+  void test_constructors_inferFromArguments_factory_callsConstructor() {
+    checkFile(r'''
+class A<T> {
+  A<T> f = /*info:INFERRED_TYPE_ALLOCATION*/new A();
+  A();
+  factory A.factory() => /*info:INFERRED_TYPE_ALLOCATION*/new A();
+  A<T> m() => /*info:INFERRED_TYPE_ALLOCATION*/new A();
+}
+    ''');
+  }
+
   void test_constructors_inferFromArguments_named() {
     var unit = checkFile('''
 class C<T> {
@@ -899,8 +910,8 @@
 import 'dart:async';
 Future test() async {
   dynamic d;
-  List<int> l0 = await /*info:INFERRED_TYPE_LITERAL*/[/*info:DYNAMIC_CAST*/d];
-  List<int> l1 = await /*info:INFERRED_TYPE_ALLOCATION*/new Future.value(/*info:INFERRED_TYPE_LITERAL*/[/*info:DYNAMIC_CAST*/d]);
+  List<int> l0 = await /*info:INFERRED_TYPE_LITERAL,error:COULD_NOT_INFER*/[/*info:DYNAMIC_CAST*/d];
+  List<int> l1 = await /*info:INFERRED_TYPE_ALLOCATION*/new Future.value(/*info:INFERRED_TYPE_LITERAL,error:COULD_NOT_INFER*/[/*info:DYNAMIC_CAST*/d]);
 }
 ''');
   }
@@ -1880,19 +1891,15 @@
     checkFile(r'''
 void main() {
   List<int> o;
-  var x = o.fold(0, /*info:INFERRED_TYPE_CLOSURE*/(int x, y) => x + y);
   int y = o.fold(0, /*info:INFERRED_TYPE_CLOSURE*/(x, y) => x + y);
-  var z = o.fold(0, /*info:INFERRED_TYPE_CLOSURE,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/(x, y) => /*info:DYNAMIC_INVOKE*/x + y);
-  y = z;
-  y = x;
+  var z = o.fold(0, /*info:INFERRED_TYPE_CLOSURE*/(x, y) => /*info:DYNAMIC_INVOKE*/x + y);
+  y = /*info:DYNAMIC_CAST*/z;
 }
 void functionExpressionInvocation() {
   List<int> o;
-  var x = (o.fold)(0, /*info:INFERRED_TYPE_CLOSURE*/(int x, y) => x + y);
   int y = (o.fold)(0, /*info:INFERRED_TYPE_CLOSURE*/(x, y) => x + y);
-  var z = (o.fold)(0, /*info:INFERRED_TYPE_CLOSURE,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/(x, y) => /*info:DYNAMIC_INVOKE*/x + y);
-  y = z;
-  y = x;
+  var z = (o.fold)(0, /*info:INFERRED_TYPE_CLOSURE*/(x, y) => /*info:DYNAMIC_INVOKE*/x + y);
+  y = /*info:DYNAMIC_CAST*/z;
 }
 ''');
   }
diff --git a/pkg/analyzer/test/src/task/strong/non_null_checker_test.dart b/pkg/analyzer/test/src/task/strong/non_null_checker_test.dart
index 8db9b24..d130a54 100644
--- a/pkg/analyzer/test/src/task/strong/non_null_checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/non_null_checker_test.dart
@@ -111,7 +111,7 @@
 void main() {
   int i = 1;
   i += 2;
-  /*error:STATIC_TYPE_ERROR*/i += null;
+  /*error:INVALID_ASSIGNMENT*/i += null;
   print(i);
 }
 ''');
diff --git a/pkg/analyzer/test/test_all.dart b/pkg/analyzer/test/test_all.dart
index 7e45412..1d598fb 100644
--- a/pkg/analyzer/test/test_all.dart
+++ b/pkg/analyzer/test/test_all.dart
@@ -8,7 +8,6 @@
 
 import 'cancelable_future_test.dart' as cancelable_future_test;
 import 'context/test_all.dart' as context;
-import 'enum_test.dart' as enum_test;
 import 'file_system/test_all.dart' as file_system;
 import 'generated/test_all.dart' as generated;
 import 'instrumentation/test_all.dart' as instrumentation;
@@ -23,7 +22,6 @@
   group('analysis engine', () {
     cancelable_future_test.main();
     context.main();
-    enum_test.main();
     file_system.main();
     generated.main();
     instrumentation.main();
diff --git a/pkg/analyzer/tool/task_dependency_graph/generate.dart b/pkg/analyzer/tool/task_dependency_graph/generate.dart
index 068790f..9761e90 100644
--- a/pkg/analyzer/tool/task_dependency_graph/generate.dart
+++ b/pkg/analyzer/tool/task_dependency_graph/generate.dart
@@ -156,9 +156,11 @@
     context = AnalysisEngine.instance.createAnalysisContext();
     ContextBuilder builder = new ContextBuilder(resourceProvider, null, null);
     if (Platform.packageRoot != null) {
-      builder.defaultPackagesDirectoryPath = Uri.parse(Platform.packageRoot).toFilePath();
+      builder.defaultPackagesDirectoryPath =
+        Uri.parse(Platform.packageRoot).toFilePath();
     } else if (Platform.packageConfig != null) {
-      builder.defaultPackageFilePath = Platform.packageConfig;
+      builder.defaultPackageFilePath =
+        Uri.parse(Platform.packageConfig).toFilePath();
     } else {
       // Let the context builder use the default algorithm for package
       // resolution.
diff --git a/pkg/analyzer_cli/lib/src/analyzer_impl.dart b/pkg/analyzer_cli/lib/src/analyzer_impl.dart
index 9f75bf9..14b61b8 100644
--- a/pkg/analyzer_cli/lib/src/analyzer_impl.dart
+++ b/pkg/analyzer_cli/lib/src/analyzer_impl.dart
@@ -8,10 +8,11 @@
 import 'dart:io';
 
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/error/error.dart';
 import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/source/error_processor.dart';
+import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/java_io.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
diff --git a/pkg/analyzer_cli/lib/src/build_mode.dart b/pkg/analyzer_cli/lib/src/build_mode.dart
index 700e797..a8e9757 100644
--- a/pkg/analyzer_cli/lib/src/build_mode.dart
+++ b/pkg/analyzer_cli/lib/src/build_mode.dart
@@ -8,10 +8,10 @@
 import 'dart:io' as io;
 
 import 'package:analyzer/dart/ast/ast.dart' show CompilationUnit;
+import 'package:analyzer/error/error.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart';
 import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index 185290b..ec779a7 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -8,6 +8,7 @@
 import 'dart:convert';
 import 'dart:io' as io;
 
+import 'package:analyzer/error/error.dart';
 import 'package:analyzer/file_system/file_system.dart' as file_system;
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
@@ -22,7 +23,6 @@
 import 'package:analyzer/src/dart/sdk/sdk.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/interner.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/sdk.dart';
diff --git a/pkg/analyzer_cli/lib/src/error_formatter.dart b/pkg/analyzer_cli/lib/src/error_formatter.dart
index e0c9a8e..cac83b3 100644
--- a/pkg/analyzer_cli/lib/src/error_formatter.dart
+++ b/pkg/analyzer_cli/lib/src/error_formatter.dart
@@ -4,8 +4,8 @@
 
 library analyzer_cli.src.error_formatter;
 
+import 'package:analyzer/error/error.dart';
 import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer_cli/src/options.dart';
 
@@ -171,6 +171,7 @@
     }
     out.writeln();
   }
+
   void formatErrors(List<AnalysisErrorInfo> errorInfos) {
     stats.unfilteredCount += errorInfos.length;
 
diff --git a/pkg/analyzer_cli/test/data/super_mixin_example.dart b/pkg/analyzer_cli/test/data/super_mixin_example.dart
index ea90486..8983592 100644
--- a/pkg/analyzer_cli/test/data/super_mixin_example.dart
+++ b/pkg/analyzer_cli/test/data/super_mixin_example.dart
@@ -8,7 +8,7 @@
 }
 
 abstract class B {
-  void foo();
+  void foo() {}
 }
 
 abstract class C extends B {
diff --git a/pkg/analyzer_cli/test/driver_test.dart b/pkg/analyzer_cli/test/driver_test.dart
index 58b5c1a..cacbc28 100644
--- a/pkg/analyzer_cli/test/driver_test.dart
+++ b/pkg/analyzer_cli/test/driver_test.dart
@@ -6,13 +6,15 @@
 
 import 'dart:io';
 
+import 'package:analyzer/error/error.dart';
 import 'package:analyzer/plugin/options.dart';
 import 'package:analyzer/source/analysis_options_provider.dart';
 import 'package:analyzer/source/error_processor.dart';
+import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/services/lint.dart';
+import 'package:analyzer/src/task/options.dart';
 import 'package:analyzer_cli/src/driver.dart';
 import 'package:analyzer_cli/src/options.dart';
 import 'package:path/path.dart' as path;
@@ -204,6 +206,7 @@
           });
         });
       }
+
       createTests('old', AnalysisEngine.ANALYSIS_OPTIONS_FILE);
       createTests('new', AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE);
     });
@@ -303,6 +306,7 @@
           });
         });
       }
+
       createTests('old', AnalysisEngine.ANALYSIS_OPTIONS_FILE);
       createTests('new', AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE);
     });
@@ -351,6 +355,7 @@
         });
       });
     }
+
     createTests('old', AnalysisEngine.ANALYSIS_OPTIONS_FILE);
     createTests('new', AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE);
 
@@ -459,6 +464,7 @@
     return new File(path.join(sdkDir, 'lib', '_internal', 'spec.sum'))
         .existsSync();
   }
+
   // Usually the sdk directory is the parent of the parent of the "dart"
   // executable.
   Directory executableParent = new File(Platform.executable).parent;
diff --git a/pkg/compiler/lib/src/closure.dart b/pkg/compiler/lib/src/closure.dart
index 7b71e69..f44b2d2 100644
--- a/pkg/compiler/lib/src/closure.dart
+++ b/pkg/compiler/lib/src/closure.dart
@@ -19,7 +19,7 @@
 import 'resolution/tree_elements.dart' show TreeElements;
 import 'tokens/token.dart' show Token;
 import 'tree/tree.dart';
-import 'universe/universe.dart' show Universe;
+import 'universe/universe.dart' show CodegenUniverse;
 import 'util/util.dart';
 
 class ClosureTask extends CompilerTask {
@@ -517,14 +517,6 @@
       scope.forEachCapturedVariable(f);
     });
   }
-
-  void removeMyselfFrom(Universe universe) {
-    freeVariableMap.values.forEach((e) {
-      universe.closurizedMembers.remove(e);
-      universe.fieldSetters.remove(e);
-      universe.fieldGetters.remove(e);
-    });
-  }
 }
 
 class ClosureTranslator extends Visitor {
@@ -1054,8 +1046,7 @@
     ClosureClassElement globalizedElement =
         new ClosureClassElement(node, closureName, compiler, element);
     // Extend [globalizedElement] as an instantiated class in the closed world.
-    compiler.world
-        .registerClass(globalizedElement, isDirectlyInstantiated: true);
+    compiler.inferenceWorld.registerClosureClass(globalizedElement);
     FunctionElement callElement = new SynthesizedCallMethodElementX(
         Identifiers.call, element, globalizedElement, node, elements);
     backend.maybeMarkClosureAsNeededForReflection(
diff --git a/pkg/compiler/lib/src/common/backend_api.dart b/pkg/compiler/lib/src/common/backend_api.dart
index 7906b04..258a38f 100644
--- a/pkg/compiler/lib/src/common/backend_api.dart
+++ b/pkg/compiler/lib/src/common/backend_api.dart
@@ -30,7 +30,8 @@
 import '../serialization/serialization.dart'
     show DeserializerPlugin, SerializerPlugin;
 import '../tree/tree.dart' show Node;
-import '../universe/world_impact.dart' show ImpactStrategy, WorldImpact;
+import '../universe/world_impact.dart'
+    show ImpactStrategy, WorldImpact, WorldImpactBuilder;
 import 'codegen.dart' show CodegenWorkItem;
 import 'registry.dart' show Registry;
 import 'tasks.dart' show CompilerTask;
@@ -116,7 +117,8 @@
   bool enableDeferredLoadingIfSupported(Spannable node, Registry registry);
 
   /// Called during codegen when [constant] has been used.
-  void registerCompileTimeConstant(ConstantValue constant, Registry registry) {}
+  void computeImpactForCompileTimeConstant(ConstantValue constant,
+      WorldImpactBuilder impactBuilder, bool isForResolution) {}
 
   /// Called to notify to the backend that a class is being instantiated.
   // TODO(johnniwinther): Remove this. It's only called once for each [cls] and
@@ -153,9 +155,7 @@
   /// Called to instruct the backend to register that a closure exists for a
   /// function on an instantiated generic class.
   void registerClosureWithFreeTypeVariables(
-      Element closure, Enqueuer enqueuer, Registry registry) {
-    enqueuer.universe.closuresWithFreeTypeVariables.add(closure);
-  }
+      Element closure, Enqueuer enqueuer, Registry registry) {}
 
   /// Call this to register that a member has been closurized.
   void registerBoundClosure(Enqueuer enqueuer) {}
diff --git a/pkg/compiler/lib/src/common/codegen.dart b/pkg/compiler/lib/src/common/codegen.dart
index 84eb422..5214585 100644
--- a/pkg/compiler/lib/src/common/codegen.dart
+++ b/pkg/compiler/lib/src/common/codegen.dart
@@ -19,17 +19,14 @@
 import '../enqueue.dart' show Enqueuer;
 import '../universe/use.dart' show DynamicUse, StaticUse, TypeUse;
 import '../universe/world_impact.dart'
-    show WorldImpact, WorldImpactBuilder, WorldImpactVisitor;
+    show WorldImpact, WorldImpactBuilderImpl, WorldImpactVisitor;
 import '../util/util.dart' show Pair, Setlet;
-import 'registry.dart' show Registry, EagerRegistry;
+import 'registry.dart' show Registry;
 import 'work.dart' show WorkItem;
 
 class CodegenImpact extends WorldImpact {
   const CodegenImpact();
 
-  // TODO(johnniwinther): Remove this.
-  Registry get registry => null;
-
   Iterable<ConstantValue> get compileTimeConstants => const <ConstantValue>[];
 
   Iterable<Pair<DartType, DartType>> get typeVariableBoundsSubtypeChecks {
@@ -49,10 +46,7 @@
   Iterable<Element> get asyncMarkers => const <FunctionElement>[];
 }
 
-class _CodegenImpact extends WorldImpactBuilder implements CodegenImpact {
-  // TODO(johnniwinther): Remove this.
-  final Registry registry;
-
+class _CodegenImpact extends WorldImpactBuilderImpl implements CodegenImpact {
   Setlet<ConstantValue> _compileTimeConstants;
   Setlet<Pair<DartType, DartType>> _typeVariableBoundsSubtypeChecks;
   Setlet<String> _constSymbols;
@@ -61,7 +55,7 @@
   Setlet<ClassElement> _typeConstants;
   Setlet<FunctionElement> _asyncMarkers;
 
-  _CodegenImpact(this.registry);
+  _CodegenImpact();
 
   void apply(WorldImpactVisitor visitor) {
     staticUses.forEach(visitor.visitStaticUse);
@@ -160,8 +154,7 @@
   CodegenRegistry(Compiler compiler, AstElement currentElement)
       : this.compiler = compiler,
         this.currentElement = currentElement,
-        this.worldImpact = new _CodegenImpact(new EagerRegistry(
-            'EagerRegistry for $currentElement', compiler.enqueuer.codegen));
+        this.worldImpact = new _CodegenImpact();
 
   bool get isForResolution => false;
 
diff --git a/pkg/compiler/lib/src/common/registry.dart b/pkg/compiler/lib/src/common/registry.dart
index 96ee845..08d6081 100644
--- a/pkg/compiler/lib/src/common/registry.dart
+++ b/pkg/compiler/lib/src/common/registry.dart
@@ -4,48 +4,10 @@
 
 library dart2js.common.registry;
 
-import '../dart_types.dart' show InterfaceType;
 import '../elements/elements.dart' show Element;
-import '../enqueue.dart' show Enqueuer;
-import '../universe/use.dart' show DynamicUse, StaticUse;
-
-/// Interface for registration of element dependencies.
-abstract class Registry {
-  // TODO(johnniwinther): Remove this.
-  void registerDependency(Element element) {}
-
-  bool get isForResolution;
-
-  void registerDynamicUse(DynamicUse staticUse);
-
-  void registerStaticUse(StaticUse staticUse);
-
-  void registerInstantiation(InterfaceType type);
-}
 
 // TODO(johnniwinther): Remove this.
-class EagerRegistry extends Registry {
-  final String name;
-  final Enqueuer world;
-
-  EagerRegistry(this.name, this.world);
-
-  bool get isForResolution => world.isResolutionQueue;
-
-  @override
-  void registerDynamicUse(DynamicUse dynamicUse) {
-    world.registerDynamicUse(dynamicUse);
-  }
-
-  @override
-  void registerInstantiation(InterfaceType type) {
-    world.registerInstantiatedType(type);
-  }
-
-  @override
-  void registerStaticUse(StaticUse staticUse) {
-    world.registerStaticUse(staticUse);
-  }
-
-  String toString() => name;
+/// Interface for registration of element dependencies.
+abstract class Registry {
+  void registerDependency(Element element) {}
 }
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index c7d00d8..5667a4e 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -13,7 +13,7 @@
 import 'common/codegen.dart' show CodegenWorkItem;
 import 'common/names.dart' show Selectors;
 import 'common/names.dart' show Identifiers, Uris;
-import 'common/registry.dart' show EagerRegistry, Registry;
+import 'common/registry.dart' show Registry;
 import 'common/resolution.dart'
     show
         ParsingContext,
@@ -73,11 +73,11 @@
 import 'types/types.dart' show GlobalTypeInferenceTask;
 import 'types/masks.dart' show CommonMasks;
 import 'universe/selector.dart' show Selector;
-import 'universe/universe.dart' show Universe;
+import 'universe/universe.dart' show ResolutionUniverse, CodegenUniverse;
 import 'universe/use.dart' show StaticUse;
 import 'universe/world_impact.dart' show ImpactStrategy, WorldImpact;
 import 'util/util.dart' show Link, Setlet;
-import 'world.dart' show World;
+import 'world.dart' show ClosedWorld, ClosedWorldRefiner, OpenWorld, WorldImpl;
 
 typedef Backend MakeBackendFuncion(Compiler compiler);
 
@@ -88,7 +88,7 @@
   Measurer get measurer;
 
   final IdGenerator idGenerator = new IdGenerator();
-  World world;
+  WorldImpl _world;
   Types types;
   _CompilerCoreTypes _coreTypes;
   CompilerDiagnosticReporter _reporter;
@@ -225,7 +225,7 @@
         this.userOutputProvider = outputProvider == null
             ? const NullCompilerOutput()
             : outputProvider {
-    world = new World(this);
+    _world = new WorldImpl(this);
     if (makeReporter != null) {
       _reporter = makeReporter(this, options);
     } else {
@@ -244,7 +244,7 @@
 
     // TODO(johnniwinther): Separate the dependency tracking from the enqueuing
     // for global dependencies.
-    globalDependencies = new GlobalDependencyRegistry(this);
+    globalDependencies = new GlobalDependencyRegistry();
 
     if (makeBackend != null) {
       backend = makeBackend(this);
@@ -302,6 +302,20 @@
     tasks.addAll(backend.tasks);
   }
 
+  /// The world currently being computed by resolution. This forms a basis for
+  /// the [inferenceWorld] and later the [closedWorld].
+  OpenWorld get openWorld => _world;
+
+  /// The closed world after resolution but currently refined by inference.
+  ClosedWorldRefiner get inferenceWorld => _world;
+
+  /// The closed world after resolution and inference.
+  ClosedWorld get closedWorld {
+    assert(invariant(CURRENT_ELEMENT_SPANNABLE, _world.isClosed,
+        message: "Closed world not computed yet."));
+    return _world;
+  }
+
   /// Creates the scanner task.
   ///
   /// Override this to mock the scanner for testing.
@@ -314,11 +328,13 @@
   /// Override this to mock the resolver for testing.
   ResolverTask createResolverTask() {
     return new ResolverTask(
-        resolution, backend.constantCompilerTask, world, measurer);
+        resolution, backend.constantCompilerTask, openWorld, measurer);
   }
 
-  Universe get resolverWorld => enqueuer.resolution.universe;
-  Universe get codegenWorld => enqueuer.codegen.universe;
+  // TODO(johnniwinther): Rename these appropriately when unification of worlds/
+  // universes is complete.
+  ResolutionUniverse get resolverWorld => enqueuer.resolution.universe;
+  CodegenUniverse get codegenWorld => enqueuer.codegen.universe;
 
   bool get analyzeAll => options.analyzeAll || compileAll;
 
@@ -709,7 +725,7 @@
         assert(mainFunction != null);
         phase = PHASE_DONE_RESOLVING;
 
-        world.populate();
+        openWorld.closeWorld();
         // Compute whole-program-knowledge that the backend needs. (This might
         // require the information computed in [world.populate].)
         backend.onResolutionComplete();
@@ -1982,7 +1998,7 @@
 
   @override
   void registerClass(ClassElement cls) {
-    compiler.world.registerClass(cls);
+    compiler.openWorld.registerClass(cls);
   }
 
   @override
@@ -2180,16 +2196,10 @@
   }
 }
 
-class GlobalDependencyRegistry extends EagerRegistry {
-  final Compiler compiler;
+class GlobalDependencyRegistry extends Registry {
   Setlet<Element> _otherDependencies;
 
-  GlobalDependencyRegistry(this.compiler) : super('GlobalDependencies', null);
-
-  // TODO(johnniwinther): Rename world/universe/enqueuer through out the
-  // compiler.
-  @override
-  Enqueuer get world => compiler.enqueuer.codegen;
+  GlobalDependencyRegistry();
 
   void registerDependency(Element element) {
     if (element == null) return;
@@ -2202,6 +2212,8 @@
   Iterable<Element> get otherDependencies {
     return _otherDependencies != null ? _otherDependencies : const <Element>[];
   }
+
+  String get name => 'GlobalDependencies';
 }
 
 class _ScriptLoader implements ScriptLoader {
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index 2afb849..de65277 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -265,12 +265,13 @@
     // TODO(sigmund): why all these checks?
     if (element.isInstanceMember &&
         !element.isAbstract &&
-        compiler.world.allFunctions.contains(element)) {
+        compiler.closedWorld.allFunctions.contains(element)) {
       returnType = '${element.type.returnType}';
     }
     String inferredReturnType =
         '${compiler.globalInference.results.returnTypeOf(element)}';
-    String sideEffects = '${compiler.world.getSideEffectsOfElement(element)}';
+    String sideEffects =
+        '${compiler.closedWorld.getSideEffectsOfElement(element)}';
 
     int inlinedCount = compiler.dumpInfoTask.inlineCount[element];
     if (inlinedCount == null) inlinedCount = 0;
@@ -438,7 +439,7 @@
         element,
         impact,
         new WorldImpactVisitorImpl(visitDynamicUse: (dynamicUse) {
-          selections.addAll(compiler.world.allFunctions
+          selections.addAll(compiler.closedWorld.allFunctions
               .filter(dynamicUse.selector, dynamicUse.mask)
               .map((e) => new Selection(e, dynamicUse.mask)));
         }, visitStaticUse: (staticUse) {
diff --git a/pkg/compiler/lib/src/elements/elements.dart b/pkg/compiler/lib/src/elements/elements.dart
index 814e1fb..29e2396 100644
--- a/pkg/compiler/lib/src/elements/elements.dart
+++ b/pkg/compiler/lib/src/elements/elements.dart
@@ -801,9 +801,9 @@
     ClassElement cls = constructor.enclosingClass;
     return cls.library == compiler.commonElements.typedDataLibrary &&
         compiler.backend.isNative(cls) &&
-        compiler.world
+        compiler.closedWorld
             .isSubtypeOf(cls, compiler.commonElements.typedDataClass) &&
-        compiler.world.isSubtypeOf(cls, compiler.coreClasses.listClass) &&
+        compiler.closedWorld.isSubtypeOf(cls, compiler.coreClasses.listClass) &&
         constructor.name == '';
   }
 
@@ -1378,6 +1378,9 @@
   /// is `C.c`.
   ConstructorElement get definingConstructor;
 
+  /// Returns `true` if this constructor is an implicit default constructor.
+  bool get isDefaultConstructor;
+
   /// The constant constructor defining the binding of fields if `const`,
   /// `null` otherwise.
   ConstantConstructor get constantConstructor;
diff --git a/pkg/compiler/lib/src/elements/modelx.dart b/pkg/compiler/lib/src/elements/modelx.dart
index 4eb76bb..691e6d7 100644
--- a/pkg/compiler/lib/src/elements/modelx.dart
+++ b/pkg/compiler/lib/src/elements/modelx.dart
@@ -224,6 +224,8 @@
 
   bool get isCyclicRedirection => false;
 
+  bool get isDefaultConstructor => false;
+
   bool get isMalformed => true;
 
   PrefixElement get redirectionDeferredPrefix => null;
@@ -2237,6 +2239,8 @@
   // generative constructors.
   bool get isCyclicRedirection => effectiveTarget.isRedirectingFactory;
 
+  bool get isDefaultConstructor => false;
+
   /// These fields are set by the post process queue when checking for cycles.
   ConstructorElement effectiveTargetInternal;
   DartType _effectiveTargetType;
diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart
index 24c8771..c29912a 100644
--- a/pkg/compiler/lib/src/enqueue.dart
+++ b/pkg/compiler/lib/src/enqueue.dart
@@ -131,7 +131,8 @@
       new Map<String, Set<Element>>();
   final Set<ClassElement> _processedClasses = new Set<ClassElement>();
   Set<ClassElement> recentClasses = new Setlet<ClassElement>();
-  final Universe universe = new Universe(const TypeMaskStrategy());
+  final ResolutionUniverseImpl _universe =
+      new ResolutionUniverseImpl(const TypeMaskStrategy());
 
   static final TRACE_MIRROR_ENQUEUING =
       const bool.fromEnvironment("TRACE_MIRROR_ENQUEUING");
@@ -155,6 +156,8 @@
   // TODO(johnniwinther): Move this to [ResolutionEnqueuer].
   Resolution get resolution => compiler.resolution;
 
+  ResolutionUniverse get universe => _universe;
+
   bool get queueIsEmpty => queue.isEmpty;
 
   QueueFilter get filter => compiler.enqueuerFilter;
@@ -191,7 +194,7 @@
       ClassElement cls = type.element;
       cls.ensureResolved(resolution);
       bool isNative = compiler.backend.isNative(cls);
-      universe.registerTypeInstantiation(type,
+      _universe.registerTypeInstantiation(type,
           isNative: isNative,
           byMirrors: mirrorUsage, onImplemented: (ClassElement cls) {
         compiler.backend
@@ -227,13 +230,13 @@
       // Note: this assumes that there are no non-native fields on native
       // classes, which may not be the case when a native class is subclassed.
       if (compiler.backend.isNative(cls)) {
-        compiler.world.registerUsedElement(member);
-        if (universe.hasInvokedGetter(member, compiler.world) ||
-            universe.hasInvocation(member, compiler.world)) {
+        compiler.openWorld.registerUsedElement(member);
+        if (_universe.hasInvokedGetter(member, compiler.openWorld) ||
+            _universe.hasInvocation(member, compiler.openWorld)) {
           addToWorkList(member);
           return;
         }
-        if (universe.hasInvokedSetter(member, compiler.world)) {
+        if (_universe.hasInvokedSetter(member, compiler.openWorld)) {
           addToWorkList(member);
           return;
         }
@@ -257,7 +260,7 @@
       }
       // If there is a property access with the same name as a method we
       // need to emit the method.
-      if (universe.hasInvokedGetter(function, compiler.world)) {
+      if (_universe.hasInvokedGetter(function, compiler.openWorld)) {
         registerClosurizedMember(function);
         addToWorkList(function);
         return;
@@ -267,27 +270,27 @@
       instanceFunctionsByName
           .putIfAbsent(memberName, () => new Set<Element>())
           .add(member);
-      if (universe.hasInvocation(function, compiler.world)) {
+      if (_universe.hasInvocation(function, compiler.openWorld)) {
         addToWorkList(function);
         return;
       }
     } else if (member.isGetter) {
       FunctionElement getter = member;
       getter.computeType(resolution);
-      if (universe.hasInvokedGetter(getter, compiler.world)) {
+      if (_universe.hasInvokedGetter(getter, compiler.openWorld)) {
         addToWorkList(getter);
         return;
       }
       // We don't know what selectors the returned closure accepts. If
       // the set contains any selector we have to assume that it matches.
-      if (universe.hasInvocation(getter, compiler.world)) {
+      if (_universe.hasInvocation(getter, compiler.openWorld)) {
         addToWorkList(getter);
         return;
       }
     } else if (member.isSetter) {
       FunctionElement setter = member;
       setter.computeType(resolution);
-      if (universe.hasInvokedSetter(setter, compiler.world)) {
+      if (_universe.hasInvokedSetter(setter, compiler.openWorld)) {
         addToWorkList(setter);
         return;
       }
@@ -334,7 +337,7 @@
 
   void registerDynamicUse(DynamicUse dynamicUse) {
     task.measure(() {
-      if (universe.registerDynamicUse(dynamicUse)) {
+      if (_universe.registerDynamicUse(dynamicUse)) {
         handleUnseenSelector(dynamicUse);
       }
     });
@@ -537,7 +540,7 @@
     Selector selector = dynamicUse.selector;
     String methodName = selector.name;
     processInstanceMembers(methodName, (Element member) {
-      if (dynamicUse.appliesUnnamed(member, compiler.world)) {
+      if (dynamicUse.appliesUnnamed(member, compiler.openWorld)) {
         if (member.isFunction && selector.isGetter) {
           registerClosurizedMember(member);
         }
@@ -548,7 +551,7 @@
     });
     if (selector.isGetter) {
       processInstanceFunctions(methodName, (Element member) {
-        if (dynamicUse.appliesUnnamed(member, compiler.world)) {
+        if (dynamicUse.appliesUnnamed(member, compiler.openWorld)) {
           registerClosurizedMember(member);
           return true;
         }
@@ -570,7 +573,7 @@
     Element element = staticUse.element;
     assert(invariant(element, element.isDeclaration,
         message: "Element ${element} is not the declaration."));
-    universe.registerStaticUse(staticUse);
+    _universe.registerStaticUse(staticUse);
     compiler.backend.registerStaticUse(element, this);
     bool addElement = true;
     switch (staticUse.kind) {
@@ -619,7 +622,7 @@
   }
 
   void _registerIsCheck(DartType type) {
-    type = universe.registerIsCheck(type, compiler);
+    type = _universe.registerIsCheck(type, compiler);
     // Even in checked mode, type annotations for return type and argument
     // types do not imply type checks, so there should never be a check
     // against the type variable of a typedef.
@@ -629,7 +632,7 @@
   void registerCallMethodWithFreeTypeVariables(Element element) {
     compiler.backend.registerCallMethodWithFreeTypeVariables(
         element, this, compiler.globalDependencies);
-    universe.callMethodsWithFreeTypeVariables.add(element);
+    _universe.callMethodsWithFreeTypeVariables.add(element);
   }
 
   void registerClosurizedMember(TypedElement element) {
@@ -637,9 +640,10 @@
     if (element.computeType(resolution).containsTypeVariables) {
       compiler.backend.registerClosureWithFreeTypeVariables(
           element, this, compiler.globalDependencies);
+      _universe.closuresWithFreeTypeVariables.add(element);
     }
     compiler.backend.registerBoundClosure(this);
-    universe.closurizedMembers.add(element);
+    _universe.closurizedMembers.add(element);
   }
 
   void forEach(void f(WorkItem work)) {
@@ -722,7 +726,7 @@
           element, "Resolution work list is closed. Trying to add $element.");
     }
 
-    compiler.world.registerUsedElement(element);
+    compiler.openWorld.registerUsedElement(element);
 
     ResolutionWorkItem workItem = compiler.resolution.createWorkItem(element);
     queue.add(workItem);
@@ -809,7 +813,7 @@
   }
 
   void forgetElement(Element element) {
-    universe.forgetElement(element, compiler);
+    _universe.forgetElement(element, compiler);
     _processedClasses.remove(element);
     instanceMembersByName[element.name]?.remove(element);
     instanceFunctionsByName[element.name]?.remove(element);
diff --git a/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart b/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
index 2e554e5..bff02bd 100644
--- a/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
+++ b/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
@@ -21,7 +21,7 @@
 import '../universe/call_structure.dart' show CallStructure;
 import '../universe/selector.dart' show Selector;
 import '../util/util.dart';
-import '../world.dart' show ClassWorld;
+import '../world.dart' show ClosedWorld;
 
 /**
  * The interface [InferrerVisitor] will use when working on types.
@@ -950,8 +950,8 @@
   T get thisType {
     if (_thisType != null) return _thisType;
     ClassElement cls = outermostElement.enclosingClass;
-    ClassWorld classWorld = compiler.world;
-    if (classWorld.isUsedAsMixin(cls)) {
+    ClosedWorld closedWorld = compiler.closedWorld;
+    if (closedWorld.isUsedAsMixin(cls)) {
       return _thisType = types.nonNullSubtype(cls);
     } else {
       return _thisType = types.nonNullSubclass(cls);
diff --git a/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart b/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
index 0a6c628..effe4fb 100644
--- a/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
@@ -22,7 +22,7 @@
 import '../universe/selector.dart' show Selector;
 import '../universe/side_effects.dart' show SideEffects;
 import '../util/util.dart' show Link, Setlet;
-import '../world.dart' show ClassWorld;
+import '../world.dart' show ClosedWorld;
 import 'inferrer_visitor.dart';
 
 /**
@@ -33,14 +33,14 @@
 abstract class InferrerEngine<T, V extends TypeSystem>
     implements MinimalInferrerEngine<T> {
   final Compiler compiler;
-  final ClassWorld classWorld;
+  final ClosedWorld closedWorld;
   final V types;
   final Map<ast.Node, T> concreteTypes = new Map<ast.Node, T>();
   final Set<Element> generativeConstructorsExposingThis = new Set<Element>();
 
   InferrerEngine(Compiler compiler, this.types)
       : this.compiler = compiler,
-        this.classWorld = compiler.world;
+        this.closedWorld = compiler.closedWorld;
 
   CoreClasses get coreClasses => compiler.coreClasses;
 
@@ -174,7 +174,7 @@
   void forEachElementMatching(
       Selector selector, TypeMask mask, bool f(Element element)) {
     Iterable<Element> elements =
-        compiler.world.allFunctions.filter(selector, mask);
+        compiler.closedWorld.allFunctions.filter(selector, mask);
     for (Element e in elements) {
       if (!f(e.implementation)) return;
     }
@@ -210,7 +210,8 @@
       sideEffects.setAllSideEffects();
       sideEffects.setDependsOnSomething();
     } else {
-      sideEffects.add(compiler.world.getSideEffectsOfElement(callee));
+      sideEffects
+          .add(compiler.inferenceWorld.getCurrentlyKnownSideEffects(callee));
     }
   }
 
@@ -480,9 +481,9 @@
         });
       }
       if (analyzedElement.isGenerativeConstructor && cls.isAbstract) {
-        if (compiler.world.isDirectlyInstantiated(cls)) {
+        if (compiler.closedWorld.isDirectlyInstantiated(cls)) {
           returnType = types.nonNullExact(cls);
-        } else if (compiler.world.isIndirectlyInstantiated(cls)) {
+        } else if (compiler.closedWorld.isIndirectlyInstantiated(cls)) {
           returnType = types.nonNullSubclass(cls);
         } else {
           // TODO(johnniwinther): Avoid analyzing [analyzedElement] in this
@@ -531,7 +532,7 @@
       }
     }
 
-    compiler.world.registerSideEffects(analyzedElement, sideEffects);
+    compiler.inferenceWorld.registerSideEffects(analyzedElement, sideEffects);
     assert(breaksFor.isEmpty);
     assert(continuesFor.isEmpty);
     return returnType;
@@ -645,7 +646,7 @@
   bool isInClassOrSubclass(Element element) {
     ClassElement cls = outermostElement.enclosingClass.declaration;
     ClassElement enclosing = element.enclosingClass.declaration;
-    return compiler.world.isSubclassOf(enclosing, cls);
+    return compiler.closedWorld.isSubclassOf(enclosing, cls);
   }
 
   void checkIfExposesThis(Selector selector, TypeMask mask) {
@@ -1070,7 +1071,7 @@
           (node.asSendSet() != null) &&
           (node.asSendSet().receiver != null) &&
           node.asSendSet().receiver.isThis()) {
-        Iterable<Element> targets = compiler.world.allFunctions.filter(
+        Iterable<Element> targets = compiler.closedWorld.allFunctions.filter(
             setterSelector, types.newTypedSelector(thisType, setterMask));
         // We just recognized a field initialization of the form:
         // `this.foo = 42`. If there is only one target, we can update
@@ -1297,7 +1298,7 @@
     } else if (element != null &&
         element.isField &&
         Elements.isStaticOrTopLevelField(element) &&
-        compiler.world.fieldNeverChanges(element)) {
+        compiler.closedWorld.fieldNeverChanges(element)) {
       FieldElement fieldElement = element;
       ConstantValue value =
           compiler.backend.constants.getConstantValue(fieldElement.constant);
@@ -1351,8 +1352,9 @@
     // In erroneous code the number of arguments in the selector might not
     // match the function element.
     // TODO(polux): return nonNullEmpty and check it doesn't break anything
-    if (!selector.applies(target, compiler.world) ||
-        (mask != null && !mask.canHit(target, selector, compiler.world))) {
+    if (!selector.applies(target, compiler.backend) ||
+        (mask != null &&
+            !mask.canHit(target, selector, compiler.closedWorld))) {
       return types.dynamicType;
     }
 
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
index 42c6913..67f2aa0 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
@@ -25,7 +25,7 @@
 import '../universe/selector.dart' show Selector;
 import '../universe/side_effects.dart' show SideEffects;
 import '../util/util.dart' show Setlet;
-import '../world.dart' show ClassWorld;
+import '../world.dart' show ClosedWorld;
 import 'closure_tracer.dart';
 import 'debug.dart' as debug;
 import 'inferrer_visitor.dart' show ArgumentsTypes, TypeSystem;
@@ -37,7 +37,7 @@
 
 class TypeInformationSystem extends TypeSystem<TypeInformation> {
   final Compiler compiler;
-  final ClassWorld classWorld;
+  final ClosedWorld closedWorld;
   final CommonMasks commonMasks;
 
   /// [ElementTypeInformation]s for elements.
@@ -74,7 +74,7 @@
 
   TypeInformationSystem(Compiler compiler, this.commonMasks)
       : this.compiler = compiler,
-        this.classWorld = compiler.world {
+        this.closedWorld = compiler.closedWorld {
     nonNullEmptyType = getConcreteTypeFor(const TypeMask.nonNullEmpty());
   }
 
@@ -242,7 +242,7 @@
       return dynamicType;
     }
     return getConcreteTypeFor(
-        firstType.type.union(secondType.type, classWorld));
+        firstType.type.union(secondType.type, closedWorld));
   }
 
   bool selectorNeedsUpdate(TypeInformation info, TypeMask mask) {
@@ -253,7 +253,7 @@
       TypeInformation receiver, bool isConditional) {
     if (receiver.type.isExact) return receiver;
     TypeMask otherType =
-        compiler.world.allFunctions.receiverType(selector, mask);
+        compiler.closedWorld.allFunctions.receiverType(selector, mask);
     // Conditional sends (a?.b) can still narrow the possible types of `a`,
     // however, we still need to consider that `a` may be null.
     if (isConditional) {
@@ -263,10 +263,10 @@
     }
     // If this is refining to nullable subtype of `Object` just return
     // the receiver. We know the narrowing is useless.
-    if (otherType.isNullable && otherType.containsAll(classWorld)) {
+    if (otherType.isNullable && otherType.containsAll(closedWorld)) {
       return receiver;
     }
-    assert(TypeMask.assertIsNormalized(otherType, classWorld));
+    assert(TypeMask.assertIsNormalized(otherType, closedWorld));
     TypeInformation newType = new NarrowTypeInformation(receiver, otherType);
     allocatedTypes.add(newType);
     return newType;
@@ -276,7 +276,10 @@
       {bool isNullable: true}) {
     if (annotation.treatAsDynamic) return type;
     if (annotation.isVoid) return nullType;
-    if (annotation.element == classWorld.objectClass && isNullable) return type;
+    if (annotation.element == closedWorld.coreClasses.objectClass &&
+        isNullable) {
+      return type;
+    }
     TypeMask otherType;
     if (annotation.isTypedef || annotation.isFunctionType) {
       otherType = functionType.type;
@@ -285,15 +288,15 @@
       return type;
     } else {
       assert(annotation.isInterfaceType);
-      otherType = annotation.element == classWorld.objectClass
+      otherType = annotation.element == closedWorld.coreClasses.objectClass
           ? dynamicType.type.nonNullable()
-          : new TypeMask.nonNullSubtype(annotation.element, classWorld);
+          : new TypeMask.nonNullSubtype(annotation.element, closedWorld);
     }
     if (isNullable) otherType = otherType.nullable();
     if (type.type.isExact) {
       return type;
     } else {
-      assert(TypeMask.assertIsNormalized(otherType, classWorld));
+      assert(TypeMask.assertIsNormalized(otherType, closedWorld));
       TypeInformation newType = new NarrowTypeInformation(type, otherType);
       allocatedTypes.add(newType);
       return newType;
@@ -339,17 +342,17 @@
 
   TypeInformation nonNullSubtype(ClassElement type) {
     return getConcreteTypeFor(
-        new TypeMask.nonNullSubtype(type.declaration, classWorld));
+        new TypeMask.nonNullSubtype(type.declaration, closedWorld));
   }
 
   TypeInformation nonNullSubclass(ClassElement type) {
     return getConcreteTypeFor(
-        new TypeMask.nonNullSubclass(type.declaration, classWorld));
+        new TypeMask.nonNullSubclass(type.declaration, closedWorld));
   }
 
   TypeInformation nonNullExact(ClassElement type) {
     return getConcreteTypeFor(
-        new TypeMask.nonNullExact(type.declaration, classWorld));
+        new TypeMask.nonNullExact(type.declaration, closedWorld));
   }
 
   TypeInformation nonNullEmpty() {
@@ -365,8 +368,8 @@
       [TypeInformation elementType, int length]) {
     ClassElement typedDataClass = compiler.commonElements.typedDataClass;
     bool isTypedArray = typedDataClass != null &&
-        classWorld.isInstantiated(typedDataClass) &&
-        type.type.satisfies(typedDataClass, classWorld);
+        closedWorld.isInstantiated(typedDataClass) &&
+        type.type.satisfies(typedDataClass, closedWorld);
     bool isConst = (type.type == commonMasks.constListType);
     bool isFixed =
         (type.type == commonMasks.fixedListType) || isConst || isTypedArray;
@@ -402,9 +405,9 @@
     TypeMask keyType, valueType;
     if (isFixed) {
       keyType = keyTypes.fold(nonNullEmptyType.type,
-          (type, info) => type.union(info.type, classWorld));
+          (type, info) => type.union(info.type, closedWorld));
       valueType = valueTypes.fold(nonNullEmptyType.type,
-          (type, info) => type.union(info.type, classWorld));
+          (type, info) => type.union(info.type, closedWorld));
     } else {
       keyType = valueType = dynamicType.type;
     }
@@ -507,15 +510,15 @@
       // work the result will be `dynamic`.
       // TODO(sigmund): change to `mask == dynamicType` so we can continue to
       // track the non-nullable bit.
-      if (mask.containsAll(classWorld)) return dynamicType;
+      if (mask.containsAll(closedWorld)) return dynamicType;
       list.add(mask);
     }
 
     TypeMask newType = null;
     for (TypeMask mask in list) {
-      newType = newType == null ? mask : newType.union(mask, classWorld);
+      newType = newType == null ? mask : newType.union(mask, closedWorld);
       // Likewise - stop early if we already reach dynamic.
-      if (newType.containsAll(classWorld)) return dynamicType;
+      if (newType.containsAll(closedWorld)) return dynamicType;
     }
 
     return newType ?? const TypeMask.nonNullEmpty();
@@ -701,7 +704,7 @@
         tracer.run();
         if (!tracer.continueAnalyzing) {
           elements.forEach((FunctionElement e) {
-            compiler.world.registerMightBePassedToApply(e);
+            compiler.inferenceWorld.registerMightBePassedToApply(e);
             if (debug.VERBOSE) print("traced closure $e as ${true} (bail)");
             e.functionSignature.forEachParameter((parameter) {
               types
@@ -721,12 +724,12 @@
             workQueue.add(info);
           });
           if (tracer.tracedType.mightBePassedToFunctionApply) {
-            compiler.world.registerMightBePassedToApply(e);
+            compiler.inferenceWorld.registerMightBePassedToApply(e);
           }
-          ;
           if (debug.VERBOSE) {
             print("traced closure $e as "
-                "${compiler.world.getMightBePassedToApply(e)}");
+                "${compiler.inferenceWorld
+                    .getCurrentlyKnownMightBePassedToApply(e)}");
           }
         });
       }
@@ -864,7 +867,7 @@
                   // the old type around to ensure that we get a complete view
                   // of the type graph and do not drop any flow edges.
                   TypeMask refinedType = computeTypeMask(compiler, value);
-                  assert(TypeMask.assertIsNormalized(refinedType, classWorld));
+                  assert(TypeMask.assertIsNormalized(refinedType, closedWorld));
                   type = new NarrowTypeInformation(type, refinedType);
                   types.allocatedTypes.add(type);
                 }
@@ -912,13 +915,14 @@
     allocatedCalls.forEach((info) {
       if (!info.inLoop) return;
       if (info is StaticCallSiteTypeInformation) {
-        compiler.world.addFunctionCalledInLoop(info.calledElement);
-      } else if (info.mask != null && !info.mask.containsAll(compiler.world)) {
+        compiler.inferenceWorld.addFunctionCalledInLoop(info.calledElement);
+      } else if (info.mask != null &&
+          !info.mask.containsAll(compiler.closedWorld)) {
         // For instance methods, we only register a selector called in a
         // loop if it is a typed selector, to avoid marking too many
         // methods as being called from within a loop. This cuts down
         // on the code bloat.
-        info.targets.forEach(compiler.world.addFunctionCalledInLoop);
+        info.targets.forEach(compiler.inferenceWorld.addFunctionCalledInLoop);
       }
     });
   }
@@ -1185,7 +1189,7 @@
           arguments, sideEffects, inLoop);
     }
 
-    compiler.world.allFunctions.filter(selector, mask).forEach((callee) {
+    compiler.closedWorld.allFunctions.filter(selector, mask).forEach((callee) {
       updateSideEffects(sideEffects, selector, callee);
     });
 
@@ -1413,11 +1417,11 @@
 
     TypeMask result = const TypeMask.nonNullEmpty();
     Iterable<Element> elements =
-        compiler.world.allFunctions.filter(selector, mask);
+        compiler.closedWorld.allFunctions.filter(selector, mask);
     for (Element element in elements) {
       TypeMask type =
           inferrer.typeOfElementWithSelector(element, selector).type;
-      result = result.union(type, compiler.world);
+      result = result.union(type, compiler.closedWorld);
     }
     return result;
   }
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
index feaed3e..98e12be 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
@@ -639,7 +639,8 @@
       giveUp(inferrer);
       return safeType(inferrer);
     }
-    if (inferrer.compiler.world.getMightBePassedToApply(declaration)) {
+    if (inferrer.compiler.inferenceWorld
+        .getCurrentlyKnownMightBePassedToApply(declaration)) {
       giveUp(inferrer);
       return safeType(inferrer);
     }
@@ -816,7 +817,8 @@
   void addToGraph(TypeGraphInferrerEngine inferrer) {
     assert(receiver != null);
     TypeMask typeMask = computeTypedSelector(inferrer);
-    targets = inferrer.compiler.world.allFunctions.filter(selector, typeMask);
+    targets =
+        inferrer.compiler.closedWorld.allFunctions.filter(selector, typeMask);
     receiver.addUser(this);
     if (arguments != null) {
       arguments.forEach((info) => info.addUser(this));
@@ -865,7 +867,7 @@
    */
   TypeInformation handleIntrisifiedSelector(
       Selector selector, TypeMask mask, TypeGraphInferrerEngine inferrer) {
-    ClassWorld classWorld = inferrer.classWorld;
+    ClassWorld classWorld = inferrer.closedWorld;
     if (!classWorld.backend.intImplementation.isResolved) return null;
     if (mask == null) return null;
     if (!mask.containsOnlyInt(classWorld)) {
@@ -968,16 +970,16 @@
 
     Compiler compiler = inferrer.compiler;
     TypeMask maskToUse =
-        compiler.world.extendMaskIfReachesAll(selector, typeMask);
+        compiler.closedWorld.extendMaskIfReachesAll(selector, typeMask);
     bool canReachAll = compiler.enabledInvokeOn && (maskToUse != typeMask);
 
     // If this call could potentially reach all methods that satisfy
     // the untyped selector (through noSuchMethod's `Invocation`
     // and a call to `delegate`), we iterate over all these methods to
     // update their parameter types.
-    targets = compiler.world.allFunctions.filter(selector, maskToUse);
+    targets = compiler.closedWorld.allFunctions.filter(selector, maskToUse);
     Iterable<Element> typedTargets = canReachAll
-        ? compiler.world.allFunctions.filter(selector, typeMask)
+        ? compiler.closedWorld.allFunctions.filter(selector, typeMask)
         : targets;
 
     // Update the call graph if the targets could have changed.
@@ -1073,7 +1075,8 @@
     if (!abandonInferencing) {
       inferrer.updateSelectorInTree(caller, call, selector, mask);
       Iterable<Element> oldTargets = targets;
-      targets = inferrer.compiler.world.allFunctions.filter(selector, mask);
+      targets =
+          inferrer.compiler.closedWorld.allFunctions.filter(selector, mask);
       for (Element element in targets) {
         if (!oldTargets.contains(element)) {
           MemberTypeInformation callee =
@@ -1274,10 +1277,10 @@
   TypeMask computeType(TypeGraphInferrerEngine inferrer) {
     TypeMask input = assignments.first.type;
     TypeMask intersection =
-        input.intersection(typeAnnotation, inferrer.classWorld);
+        input.intersection(typeAnnotation, inferrer.closedWorld);
     if (debug.ANOMALY_WARN) {
-      if (!input.containsMask(intersection, inferrer.classWorld) ||
-          !typeAnnotation.containsMask(intersection, inferrer.classWorld)) {
+      if (!input.containsMask(intersection, inferrer.closedWorld) ||
+          !typeAnnotation.containsMask(intersection, inferrer.closedWorld)) {
         print("ANOMALY WARNING: narrowed $input to $intersection via "
             "$typeAnnotation");
       }
@@ -1513,7 +1516,7 @@
       for (var key in typeInfoMap.keys) {
         TypeInformation value = typeInfoMap[key];
         if (!mask.typeMap.containsKey(key) &&
-            !value.type.containsAll(inferrer.classWorld) &&
+            !value.type.containsAll(inferrer.closedWorld) &&
             !value.type.isNullable) {
           return toTypeMask(inferrer);
         }
@@ -1734,9 +1737,10 @@
     otherType = compiler.commonMasks.nullType;
   } else {
     assert(annotation.isInterfaceType);
-    otherType = new TypeMask.nonNullSubtype(annotation.element, compiler.world);
+    otherType =
+        new TypeMask.nonNullSubtype(annotation.element, compiler.closedWorld);
   }
   if (isNullable) otherType = otherType.nullable();
   if (type == null) return otherType;
-  return type.intersection(otherType, compiler.world);
+  return type.intersection(otherType, compiler.closedWorld);
 }
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index f688ff7..acc0edc1 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -14,7 +14,7 @@
     show Backend, ImpactTransformer, ForeignResolver, NativeRegistry;
 import '../common/codegen.dart' show CodegenImpact, CodegenWorkItem;
 import '../common/names.dart' show Identifiers, Selectors, Uris;
-import '../common/registry.dart' show EagerRegistry, Registry;
+import '../common/registry.dart' show Registry;
 import '../common/resolution.dart' show Frontend, Resolution, ResolutionImpact;
 import '../common/tasks.dart' show CompilerTask;
 import '../compiler.dart' show Compiler;
@@ -54,9 +54,11 @@
         ImpactUseCase,
         TransformedWorldImpact,
         WorldImpact,
-        WorldImpactVisitor;
+        WorldImpactBuilder,
+        WorldImpactVisitor,
+        StagedWorldImpactBuilder;
 import '../util/util.dart';
-import '../world.dart' show ClassWorld;
+import '../world.dart' show ClosedWorld;
 import 'backend_helpers.dart';
 import 'backend_impact.dart';
 import 'backend_serialization.dart' show JavaScriptBackendSerialization;
@@ -345,8 +347,8 @@
   TypeMask _indexablePrimitiveTypeCache;
   TypeMask get indexablePrimitiveType {
     if (_indexablePrimitiveTypeCache == null) {
-      _indexablePrimitiveTypeCache =
-          new TypeMask.nonNullSubtype(helpers.jsIndexableClass, compiler.world);
+      _indexablePrimitiveTypeCache = new TypeMask.nonNullSubtype(
+          helpers.jsIndexableClass, compiler.closedWorld);
     }
     return _indexablePrimitiveTypeCache;
   }
@@ -354,8 +356,8 @@
   TypeMask _readableArrayTypeCache;
   TypeMask get readableArrayType {
     if (_readableArrayTypeCache == null) {
-      _readableArrayTypeCache =
-          new TypeMask.nonNullSubclass(helpers.jsArrayClass, compiler.world);
+      _readableArrayTypeCache = new TypeMask.nonNullSubclass(
+          helpers.jsArrayClass, compiler.closedWorld);
     }
     return _readableArrayTypeCache;
   }
@@ -364,7 +366,7 @@
   TypeMask get mutableArrayType {
     if (_mutableArrayTypeCache == null) {
       _mutableArrayTypeCache = new TypeMask.nonNullSubclass(
-          helpers.jsMutableArrayClass, compiler.world);
+          helpers.jsMutableArrayClass, compiler.closedWorld);
     }
     return _mutableArrayTypeCache;
   }
@@ -372,8 +374,8 @@
   TypeMask _fixedArrayTypeCache;
   TypeMask get fixedArrayType {
     if (_fixedArrayTypeCache == null) {
-      _fixedArrayTypeCache =
-          new TypeMask.nonNullExact(helpers.jsFixedArrayClass, compiler.world);
+      _fixedArrayTypeCache = new TypeMask.nonNullExact(
+          helpers.jsFixedArrayClass, compiler.closedWorld);
     }
     return _fixedArrayTypeCache;
   }
@@ -382,7 +384,7 @@
   TypeMask get extendableArrayType {
     if (_extendableArrayTypeCache == null) {
       _extendableArrayTypeCache = new TypeMask.nonNullExact(
-          helpers.jsExtendableArrayClass, compiler.world);
+          helpers.jsExtendableArrayClass, compiler.closedWorld);
     }
     return _extendableArrayTypeCache;
   }
@@ -391,7 +393,7 @@
   TypeMask get unmodifiableArrayType {
     if (_unmodifiableArrayTypeCache == null) {
       _unmodifiableArrayTypeCache = new TypeMask.nonNullExact(
-          helpers.jsUnmodifiableArrayClass, compiler.world);
+          helpers.jsUnmodifiableArrayClass, compiler.closedWorld);
     }
     return _fixedArrayTypeCache;
   }
@@ -579,6 +581,12 @@
 
   JavaScriptBackendSerialization serialization;
 
+  StagedWorldImpactBuilder constantImpactsForResolution =
+      new StagedWorldImpactBuilder();
+
+  StagedWorldImpactBuilder constantImpactsForCodegen =
+      new StagedWorldImpactBuilder();
+
   final NativeData nativeData = new NativeData();
 
   final BackendHelpers helpers;
@@ -917,8 +925,9 @@
     if (elements == null) return false;
     if (elements.isEmpty) return false;
     return elements.any((element) {
-      return selector.applies(element, compiler.world) &&
-          (mask == null || mask.canHit(element, selector, compiler.world));
+      return selector.applies(element, this) &&
+          (mask == null ||
+              mask.canHit(element, selector, compiler.closedWorld));
     });
   }
 
@@ -974,11 +983,11 @@
   }
 
   Set<ClassElement> nativeSubclassesOfMixin(ClassElement mixin) {
-    ClassWorld classWorld = compiler.world;
-    Iterable<MixinApplicationElement> uses = classWorld.mixinUsesOf(mixin);
+    ClosedWorld closedWorld = compiler.closedWorld;
+    Iterable<MixinApplicationElement> uses = closedWorld.mixinUsesOf(mixin);
     Set<ClassElement> result = null;
     for (MixinApplicationElement use in uses) {
-      classWorld.forEachStrictSubclassOf(use, (ClassElement subclass) {
+      closedWorld.forEachStrictSubclassOf(use, (ClassElement subclass) {
         if (isNativeOrExtendsNative(subclass)) {
           if (result == null) result = new Set<ClassElement>();
           result.add(subclass);
@@ -1068,17 +1077,20 @@
     }
   }
 
-  void registerCompileTimeConstant(ConstantValue constant, Registry registry) {
-    registerCompileTimeConstantInternal(constant, registry);
+  void computeImpactForCompileTimeConstant(ConstantValue constant,
+      WorldImpactBuilder impactBuilder, bool isForResolution) {
+    computeImpactForCompileTimeConstantInternal(
+        constant, impactBuilder, isForResolution);
 
-    if (!registry.isForResolution && lookupMapAnalysis.isLookupMap(constant)) {
+    if (!isForResolution && lookupMapAnalysis.isLookupMap(constant)) {
       // Note: internally, this registration will temporarily remove the
       // constant dependencies and add them later on-demand.
       lookupMapAnalysis.registerLookupMapReference(constant);
     }
 
     for (ConstantValue dependency in constant.getDependencies()) {
-      registerCompileTimeConstant(dependency, registry);
+      computeImpactForCompileTimeConstant(
+          dependency, impactBuilder, isForResolution);
     }
   }
 
@@ -1086,32 +1098,43 @@
     constants.addCompileTimeConstantForEmission(constant);
   }
 
-  void registerCompileTimeConstantInternal(
-      ConstantValue constant, Registry registry) {
+  void computeImpactForCompileTimeConstantInternal(ConstantValue constant,
+      WorldImpactBuilder impactBuilder, bool isForResolution) {
     DartType type = constant.getType(compiler.coreTypes);
-    registerInstantiatedConstantType(type, registry);
+    computeImpactForInstantiatedConstantType(type, impactBuilder);
 
     if (constant.isFunction) {
       FunctionConstantValue function = constant;
-      registry.registerStaticUse(new StaticUse.staticTearOff(function.element));
+      impactBuilder
+          .registerStaticUse(new StaticUse.staticTearOff(function.element));
     } else if (constant.isInterceptor) {
       // An interceptor constant references the class's prototype chain.
       InterceptorConstantValue interceptor = constant;
-      registerInstantiatedConstantType(interceptor.dispatchedType, registry);
+      computeImpactForInstantiatedConstantType(
+          interceptor.dispatchedType, impactBuilder);
     } else if (constant.isType) {
-      enqueueInResolution(helpers.createRuntimeType, registry);
-      registry.registerInstantiation(typeImplementation.rawType);
+      if (isForResolution) {
+        impactBuilder.registerStaticUse(new StaticUse.staticInvoke(
+            // TODO(johnniwinther): Find the right [CallStructure].
+            helpers.createRuntimeType,
+            null));
+        registerBackendUse(helpers.createRuntimeType);
+      }
+      impactBuilder.registerTypeUse(
+          new TypeUse.instantiation(typeImplementation.rawType));
     }
     lookupMapAnalysis.registerConstantKey(constant);
   }
 
-  void registerInstantiatedConstantType(DartType type, Registry registry) {
+  void computeImpactForInstantiatedConstantType(
+      DartType type, WorldImpactBuilder impactBuilder) {
     DartType instantiatedType =
         type.isFunctionType ? coreTypes.functionType : type;
     if (type is InterfaceType) {
-      registry.registerInstantiation(instantiatedType);
+      impactBuilder
+          .registerTypeUse(new TypeUse.instantiation(instantiatedType));
       if (classNeedsRtiField(type.element)) {
-        registry.registerStaticUse(new StaticUse.staticInvoke(
+        impactBuilder.registerStaticUse(new StaticUse.staticInvoke(
             // TODO(johnniwinther): Find the right [CallStructure].
             helpers.setRuntimeTypeInfo,
             null));
@@ -1120,7 +1143,7 @@
         // If we use a type literal in a constant, the compile time
         // constant emitter will generate a call to the createRuntimeType
         // helper so we register a use of that.
-        registry.registerStaticUse(new StaticUse.staticInvoke(
+        impactBuilder.registerStaticUse(new StaticUse.staticInvoke(
             // TODO(johnniwinther): Find the right [CallStructure].
             helpers.createRuntimeType,
             null));
@@ -1289,23 +1312,11 @@
   void registerInstantiatedType(
       InterfaceType type, Enqueuer enqueuer, Registry registry,
       {bool mirrorUsage: false}) {
-    lookupMapAnalysis.registerInstantiatedType(type, registry);
+    lookupMapAnalysis.registerInstantiatedType(type);
     super.registerInstantiatedType(type, enqueuer, registry,
         mirrorUsage: mirrorUsage);
   }
 
-  void registerUseInterceptor(Enqueuer enqueuer) {
-    assert(!enqueuer.isResolutionQueue);
-    if (!enqueuer.nativeEnqueuer.hasInstantiatedNativeClasses()) return;
-    Registry registry = compiler.globalDependencies;
-    enqueue(enqueuer, helpers.getNativeInterceptorMethod, registry);
-    enqueueClass(enqueuer, helpers.jsJavaScriptObjectClass, registry);
-    enqueueClass(enqueuer, helpers.jsPlainJavaScriptObjectClass, registry);
-    enqueueClass(enqueuer, helpers.jsJavaScriptFunctionClass, registry);
-    needToInitializeIsolateAffinityTag = true;
-    needToInitializeDispatchProperty = true;
-  }
-
   void enqueueHelpers(ResolutionEnqueuer world, Registry registry) {
     assert(helpers.interceptorsLibrary != null);
     // TODO(ngeoffray): Not enqueuing those two classes currently make
@@ -1361,7 +1372,6 @@
     if (enqueuer.isResolutionQueue || methodNeedsRti(closure)) {
       registerComputeSignature(enqueuer, registry);
     }
-    super.registerClosureWithFreeTypeVariables(closure, enqueuer, registry);
   }
 
   void registerBoundClosure(Enqueuer enqueuer) {
@@ -1605,7 +1615,8 @@
       if (constant != null) {
         ConstantValue initialValue = constants.getConstantValue(constant);
         if (initialValue != null) {
-          registerCompileTimeConstant(initialValue, work.registry);
+          computeImpactForCompileTimeConstant(
+              initialValue, work.registry.worldImpact, false);
           addCompileTimeConstantForEmission(initialValue);
           // We don't need to generate code for static or top-level
           // variables. For instance variables, we may need to generate
@@ -1883,7 +1894,7 @@
     if (!type.isRaw) return false;
     ClassElement classElement = type.element;
     if (isInterceptorClass(classElement)) return false;
-    return compiler.world.hasOnlySubclasses(classElement);
+    return compiler.closedWorld.hasOnlySubclasses(classElement);
   }
 
   bool isNullImplementation(ClassElement cls) {
@@ -2176,8 +2187,9 @@
           }
         });
         // 4) all overriding members of subclasses/subtypes (should be resolved)
-        if (compiler.world.hasAnyStrictSubtype(cls)) {
-          compiler.world.forEachStrictSubtypeOf(cls, (ClassElement subcls) {
+        if (compiler.closedWorld.hasAnyStrictSubtype(cls)) {
+          compiler.closedWorld.forEachStrictSubtypeOf(cls,
+              (ClassElement subcls) {
             subcls.forEachClassMember((Member member) {
               if (memberNames.contains(member.name)) {
                 // TODO(20993): find out why this assertion fails.
@@ -2256,8 +2268,8 @@
       reflectableMembers.add(helpers.boundClosureClass);
     }
     // Add typedefs.
-    reflectableMembers
-        .addAll(compiler.world.allTypedefs.where(referencedFromMirrorSystem));
+    reflectableMembers.addAll(
+        compiler.closedWorld.allTypedefs.where(referencedFromMirrorSystem));
     // Register all symbols of reflectable elements
     for (Element element in reflectableMembers) {
       symbolsUsed.add(element.name);
@@ -2300,25 +2312,26 @@
     // check for the interface [JavaScriptIndexingBehavior].
     ClassElement typedDataClass = compiler.commonElements.typedDataClass;
     return typedDataClass != null &&
-        compiler.world.isInstantiated(typedDataClass) &&
-        mask.satisfies(typedDataClass, compiler.world) &&
-        mask.satisfies(helpers.jsIndexingBehaviorInterface, compiler.world);
+        compiler.closedWorld.isInstantiated(typedDataClass) &&
+        mask.satisfies(typedDataClass, compiler.closedWorld) &&
+        mask.satisfies(
+            helpers.jsIndexingBehaviorInterface, compiler.closedWorld);
   }
 
   bool couldBeTypedArray(TypeMask mask) {
     bool intersects(TypeMask type1, TypeMask type2) =>
-        !type1.intersection(type2, compiler.world).isEmpty;
+        !type1.intersection(type2, compiler.closedWorld).isEmpty;
     // TODO(herhut): Maybe cache the TypeMask for typedDataClass and
     //               jsIndexingBehaviourInterface.
     ClassElement typedDataClass = compiler.commonElements.typedDataClass;
     return typedDataClass != null &&
-        compiler.world.isInstantiated(typedDataClass) &&
+        compiler.closedWorld.isInstantiated(typedDataClass) &&
         intersects(
-            mask, new TypeMask.subtype(typedDataClass, compiler.world)) &&
+            mask, new TypeMask.subtype(typedDataClass, compiler.closedWorld)) &&
         intersects(
             mask,
             new TypeMask.subtype(
-                helpers.jsIndexingBehaviorInterface, compiler.world));
+                helpers.jsIndexingBehaviorInterface, compiler.closedWorld));
   }
 
   /// Returns all static fields that are referenced through [targetsUsed].
@@ -2350,15 +2363,15 @@
 
   /// Called when [enqueuer] is empty, but before it is closed.
   bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassElement> recentClasses) {
-    if (!compiler.options.resolveOnly) {
-      // TODO(johnniwinther): The custom element analysis eagerly enqueues
-      // elements on the codegen queue. Change to compute the data needed
-      // instead.
+    // Add elements used synthetically, that is, through features rather than
+    // syntax, for instance custom elements.
+    //
+    // Return early if any elements are added to avoid counting the elements as
+    // due to mirrors.
+    customElementsAnalysis.onQueueEmpty(enqueuer);
+    lookupMapAnalysis.onQueueEmpty(enqueuer);
+    typeVariableHandler.onQueueEmpty(enqueuer);
 
-      // Add elements referenced only via custom elements.  Return early if any
-      // elements are added to avoid counting the elements as due to mirrors.
-      customElementsAnalysis.onQueueEmpty(enqueuer);
-    }
     if (!enqueuer.queueIsEmpty) return false;
 
     noSuchMethodRegistry.onQueueEmpty();
@@ -2402,6 +2415,9 @@
 
       compiler.libraryLoader.libraries.forEach(retainMetadataOf);
 
+      StagedWorldImpactBuilder impactBuilder = enqueuer.isResolutionQueue
+          ? constantImpactsForResolution
+          : constantImpactsForResolution;
       if (enqueuer.isResolutionQueue && !enqueuer.queueIsClosed) {
         /// Register the constant value of [metadata] as live in resolution.
         void registerMetadataConstant(MetadataAnnotation metadata) {
@@ -2410,8 +2426,8 @@
           Dependency dependency =
               new Dependency(constant, metadata.annotatedElement);
           metadataConstants.add(dependency);
-          registerCompileTimeConstant(dependency.constant,
-              new EagerRegistry('EagerRegistry for ${dependency}', enqueuer));
+          computeImpactForCompileTimeConstant(
+              dependency.constant, impactBuilder, enqueuer.isResolutionQueue);
         }
 
         // TODO(johnniwinther): We should have access to all recently processed
@@ -2420,11 +2436,12 @@
             registerMetadataConstant);
       } else {
         for (Dependency dependency in metadataConstants) {
-          registerCompileTimeConstant(dependency.constant,
-              new EagerRegistry('EagerRegistry for ${dependency}', enqueuer));
+          computeImpactForCompileTimeConstant(
+              dependency.constant, impactBuilder, enqueuer.isResolutionQueue);
         }
         metadataConstants.clear();
       }
+      enqueuer.applyImpact(null, impactBuilder.flush());
     }
     return true;
   }
@@ -2524,14 +2541,14 @@
           reporter.reportHintMessage(
               element, MessageKind.GENERIC, {'text': "Cannot throw"});
         }
-        compiler.world.registerCannotThrow(element);
+        compiler.inferenceWorld.registerCannotThrow(element);
       } else if (cls == helpers.noSideEffectsClass) {
         hasNoSideEffects = true;
         if (VERBOSE_OPTIMIZER_HINTS) {
           reporter.reportHintMessage(
               element, MessageKind.GENERIC, {'text': "Has no side effects"});
         }
-        compiler.world.registerSideEffectsFree(element);
+        compiler.inferenceWorld.registerSideEffectsFree(element);
       }
     }
     if (hasForceInline && hasNoInline) {
@@ -2821,6 +2838,7 @@
           registerBackendImpact(transformed, impacts.fallThroughError);
           break;
         case Feature.FIELD_WITHOUT_INITIALIZER:
+        case Feature.LOCAL_WITHOUT_INITIALIZER:
           transformed.registerTypeUse(
               new TypeUse.instantiation(backend.coreTypes.nullType));
           registerBackendImpact(transformed, impacts.nullLiteral);
@@ -2890,7 +2908,7 @@
         case TypeUseKind.TYPE_LITERAL:
           backend.customElementsAnalysis.registerTypeLiteral(type);
           if (type.isTypedef) {
-            backend.compiler.world.allTypedefs.add(type.element);
+            backend.compiler.openWorld.registerTypedef(type.element);
           }
           if (type.isTypeVariable && type is! MethodTypeVariableType) {
             // GENERIC_METHODS: The `is!` test above filters away method type
@@ -2996,6 +3014,10 @@
           // TODO(johnniwinther): Store the correct use in impacts.
           new StaticUse.foreignUse(staticUse));
     }
+    for (Selector selector in backendImpact.dynamicUses) {
+      assert(selector != null);
+      worldImpact.registerDynamicUse(new DynamicUse(selector, null));
+    }
     for (InterfaceType instantiatedType in backendImpact.instantiatedTypes) {
       backend.registerBackendUse(instantiatedType.element);
       worldImpact.registerTypeUse(new TypeUse.instantiation(instantiatedType));
@@ -3008,6 +3030,16 @@
     for (BackendImpact otherImpact in backendImpact.otherImpacts) {
       registerBackendImpact(worldImpact, otherImpact);
     }
+    for (BackendFeature feature in backendImpact.features) {
+      switch (feature) {
+        case BackendFeature.needToInitializeDispatchProperty:
+          backend.needToInitializeDispatchProperty = true;
+          break;
+        case BackendFeature.needToInitializeIsolateAffinityTag:
+          backend.needToInitializeIsolateAffinityTag = true;
+          break;
+      }
+    }
   }
 
   /// Register [type] as required for the runtime type information system.
@@ -3099,14 +3131,12 @@
   @override
   WorldImpact transformCodegenImpact(CodegenImpact impact) {
     TransformedWorldImpact transformed = new TransformedWorldImpact(impact);
-    EagerRegistry registry = impact.registry;
-    Enqueuer world = registry.world;
 
     for (TypeUse typeUse in impact.typeUses) {
       DartType type = typeUse.type;
       switch (typeUse.kind) {
         case TypeUseKind.INSTANTIATION:
-          backend.lookupMapAnalysis.registerInstantiatedType(type, registry);
+          backend.lookupMapAnalysis.registerInstantiatedType(type);
           break;
         case TypeUseKind.IS_CHECK:
           onIsCheckForCodegen(type, transformed);
@@ -3116,7 +3146,7 @@
     }
 
     for (ConstantValue constant in impact.compileTimeConstants) {
-      backend.registerCompileTimeConstant(constant, registry);
+      backend.computeImpactForCompileTimeConstant(constant, transformed, false);
       backend.addCompileTimeConstantForEmission(constant);
     }
 
@@ -3143,7 +3173,9 @@
     }
 
     if (impact.usesInterceptor) {
-      backend.registerUseInterceptor(world);
+      if (backend.codegenEnqueuer.nativeEnqueuer.hasInstantiatedNativeClasses) {
+        registerBackendImpact(transformed, impacts.interceptorUse);
+      }
     }
 
     for (ClassElement element in impact.typeConstants) {
@@ -3201,7 +3233,9 @@
         impact.apply(visitor);
       } else {
         impact.apply(visitor);
-        resolution.uncacheWorldImpact(element);
+        if (element != null) {
+          resolution.uncacheWorldImpact(element);
+        }
       }
     } else if (impactUse == DeferredLoadTask.IMPACT_USE) {
       impact.apply(visitor);
diff --git a/pkg/compiler/lib/src/js_backend/backend_impact.dart b/pkg/compiler/lib/src/js_backend/backend_impact.dart
index 7fb1e9c..e933ae5 100644
--- a/pkg/compiler/lib/src/js_backend/backend_impact.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_impact.dart
@@ -4,26 +4,43 @@
 
 library dart2js.js_helpers.impact;
 
+import '../common/names.dart';
 import '../compiler.dart' show Compiler;
 import '../core_types.dart' show CommonElements;
 import '../dart_types.dart' show InterfaceType;
 import '../elements/elements.dart' show ClassElement, Element;
+import '../universe/selector.dart';
+import '../util/enumset.dart';
 import 'backend_helpers.dart';
 import 'constant_system_javascript.dart';
 import 'js_backend.dart';
 
+/// Backend specific features required by a backend impact.
+enum BackendFeature {
+  needToInitializeIsolateAffinityTag,
+  needToInitializeDispatchProperty,
+}
+
 /// A set of JavaScript backend dependencies.
 class BackendImpact {
   final List<Element> staticUses;
+  final List<Selector> dynamicUses;
   final List<InterfaceType> instantiatedTypes;
   final List<ClassElement> instantiatedClasses;
   final List<BackendImpact> otherImpacts;
+  final EnumSet<BackendFeature> _features;
 
-  BackendImpact(
+  const BackendImpact(
       {this.staticUses: const <Element>[],
+      this.dynamicUses: const <Selector>[],
       this.instantiatedTypes: const <InterfaceType>[],
       this.instantiatedClasses: const <ClassElement>[],
-      this.otherImpacts: const <BackendImpact>[]});
+      this.otherImpacts: const <BackendImpact>[],
+      EnumSet<BackendFeature> features: const EnumSet<BackendFeature>.fixed(0)})
+      : this._features = features;
+
+  Iterable<BackendFeature> get features =>
+      _features.iterable(BackendFeature.values);
 }
 
 /// The JavaScript backend dependencies for various features.
@@ -359,6 +376,7 @@
   BackendImpact get stringInterpolation {
     if (_stringInterpolation == null) {
       _stringInterpolation = new BackendImpact(
+          dynamicUses: [Selectors.toString_],
           staticUses: [helpers.stringInterpolationHelper],
           otherImpacts: [_needsString('Strings are created.')]);
     }
@@ -593,4 +611,25 @@
     }
     return _closure;
   }
+
+  BackendImpact _interceptorUse;
+
+  BackendImpact get interceptorUse {
+    if (_interceptorUse == null) {
+      _interceptorUse = new BackendImpact(
+          staticUses: [
+            helpers.getNativeInterceptorMethod
+          ],
+          instantiatedClasses: [
+            helpers.jsJavaScriptObjectClass,
+            helpers.jsPlainJavaScriptObjectClass,
+            helpers.jsJavaScriptFunctionClass
+          ],
+          features: new EnumSet<BackendFeature>.fromValues([
+            BackendFeature.needToInitializeDispatchProperty,
+            BackendFeature.needToInitializeIsolateAffinityTag
+          ], fixed: true));
+    }
+    return _interceptorUse;
+  }
 }
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 2ab684e..0473fe6 100644
--- a/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
@@ -274,14 +274,5 @@
   void visitNode(Node node) {
     node.visitChildren(this);
     constants.nodeConstantMap.remove(node);
-
-    // TODO(ahe): This doesn't belong here. Rename this class and generalize.
-    var closureClassMap = constants
-        .compiler.closureToClassMapper.closureMappingCache
-        .remove(node);
-    if (closureClassMap != null) {
-      closureClassMap
-          .removeMyselfFrom(constants.compiler.enqueuer.codegen.universe);
-    }
   }
 }
diff --git a/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart b/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart
index 11ff3c9..807bcb9 100644
--- a/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart
@@ -8,6 +8,8 @@
 import '../elements/elements.dart';
 import '../enqueue.dart' show Enqueuer;
 import '../universe/use.dart' show StaticUse;
+import '../universe/world_impact.dart'
+    show WorldImpact, StagedWorldImpactBuilder;
 import 'backend.dart';
 
 /**
@@ -130,6 +132,8 @@
   final JavaScriptBackend backend;
   Compiler get compiler => backend.compiler;
 
+  final StagedWorldImpactBuilder impactBuilder = new StagedWorldImpactBuilder();
+
   // Classes that are candidates for needing constructors.  Classes are moved to
   // [activeClasses] when we know they need constructors.
   final instantiatedClasses = new Set<ClassElement>();
@@ -171,13 +175,14 @@
         // Force the generaton of the type constant that is the key to an entry
         // in the generated table.
         ConstantValue constant = makeTypeConstant(classElement);
-        backend.registerCompileTimeConstant(
-            constant, compiler.globalDependencies);
+        backend.computeImpactForCompileTimeConstant(
+            constant, impactBuilder, false);
         backend.addCompileTimeConstantForEmission(constant);
       }
     }
     activeClasses.addAll(newActiveClasses);
     instantiatedClasses.removeAll(newActiveClasses);
+    enqueuer.applyImpact(null, impactBuilder.flush());
   }
 
   TypeConstantValue makeTypeConstant(ClassElement element) {
diff --git a/pkg/compiler/lib/src/js_backend/enqueuer.dart b/pkg/compiler/lib/src/js_backend/enqueuer.dart
index 29bec96..8ceca0b 100644
--- a/pkg/compiler/lib/src/js_backend/enqueuer.dart
+++ b/pkg/compiler/lib/src/js_backend/enqueuer.dart
@@ -54,7 +54,8 @@
       new Map<String, Set<Element>>();
   final Set<ClassElement> _processedClasses = new Set<ClassElement>();
   Set<ClassElement> recentClasses = new Setlet<ClassElement>();
-  final Universe universe = new Universe(const TypeMaskStrategy());
+  final CodegenUniverseImpl _universe =
+      new CodegenUniverseImpl(const TypeMaskStrategy());
 
   static final TRACE_MIRROR_ENQUEUING =
       const bool.fromEnvironment("TRACE_MIRROR_ENQUEUING");
@@ -77,6 +78,8 @@
     impactVisitor = new _EnqueuerImpactVisitor(this);
   }
 
+  CodegenUniverse get universe => _universe;
+
   Backend get backend => _compiler.backend;
 
   CompilerOptions get options => _compiler.options;
@@ -85,7 +88,7 @@
 
   Registry get mirrorDependencies => _compiler.mirrorDependencies;
 
-  ClassWorld get _world => _compiler.world;
+  ClassWorld get _world => _compiler.closedWorld;
 
   bool get queueIsEmpty => queue.isEmpty;
 
@@ -141,7 +144,7 @@
     task.measure(() {
       ClassElement cls = type.element;
       bool isNative = backend.isNative(cls);
-      universe.registerTypeInstantiation(type,
+      _universe.registerTypeInstantiation(type,
           isNative: isNative,
           byMirrors: mirrorUsage, onImplemented: (ClassElement cls) {
         backend.registerImplementedClass(cls, this, globalDependencies);
@@ -176,13 +179,11 @@
       // Note: this assumes that there are no non-native fields on native
       // classes, which may not be the case when a native class is subclassed.
       if (backend.isNative(cls)) {
-        _compiler.world.registerUsedElement(member);
-        if (universe.hasInvokedGetter(member, _world) ||
-            universe.hasInvocation(member, _world)) {
+        if (_universe.hasInvokedGetter(member, _world) ||
+            _universe.hasInvocation(member, _world)) {
           addToWorkList(member);
           return;
-        }
-        if (universe.hasInvokedSetter(member, _world)) {
+        } else if (universe.hasInvokedSetter(member, _world)) {
           addToWorkList(member);
           return;
         }
@@ -205,7 +206,7 @@
       }
       // If there is a property access with the same name as a method we
       // need to emit the method.
-      if (universe.hasInvokedGetter(function, _world)) {
+      if (_universe.hasInvokedGetter(function, _world)) {
         registerClosurizedMember(function);
         addToWorkList(function);
         return;
@@ -215,25 +216,25 @@
       instanceFunctionsByName
           .putIfAbsent(memberName, () => new Set<Element>())
           .add(member);
-      if (universe.hasInvocation(function, _world)) {
+      if (_universe.hasInvocation(function, _world)) {
         addToWorkList(function);
         return;
       }
     } else if (member.isGetter) {
       FunctionElement getter = member;
-      if (universe.hasInvokedGetter(getter, _world)) {
+      if (_universe.hasInvokedGetter(getter, _world)) {
         addToWorkList(getter);
         return;
       }
       // We don't know what selectors the returned closure accepts. If
       // the set contains any selector we have to assume that it matches.
-      if (universe.hasInvocation(getter, _world)) {
+      if (_universe.hasInvocation(getter, _world)) {
         addToWorkList(getter);
         return;
       }
     } else if (member.isSetter) {
       FunctionElement setter = member;
-      if (universe.hasInvokedSetter(setter, _world)) {
+      if (_universe.hasInvokedSetter(setter, _world)) {
         addToWorkList(setter);
         return;
       }
@@ -282,7 +283,7 @@
 
   void registerDynamicUse(DynamicUse dynamicUse) {
     task.measure(() {
-      if (universe.registerDynamicUse(dynamicUse)) {
+      if (_universe.registerDynamicUse(dynamicUse)) {
         handleUnseenSelector(dynamicUse);
       }
     });
@@ -511,7 +512,7 @@
     Element element = staticUse.element;
     assert(invariant(element, element.isDeclaration,
         message: "Element ${element} is not the declaration."));
-    universe.registerStaticUse(staticUse);
+    _universe.registerStaticUse(staticUse);
     backend.registerStaticUse(element, this);
     bool addElement = true;
     switch (staticUse.kind) {
@@ -560,7 +561,7 @@
   }
 
   void _registerIsCheck(DartType type) {
-    type = universe.registerIsCheck(type, _compiler);
+    type = _universe.registerIsCheck(type, _compiler);
     // Even in checked mode, type annotations for return type and argument
     // types do not imply type checks, so there should never be a check
     // against the type variable of a typedef.
@@ -570,7 +571,6 @@
   void registerCallMethodWithFreeTypeVariables(Element element) {
     backend.registerCallMethodWithFreeTypeVariables(
         element, this, globalDependencies);
-    universe.callMethodsWithFreeTypeVariables.add(element);
   }
 
   void registerClosurizedMember(TypedElement element) {
@@ -580,7 +580,6 @@
           element, this, globalDependencies);
     }
     backend.registerBoundClosure(this);
-    universe.closurizedMembers.add(element);
   }
 
   void forEach(void f(WorkItem work)) {
@@ -613,7 +612,7 @@
   String toString() => 'Enqueuer($name)';
 
   void _forgetElement(Element element) {
-    universe.forgetElement(element, _compiler);
+    _universe.forgetElement(element, _compiler);
     _processedClasses.remove(element);
     instanceMembersByName[element.name]?.remove(element);
     instanceFunctionsByName[element.name]?.remove(element);
diff --git a/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart b/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
index 7ac77d5..b5e3c71 100644
--- a/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
+++ b/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
@@ -24,8 +24,8 @@
       names = new _FieldNamingScope.forBox(element.box, fieldRegistry);
     } else {
       ClassElement cls = element.enclosingClass;
-      names =
-          new _FieldNamingScope.forClass(cls, compiler.world, fieldRegistry);
+      names = new _FieldNamingScope.forClass(
+          cls, compiler.closedWorld, fieldRegistry);
     }
 
     if (names.containsField(element)) {
@@ -118,7 +118,7 @@
   }
 
   factory _FieldNamingScope.forClass(
-      ClassElement cls, ClassWorld world, _FieldNamingRegistry registry) {
+      ClassElement cls, ClosedWorld world, _FieldNamingRegistry registry) {
     _FieldNamingScope result = registry.scopes[cls];
     if (result != null) return result;
 
diff --git a/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart b/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
index 74b10ab..380d196 100644
--- a/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
@@ -116,7 +116,7 @@
 
       // Skip classes that are completely unreachable. This should only happen
       // when all of jsinterop types are unreachable from main.
-      if (!backend.compiler.world.isImplemented(classElement)) return;
+      if (!backend.compiler.resolverWorld.isImplemented(classElement)) return;
 
       if (!classElement.implementsInterface(helpers.jsJavaScriptObjectClass)) {
         backend.reporter.reportErrorMessage(classElement,
diff --git a/pkg/compiler/lib/src/js_backend/kernel_task.dart b/pkg/compiler/lib/src/js_backend/kernel_task.dart
index 0c59fa4..ea32143 100644
--- a/pkg/compiler/lib/src/js_backend/kernel_task.dart
+++ b/pkg/compiler/lib/src/js_backend/kernel_task.dart
@@ -4,6 +4,7 @@
 
 import '../compiler.dart';
 import '../kernel/kernel.dart';
+import 'package:kernel/ast.dart' as ir;
 
 import 'backend.dart';
 
@@ -18,10 +19,14 @@
       : this._compiler = backend.compiler,
         this.kernel = new Kernel(backend.compiler);
 
+  ir.Program program;
+
   /// Builds the kernel IR for the main function.
   ///
   /// May enqueue more elements to the resolution queue.
   void buildKernelIr() {
-    kernel.libraryDependencies(_compiler.options.entryPoint);
+    program =
+        new ir.Program(kernel.libraryDependencies(_compiler.options.entryPoint))
+          ..mainMethod = kernel.functionToIr(_compiler.mainFunction);
   }
 }
diff --git a/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart b/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart
index 2db7b35..2045c6c 100644
--- a/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart
@@ -22,6 +22,9 @@
 import '../dart_types.dart' show InterfaceType;
 import '../elements/elements.dart'
     show ClassElement, FieldElement, LibraryElement, VariableElement;
+import '../enqueue.dart';
+import '../universe/world_impact.dart'
+    show WorldImpact, StagedWorldImpactBuilder;
 import 'js_backend.dart' show JavaScriptBackend;
 
 /// An analysis and optimization to remove unused entries from a `LookupMap`.
@@ -118,11 +121,18 @@
   /// entry with that key.
   final _pending = <ConstantValue, List<_LookupMapInfo>>{};
 
+  final StagedWorldImpactBuilder impactBuilder = new StagedWorldImpactBuilder();
+
   /// Whether the backend is currently processing the codegen queue.
   bool _inCodegen = false;
 
   LookupMapAnalysis(this.backend, this.reporter);
 
+  void onQueueEmpty(Enqueuer enqueuer) {
+    if (enqueuer.isResolutionQueue) return;
+    enqueuer.applyImpact(null, impactBuilder.flush());
+  }
+
   /// Whether this analysis and optimization is enabled.
   bool get _isEnabled {
     // `lookupMap==off` kept here to make it easy to test disabling this feature
@@ -248,17 +258,17 @@
   }
 
   /// Callback from the enqueuer, invoked when [type] is instantiated.
-  void registerInstantiatedType(InterfaceType type, Registry registry) {
+  void registerInstantiatedType(InterfaceType type) {
     if (!_isEnabled || !_inCodegen) return;
     // TODO(sigmund): only add if .runtimeType is ever used
     _addClassUse(type.element);
     // TODO(sigmund): only do this when type-argument expressions are used?
-    _addGenerics(type, registry);
+    _addGenerics(type);
   }
 
   /// Records generic type arguments in [type], in case they are retrieved and
   /// returned using a type-argument expression.
-  void _addGenerics(InterfaceType type, Registry registry) {
+  void _addGenerics(InterfaceType type) {
     if (!type.isGeneric) return;
     for (var arg in type.typeArguments) {
       if (arg is InterfaceType) {
@@ -266,9 +276,9 @@
         // Note: this call was needed to generate correct code for
         // type_lookup_map/generic_type_test
         // TODO(sigmund): can we get rid of this?
-        backend.registerInstantiatedConstantType(
-            backend.typeImplementation.rawType, registry);
-        _addGenerics(arg, registry);
+        backend.computeImpactForInstantiatedConstantType(
+            backend.typeImplementation.rawType, impactBuilder);
+        _addGenerics(arg);
       }
     }
   }
@@ -407,8 +417,8 @@
     assert(!usedEntries.containsKey(key));
     ConstantValue constant = unusedEntries.remove(key);
     usedEntries[key] = constant;
-    analysis.backend.registerCompileTimeConstant(
-        constant, analysis.backend.compiler.globalDependencies);
+    analysis.backend.computeImpactForCompileTimeConstant(
+        constant, analysis.impactBuilder, false);
   }
 
   /// Restores [original] to contain all of the entries marked as possibly used.
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index 0d43e7b..8043861 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -24,7 +24,7 @@
 import '../universe/selector.dart' show Selector, SelectorKind;
 import '../util/characters.dart';
 import '../util/util.dart';
-import '../world.dart' show ClassWorld;
+import '../world.dart' show ClosedWorld;
 import 'backend.dart';
 import 'backend_helpers.dart';
 import 'constant_system_javascript.dart';
@@ -853,8 +853,8 @@
     // mangle the field names of classes extending native classes.
     // Methods on such classes are stored on the interceptor, not the instance,
     // so only fields have the potential to clash with a native property name.
-    ClassWorld classWorld = compiler.world;
-    if (classWorld.isUsedAsMixin(enclosingClass) ||
+    ClosedWorld closedWorld = compiler.closedWorld;
+    if (closedWorld.isUsedAsMixin(enclosingClass) ||
         _isShadowingSuperField(element) ||
         _isUserClassExtendingNative(enclosingClass)) {
       String proposeName() => '${enclosingClass.name}_${element.name}';
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index 21e3e76..f465f76 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -227,7 +227,7 @@
       classesNeedingRti.add(cls);
 
       // TODO(ngeoffray): This should use subclasses, not subtypes.
-      compiler.world.forEachStrictSubtypeOf(cls, (ClassElement sub) {
+      compiler.closedWorld.forEachStrictSubtypeOf(cls, (ClassElement sub) {
         potentiallyAddForRti(sub);
       });
 
@@ -364,7 +364,7 @@
         computeChecks(allInstantiatedArguments, checkedArguments);
   }
 
-  Set<DartType> computeInstantiatedTypesAndClosures(Universe universe) {
+  Set<DartType> computeInstantiatedTypesAndClosures(CodegenUniverse universe) {
     Set<DartType> instantiatedTypes =
         new Set<DartType>.from(universe.instantiatedTypes);
     for (DartType instantiatedType in universe.instantiatedTypes) {
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 ada9d16..d7c3281 100644
--- a/pkg/compiler/lib/src/js_backend/type_variable_handler.dart
+++ b/pkg/compiler/lib/src/js_backend/type_variable_handler.dart
@@ -15,6 +15,7 @@
     show CodeEmitterTask, MetadataCollector, Placeholder;
 import '../universe/call_structure.dart' show CallStructure;
 import '../universe/use.dart' show StaticUse;
+import '../universe/world_impact.dart';
 import '../util/util.dart';
 import 'backend.dart';
 
@@ -44,6 +45,10 @@
   Map<TypeVariableElement, jsAst.Expression> _typeVariableConstants =
       new Map<TypeVariableElement, jsAst.Expression>();
 
+  /// Impact builder used for the codegen world computation.
+  // TODO(johnniwinther): Add impact builder for resolution.
+  final StagedWorldImpactBuilder impactBuilder = new StagedWorldImpactBuilder();
+
   TypeVariableHandler(this._compiler);
 
   ClassElement get _typeVariableClass => _backend.helpers.typeVariableClass;
@@ -52,6 +57,12 @@
   JavaScriptBackend get _backend => _compiler.backend;
   DiagnosticReporter get reporter => _compiler.reporter;
 
+  void onQueueEmpty(Enqueuer enqueuer) {
+    if (enqueuer.isResolutionQueue) return;
+
+    enqueuer.applyImpact(null, impactBuilder.flush());
+  }
+
   void registerClassWithTypeVariables(
       ClassElement cls, Enqueuer enqueuer, Registry registry) {
     if (enqueuer.isResolutionQueue) {
@@ -108,9 +119,8 @@
 
       _backend.constants.evaluate(constant);
       ConstantValue value = _backend.constants.getConstantValue(constant);
-      _backend.registerCompileTimeConstant(value, _compiler.globalDependencies);
+      _backend.computeImpactForCompileTimeConstant(value, impactBuilder, false);
       _backend.addCompileTimeConstantForEmission(value);
-      _backend.constants.addCompileTimeConstantForEmission(value);
       constants
           .add(_reifyTypeVariableConstant(value, currentTypeVariable.element));
     }
diff --git a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
index d07c36f..1e0b6a3 100644
--- a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
@@ -92,8 +92,8 @@
     Set<Selector> generatedSelectors = new Set<Selector>();
     for (Selector selector in selectors.keys) {
       if (generatedSelectors.contains(selector)) continue;
-      if (!selector.appliesUnnamed(member, compiler.world)) continue;
-      if (selectors[selector].applies(member, selector, compiler.world)) {
+      if (!selector.appliesUnnamed(member, backend)) continue;
+      if (selectors[selector].applies(member, selector, compiler.closedWorld)) {
         generatedSelectors.add(selector);
 
         jsAst.Name invocationName = namer.invocationName(selector);
@@ -134,7 +134,7 @@
         String ignore, Map<Selector, SelectorConstraints> selectors) {
       for (Selector selector in selectors.keys) {
         SelectorConstraints maskSet = selectors[selector];
-        if (maskSet.needsNoSuchMethodHandling(selector, compiler.world)) {
+        if (maskSet.needsNoSuchMethodHandling(selector, compiler.closedWorld)) {
           jsAst.Name jsName = namer.invocationMirrorInternalName(selector);
           jsNames[jsName] = selector;
         }
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/nsm_emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/nsm_emitter.dart
index a21e42a..f0a6e0f 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/nsm_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/nsm_emitter.dart
@@ -55,7 +55,7 @@
             generator.generateStubForNoSuchMethod(jsName, selector);
         addProperty(method.name, method.code);
         if (reflectionName != null) {
-          bool accessible = compiler.world.allFunctions
+          bool accessible = compiler.closedWorld.allFunctions
               .filter(selector, null)
               .any((Element e) => backend.isAccessibleByReflection(e));
           addProperty(
diff --git a/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
index 1ccb101..265c946 100644
--- a/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
@@ -57,7 +57,7 @@
     bool hasString = false;
     bool hasNative = false;
     bool anyNativeClasses =
-        compiler.enqueuer.codegen.nativeEnqueuer.hasInstantiatedNativeClasses();
+        compiler.enqueuer.codegen.nativeEnqueuer.hasInstantiatedNativeClasses;
 
     for (ClassElement cls in classes) {
       if (cls == helpers.jsArrayClass ||
@@ -248,7 +248,7 @@
       bool containsJsIndexable =
           helpers.jsIndexingBehaviorInterface.isResolved &&
               classes.any((cls) {
-                return compiler.world
+                return compiler.closedWorld
                     .isSubtypeOf(cls, helpers.jsIndexingBehaviorInterface);
               });
       // The index set operator requires a check on its set value in
diff --git a/pkg/compiler/lib/src/js_emitter/native_emitter.dart b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
index 137f407..2e5f457 100644
--- a/pkg/compiler/lib/src/js_emitter/native_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
@@ -191,8 +191,7 @@
 
     // Add properties containing the information needed to construct maps used
     // by getNativeInterceptor and custom elements.
-    if (compiler.enqueuer.codegen.nativeEnqueuer
-        .hasInstantiatedNativeClasses()) {
+    if (compiler.enqueuer.codegen.nativeEnqueuer.hasInstantiatedNativeClasses) {
       fillNativeInfo(jsInterceptorClass);
       for (Class cls in classes) {
         if (!cls.isNative || neededClasses.contains(cls)) {
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 fa01ef9..621d781 100644
--- a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
@@ -248,7 +248,9 @@
           new Selector.call(member.memberName, selector.callStructure);
       renamedCallSelectors.add(renamedSelector);
 
-      if (!renamedSelector.appliesUnnamed(member, compiler.world)) continue;
+      if (!renamedSelector.appliesUnnamed(member, compiler.backend)) {
+        continue;
+      }
 
       if (untypedSelectors.add(renamedSelector)) {
         ParameterStubMethod stub =
@@ -264,8 +266,9 @@
     // call-selectors (and they are in the renamedCallSelectors set.
     for (Selector selector in selectors.keys) {
       if (renamedCallSelectors.contains(selector)) continue;
-      if (!selector.appliesUnnamed(member, compiler.world)) continue;
-      if (!selectors[selector].applies(member, selector, compiler.world)) {
+      if (!selector.appliesUnnamed(member, backend)) continue;
+      if (!selectors[selector]
+          .applies(member, selector, compiler.closedWorld)) {
         continue;
       }
 
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
index 8314f15..6e43f98 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
@@ -170,7 +170,7 @@
   void computeNeededDeclarations() {
     // Compute needed typedefs.
     typedefsNeededForReflection = Elements.sortedByPosition(compiler
-        .world.allTypedefs
+        .closedWorld.allTypedefs
         .where(backend.isAccessibleByReflection)
         .toList());
 
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart b/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart
index 935fa5f..1f6956d 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart
@@ -140,7 +140,7 @@
     if (fieldAccessNeverThrows(field)) return false;
     if (backend.shouldRetainGetter(field)) return true;
     return field.isClassMember &&
-        compiler.codegenWorld.hasInvokedGetter(field, compiler.world);
+        compiler.codegenWorld.hasInvokedGetter(field, compiler.closedWorld);
   }
 
   bool fieldNeedsSetter(VariableElement field) {
@@ -149,7 +149,7 @@
     if (field.isFinal || field.isConst) return false;
     if (backend.shouldRetainSetter(field)) return true;
     return field.isClassMember &&
-        compiler.codegenWorld.hasInvokedSetter(field, compiler.world);
+        compiler.codegenWorld.hasInvokedSetter(field, compiler.closedWorld);
   }
 
   static bool fieldAccessNeverThrows(VariableElement field) {
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
index a3dc79f..b977ffe 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
@@ -32,7 +32,7 @@
 import '../../js_backend/js_backend.dart'
     show Namer, JavaScriptBackend, JavaScriptConstantCompiler, StringBackedName;
 import '../../universe/selector.dart' show Selector;
-import '../../universe/universe.dart' show Universe, SelectorConstraints;
+import '../../universe/universe.dart' show CodegenUniverse, SelectorConstraints;
 import '../js_emitter.dart'
     show
         ClassStubGenerator,
@@ -79,7 +79,7 @@
 
   JavaScriptBackend get backend => _compiler.backend;
   BackendHelpers get helpers => backend.helpers;
-  Universe get universe => _compiler.codegenWorld;
+  CodegenUniverse get universe => _compiler.codegenWorld;
 
   /// Mapping from [ClassElement] to constructed [Class]. We need this to
   /// update the superclass in the [Class].
@@ -169,7 +169,7 @@
     List<Holder> holders = _registry.holders.toList(growable: false);
 
     bool needsNativeSupport = _compiler.enqueuer.codegen.nativeEnqueuer
-        .hasInstantiatedNativeClasses();
+        .hasInstantiatedNativeClasses;
 
     assert(!needsNativeSupport || nativeClasses.isNotEmpty);
 
@@ -675,7 +675,7 @@
 
   bool _methodCanBeApplied(FunctionElement method) {
     return _compiler.enabledFunctionApply &&
-        _compiler.world.getMightBePassedToApply(method);
+        _compiler.closedWorld.getMightBePassedToApply(method);
   }
 
   // TODO(herhut): Refactor incremental compilation and remove method.
@@ -735,8 +735,9 @@
         isClosureCallMethod = true;
       } else {
         // Careful with operators.
-        canTearOff = universe.hasInvokedGetter(element, _compiler.world) ||
-            (canBeReflected && !element.isOperator);
+        canTearOff =
+            universe.hasInvokedGetter(element, _compiler.closedWorld) ||
+                (canBeReflected && !element.isOperator);
         assert(canTearOff ||
             !universe.methodsNeedingSuperGetter.contains(element));
         tearOffName = namer.getterForElement(element);
diff --git a/pkg/compiler/lib/src/js_emitter/type_test_registry.dart b/pkg/compiler/lib/src/js_emitter/type_test_registry.dart
index 0a6e271..c1ff342 100644
--- a/pkg/compiler/lib/src/js_emitter/type_test_registry.dart
+++ b/pkg/compiler/lib/src/js_emitter/type_test_registry.dart
@@ -106,7 +106,7 @@
       } else if (function.isInstanceMember) {
         if (!function.enclosingClass.isClosure) {
           return compiler.codegenWorld
-              .hasInvokedGetter(function, compiler.world);
+              .hasInvokedGetter(function, compiler.closedWorld);
         }
       }
       return false;
diff --git a/pkg/compiler/lib/src/kernel/kernel.dart b/pkg/compiler/lib/src/kernel/kernel.dart
index fa53c0e..2fe3c70 100644
--- a/pkg/compiler/lib/src/kernel/kernel.dart
+++ b/pkg/compiler/lib/src/kernel/kernel.dart
@@ -24,6 +24,7 @@
         FunctionElement,
         ImportElement,
         LibraryElement,
+        LocalFunctionElement,
         MixinApplicationElement,
         TypeVariableElement;
 import '../elements/modelx.dart' show ErroneousFieldElementX;
@@ -50,6 +51,9 @@
   final Map<FunctionElement, ir.Member> functions =
       <FunctionElement, ir.Member>{};
 
+  final Map<LocalFunctionElement, ir.Node> localFunctions =
+      <LocalFunctionElement, ir.Node>{};
+
   final Map<FieldElement, ir.Field> fields = <FieldElement, ir.Field>{};
 
   final Map<TypeVariableElement, ir.TypeParameter> typeParameters =
@@ -206,7 +210,8 @@
           }
         });
         classNode.typeParameters.addAll(typeVariablesToIr(cls.typeVariables));
-        for (ir.InterfaceType interface in typesToIr(cls.interfaces.toList())) {
+        for (ir.InterfaceType interface
+            in typesToIr(cls.interfaces.reverse().toList())) {
           classNode.implementedTypes.add(interface);
         }
       });
@@ -378,6 +383,7 @@
           procedure.kind = irFunction.kind;
         }
         endFactoryScope(function);
+        member.transformerFlags = visitor.transformerFlags;
         assert(() {
           visitor.locals.forEach(checkMember);
           return true;
@@ -437,9 +443,7 @@
           isConst: field.isConst);
       addWork(field, () {
         setParent(fieldNode, field);
-        if (!field.isMalformed &&
-            !field.isInstanceMember &&
-            field.initializer != null) {
+        if (!field.isMalformed && field.initializer != null) {
           KernelVisitor visitor =
               new KernelVisitor(field, field.treeElements, this);
           fieldNode.initializer = visitor.buildInitializer()
diff --git a/pkg/compiler/lib/src/kernel/kernel_debug.dart b/pkg/compiler/lib/src/kernel/kernel_debug.dart
index 7258161..725e2d1 100644
--- a/pkg/compiler/lib/src/kernel/kernel_debug.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_debug.dart
@@ -36,6 +36,32 @@
     openAndCloseNode(node, '${node.runtimeType}', {'value': '${node.value}'});
   }
 
+  @override
+  void visitVariableGet(VariableGet node) {
+    openAndCloseNode(
+        node, '${node.runtimeType}', {'variable': '${node.variable}'});
+  }
+
+  @override
+  void visitVariableDeclaration(VariableDeclaration node) {
+    openNode(node, '${node.runtimeType}', {
+      'name': '${node.name}',
+      'isFinal': '${node.isFinal}',
+      'isConst': '${node.isConst}'
+    });
+    node.visitChildren(this);
+    closeNode();
+  }
+
+  @override
+  void visitInterfaceType(InterfaceType node) {
+    openNode(node, '${node.runtimeType}', {
+      'name': '${node.classNode.name}',
+    });
+    node.visitChildren(this);
+    closeNode();
+  }
+
   /// Pretty-prints given node tree into string.
   static String prettyPrint(Node node) {
     var p = new DebugPrinter();
diff --git a/pkg/compiler/lib/src/kernel/kernel_visitor.dart b/pkg/compiler/lib/src/kernel/kernel_visitor.dart
index 26f3b3a..37ab7d2 100644
--- a/pkg/compiler/lib/src/kernel/kernel_visitor.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_visitor.dart
@@ -19,7 +19,9 @@
         makeBinary,
         makeLet,
         makeOrReuseVariable;
+import 'package:kernel/transformations/flags.dart';
 
+import '../common.dart';
 import '../constants/expressions.dart'
     show
         BoolFromEnvironmentConstantExpression,
@@ -182,6 +184,7 @@
   TreeElements elements;
   AstElement currentElement;
   final Kernel kernel;
+  int transformerFlags = 0;
 
   final Map<JumpTarget, ir.LabeledStatement> continueTargets =
       <JumpTarget, ir.LabeledStatement>{};
@@ -774,8 +777,8 @@
     JumpTarget jumpTarget = elements.getTargetDefinition(node);
     ir.Statement body =
         buildContinueTarget(buildStatementInBlock(node.body), node, jumpTarget);
-    ir.ForStatement forStatement =
-        new ir.ForStatement(variables, condition, updates, body);
+    ir.ForStatement forStatement = associateNode(
+        new ir.ForStatement(variables, condition, updates, body), node);
     ir.Statement result = buildBreakTarget(forStatement, node, jumpTarget);
     if (initializer != null) {
       result = new ir.Block(
@@ -1090,7 +1093,9 @@
     ir.Statement body =
         buildContinueTarget(buildStatementInBlock(node.body), node, jumpTarget);
     return buildBreakTarget(
-        new ir.WhileStatement(condition, body), node, jumpTarget);
+        associateNode(new ir.WhileStatement(condition, body), node),
+        node,
+        jumpTarget);
   }
 
   @override
@@ -1142,8 +1147,13 @@
 
   ir.Expression buildConstructorInvoke(NewExpression node, {bool isConst}) {
     ConstructorElement constructor = elements[node.send];
-    ConstructorTarget target =
-        kernel.computeEffectiveTarget(constructor, elements.getType(node));
+    ConstructorTarget target;
+    if (isConst) {
+      target =
+          kernel.computeEffectiveTarget(constructor, elements.getType(node));
+    } else {
+      target = new ConstructorTarget(constructor, elements.getType(node));
+    }
     NodeList arguments = node.send.argumentsNode;
     if (kernel.isSyntheticError(target.element)) {
       return new ir.MethodInvocation(new ir.InvalidExpression(),
@@ -1203,7 +1213,10 @@
   ir.FunctionExpression visitClosureDeclaration(FunctionExpression node,
       LocalFunctionElement closure, NodeList parameters, Node body, _) {
     return withCurrentElement(closure, () {
-      return new ir.FunctionExpression(buildFunctionNode(closure, body));
+      ir.FunctionExpression function =
+          new ir.FunctionExpression(buildFunctionNode(closure, body));
+      kernel.localFunctions[closure] = function;
+      return function;
     });
   }
 
@@ -1383,22 +1396,6 @@
         .buildAssignment(visitForValue(rhs), voidContext: isVoidContext);
   }
 
-  void addFieldsWithInitializers(
-      ConstructorElement constructor, List<ir.Initializer> initializers) {
-    constructor.enclosingClass.forEachInstanceField((_, FieldElement element) {
-      // Convert the element into the corresponding IR field before asking
-      // if the initializer exists. This is necessary to ensure that the
-      // element has been analyzed before looking at its initializer.
-      ir.Field field = kernel.fieldToIr(element);
-      if (element.initializer != null) {
-        KernelVisitor visitor =
-            new KernelVisitor(element, element.treeElements, kernel);
-        ir.Expression value = visitor.buildInitializer();
-        initializers.add(new ir.FieldInitializer(field, value));
-      }
-    });
-  }
-
   IrFunction buildGenerativeConstructor(
       ConstructorElement constructor, NodeList parameters, Node body) {
     List<ir.Initializer> constructorInitializers = <ir.Initializer>[];
@@ -1424,13 +1421,11 @@
       if (kernel.isSyntheticError(constructor.definingConstructor)) {
         constructorInitializers.add(new ir.InvalidInitializer());
       } else {
-        addFieldsWithInitializers(constructor, constructorInitializers);
         constructorInitializers.add(new ir.SuperInitializer(
             kernel.functionToIr(constructor.definingConstructor),
             new ir.Arguments(arguments, named: named, types: null)));
       }
     } else {
-      addFieldsWithInitializers(constructor, constructorInitializers);
       if (parameters != null) {
         // TODO(ahe): the following is a (modified) copy of
         // [SemanticDeclarationResolvedMixin.visitParameters].
@@ -1689,8 +1684,12 @@
       LocalFunctionElement localFunction, NodeList parameters, Node body, _) {
     return withCurrentElement(localFunction, () {
       ir.VariableDeclaration local = getLocal(localFunction)..isFinal = true;
-      return new ir.FunctionDeclaration(
+      ir.FunctionDeclaration function = new ir.FunctionDeclaration(
           local, buildFunctionNode(localFunction, body));
+      // Closures can escape their context and we must therefore store them
+      // globally to include them in the world computation.
+      kernel.localFunctions[localFunction] = function;
+      return function;
     });
   }
 
@@ -1955,11 +1954,13 @@
 
   ir.VariableDeclaration getLocal(LocalElement local) {
     return locals.putIfAbsent(local, () {
+      // Currently, initializing formals are not final.
+      bool isFinal = local.isFinal && !local.isInitializingFormal;
       return associateElement(
           new ir.VariableDeclaration(local.name,
               initializer: null,
               type: typeToIrHack(local.type),
-              isFinal: local.isFinal,
+              isFinal: isFinal,
               isConst: local.isConst),
           local);
     });
@@ -1993,7 +1994,11 @@
           initializer.parent = variable;
         }
       });
-      returnType = typeToIrHack(signature.type.returnType);
+      if (function.isGenerativeConstructor) {
+        returnType = const ir.VoidType();
+      } else {
+        returnType = typeToIrHack(signature.type.returnType);
+      }
       if (function.isFactoryConstructor) {
         InterfaceType type = function.enclosingClass.thisType;
         if (type.isGeneric) {
@@ -2029,8 +2034,20 @@
           break;
       }
     }
-    ir.Statement body =
-        (bodyNode == null) ? null : buildStatementInBlock(bodyNode);
+    ir.Statement body;
+    if (function.isExternal) {
+      // [body] must be `null`.
+    } else if (function.isConstructor) {
+      // TODO(johnniwinther): Clean this up pending kernel issue #28.
+      ConstructorElement constructor = function;
+      if (constructor.isDefaultConstructor) {
+        body = new ir.EmptyStatement();
+      } else if (bodyNode != null && bodyNode.asEmptyStatement() == null) {
+        body = buildStatementInBlock(bodyNode);
+      }
+    } else if (bodyNode != null) {
+      body = buildStatementInBlock(bodyNode);
+    }
     return associateElement(
         new ir.FunctionNode(body,
             asyncMarker: asyncMarker,
@@ -2179,6 +2196,7 @@
   @override
   ir.SuperMethodInvocation visitSuperBinary(Send node, FunctionElement function,
       BinaryOperator operator, Node argument, _) {
+    transformerFlags |= TransformerFlag.superCalls;
     return new ir.SuperMethodInvocation(
         kernel.irName(operator.selectorName, currentElement),
         new ir.Arguments(<ir.Expression>[visitForValue(argument)]),
@@ -2219,6 +2237,7 @@
 
   ir.SuperMethodInvocation buildSuperEquals(
       FunctionElement function, Node argument) {
+    transformerFlags |= TransformerFlag.superCalls;
     return new ir.SuperMethodInvocation(
         kernel.irName(function.name, function),
         new ir.Arguments(<ir.Expression>[visitForValue(argument)],
@@ -2298,6 +2317,7 @@
   }
 
   Accessor buildSuperPropertyAccessor(Element getter, [Element setter]) {
+    transformerFlags |= TransformerFlag.superCalls;
     if (setter == null &&
         getter.isField &&
         !getter.isFinal &&
@@ -2398,6 +2418,7 @@
 
   ir.SuperMethodInvocation buildSuperMethodInvoke(
       MethodElement method, NodeList arguments) {
+    transformerFlags |= TransformerFlag.superCalls;
     return new ir.SuperMethodInvocation(kernel.irName(method.name, method),
         buildArguments(arguments), kernel.functionToIr(method));
   }
@@ -2457,6 +2478,7 @@
   @override
   ir.SuperMethodInvocation visitSuperUnary(
       Send node, UnaryOperator operator, FunctionElement function, _) {
+    transformerFlags |= TransformerFlag.superCalls;
     return new ir.SuperMethodInvocation(kernel.irName(function.name, function),
         new ir.Arguments.empty(), kernel.functionToIr(function));
   }
diff --git a/pkg/compiler/lib/src/native/enqueue.dart b/pkg/compiler/lib/src/native/enqueue.dart
index 166e6cf..1ab06fe 100644
--- a/pkg/compiler/lib/src/native/enqueue.dart
+++ b/pkg/compiler/lib/src/native/enqueue.dart
@@ -47,7 +47,7 @@
   void handleMethodAnnotations(Element method) {}
 
   /// Returns whether native classes are being used.
-  bool hasInstantiatedNativeClasses() => false;
+  bool get hasInstantiatedNativeClasses => false;
 
   /// Emits a summary information using the [log] function.
   void logSummary(log(message)) {}
@@ -73,7 +73,7 @@
 
   final Set<LibraryElement> processedLibraries;
 
-  bool hasInstantiatedNativeClasses() => !registeredClasses.isEmpty;
+  bool get hasInstantiatedNativeClasses => !registeredClasses.isEmpty;
 
   final Set<ClassElement> nativeClassesAndSubclasses = new Set<ClassElement>();
 
diff --git a/pkg/compiler/lib/src/resolution/members.dart b/pkg/compiler/lib/src/resolution/members.dart
index 39bd77d..390b161 100644
--- a/pkg/compiler/lib/src/resolution/members.dart
+++ b/pkg/compiler/lib/src/resolution/members.dart
@@ -4157,9 +4157,7 @@
   ResolutionResult visitStringInterpolation(StringInterpolation node) {
     // TODO(johnniwinther): This should be a consequence of the registration
     // of [registerStringInterpolation].
-    registry.registerTypeUse(new TypeUse.instantiation(coreTypes.stringType));
     registry.registerFeature(Feature.STRING_INTERPOLATION);
-    registerImplicitInvocation(Selectors.toString_);
 
     bool isValidAsConstant = true;
     List<ConstantExpression> parts = <ConstantExpression>[];
@@ -4244,10 +4242,6 @@
     return const NoneResult();
   }
 
-  registerImplicitInvocation(Selector selector) {
-    registry.registerDynamicUse(new DynamicUse(selector, null));
-  }
-
   ResolutionResult visitAsyncForIn(AsyncForIn node) {
     if (!resolution.target.supportsAsyncAwait) {
       reporter.reportErrorMessage(
diff --git a/pkg/compiler/lib/src/resolution/registry.dart b/pkg/compiler/lib/src/resolution/registry.dart
index d6aa72c..da2c129 100644
--- a/pkg/compiler/lib/src/resolution/registry.dart
+++ b/pkg/compiler/lib/src/resolution/registry.dart
@@ -18,16 +18,15 @@
 import '../universe/feature.dart';
 import '../universe/selector.dart' show Selector;
 import '../universe/use.dart' show DynamicUse, StaticUse, TypeUse;
-import '../universe/world_impact.dart' show WorldImpact, WorldImpactBuilder;
+import '../universe/world_impact.dart' show WorldImpact, WorldImpactBuilderImpl;
 import '../util/enumset.dart' show EnumSet;
 import '../util/util.dart' show Setlet;
 import 'members.dart' show ResolverVisitor;
 import 'send_structure.dart';
 import 'tree_elements.dart' show TreeElementMapping;
 
-class ResolutionWorldImpactBuilder extends ResolutionImpact
-    with WorldImpactBuilder
-    implements NativeRegistry {
+class ResolutionWorldImpactBuilder extends WorldImpactBuilderImpl
+    implements NativeRegistry, ResolutionImpact {
   final String name;
   EnumSet<Feature> _features;
   Setlet<MapLiteralUse> _mapLiterals;
diff --git a/pkg/compiler/lib/src/resolution/resolution.dart b/pkg/compiler/lib/src/resolution/resolution.dart
index 37c0933..13f248c 100644
--- a/pkg/compiler/lib/src/resolution/resolution.dart
+++ b/pkg/compiler/lib/src/resolution/resolution.dart
@@ -64,7 +64,7 @@
 class ResolverTask extends CompilerTask {
   final ConstantCompiler constantCompiler;
   final Resolution resolution;
-  final World world;
+  final OpenWorld world;
 
   ResolverTask(
       this.resolution, this.constantCompiler, this.world, Measurer measurer)
@@ -1017,7 +1017,7 @@
 
   WorldImpact resolveTypedef(TypedefElementX element) {
     if (element.isResolved) return const ResolutionImpact();
-    world.allTypedefs.add(element);
+    world.registerTypedef(element);
     return _resolveTypeDeclaration(element, () {
       ResolutionRegistry registry = new ResolutionRegistry(
           resolution.target, _ensureTreeElements(element));
diff --git a/pkg/compiler/lib/src/resolution/variables.dart b/pkg/compiler/lib/src/resolution/variables.dart
index 77a8f4e..fa7dd75 100644
--- a/pkg/compiler/lib/src/resolution/variables.dart
+++ b/pkg/compiler/lib/src/resolution/variables.dart
@@ -9,6 +9,7 @@
 import '../elements/modelx.dart' show LocalVariableElementX, VariableList;
 import '../tree/tree.dart';
 import '../universe/use.dart' show TypeUse;
+import '../universe/feature.dart';
 import '../util/util.dart' show Link;
 import 'members.dart' show ResolverVisitor;
 import 'registry.dart' show ResolutionRegistry;
@@ -42,9 +43,7 @@
 
   Identifier visitIdentifier(Identifier node) {
     // The variable is initialized to null.
-    // TODO(johnniwinther): Register a feature instead.
-    registry.registerTypeUse(
-        new TypeUse.instantiation(resolution.coreTypes.nullType));
+    registry.registerFeature(Feature.LOCAL_WITHOUT_INITIALIZER);
     if (definitions.modifiers.isConst) {
       if (resolver.inLoopVariable) {
         reporter.reportErrorMessage(node, MessageKind.CONST_LOOP_VARIABLE);
diff --git a/pkg/compiler/lib/src/serialization/equivalence.dart b/pkg/compiler/lib/src/serialization/equivalence.dart
index 4456623..9db38fd 100644
--- a/pkg/compiler/lib/src/serialization/equivalence.dart
+++ b/pkg/compiler/lib/src/serialization/equivalence.dart
@@ -516,14 +516,18 @@
   bool visitLocalFunctionElement(
       LocalFunctionElement element1, LocalFunctionElement element2) {
     // TODO(johnniwinther): Define an equivalence on locals.
-    return checkMembers(element1.memberContext, element2.memberContext);
+    return strategy.test(
+            element1, element2, 'name', element1.name, element2.name) &&
+        checkMembers(element1.memberContext, element2.memberContext);
   }
 
   @override
   bool visitLocalVariableElement(
       LocalVariableElement element1, LocalVariableElement element2) {
     // TODO(johnniwinther): Define an equivalence on locals.
-    return checkMembers(element1.memberContext, element2.memberContext);
+    return strategy.test(
+            element1, element2, 'name', element1.name, element2.name) &&
+        checkMembers(element1.memberContext, element2.memberContext);
   }
 
   bool visitAbstractFieldElement(
diff --git a/pkg/compiler/lib/src/serialization/modelz.dart b/pkg/compiler/lib/src/serialization/modelz.dart
index a6ba195..a628cbf 100644
--- a/pkg/compiler/lib/src/serialization/modelz.dart
+++ b/pkg/compiler/lib/src/serialization/modelz.dart
@@ -1242,6 +1242,9 @@
   @override
   bool get isExternal => _decoder.getBool(Key.IS_EXTERNAL);
 
+  @override
+  bool get isDefaultConstructor => false;
+
   ConstantConstructor get constantConstructor {
     if (isConst && _constantConstructor == null) {
       ObjectDecoder data =
@@ -1320,6 +1323,9 @@
   bool get isSynthesized => true;
 
   @override
+  bool get isDefaultConstructor => true;
+
+  @override
   ConstructorElement get definingConstructor {
     return enclosingClass.superclass.lookupConstructor('');
   }
@@ -1440,6 +1446,9 @@
   bool get isClassMember => true;
 
   @override
+  bool get isDefaultConstructor => false;
+
+  @override
   ConstantConstructor get constantConstructor => null;
 
   @override
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index 2456e81..5cca521 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -37,10 +37,12 @@
 import '../universe/side_effects.dart' show SideEffects;
 import '../universe/use.dart' show DynamicUse, StaticUse, TypeUse;
 import '../util/util.dart';
-import '../world.dart' show ClassWorld;
+import '../world.dart' show ClosedWorld;
 
 import 'graph_builder.dart';
+import 'jump_handler.dart';
 import 'locals_handler.dart';
+import 'loop_handler.dart';
 import 'nodes.dart';
 import 'optimize.dart';
 import 'ssa_branch_builder.dart';
@@ -125,226 +127,6 @@
   }
 }
 
-// Represents a single break/continue instruction.
-class JumpHandlerEntry {
-  final HJump jumpInstruction;
-  final LocalsHandler locals;
-  bool isBreak() => jumpInstruction is HBreak;
-  bool isContinue() => jumpInstruction is HContinue;
-  JumpHandlerEntry(this.jumpInstruction, this.locals);
-}
-
-abstract class JumpHandler {
-  factory JumpHandler(SsaBuilder builder, JumpTarget target) {
-    return new TargetJumpHandler(builder, target);
-  }
-  void generateBreak([LabelDefinition label]);
-  void generateContinue([LabelDefinition label]);
-  void forEachBreak(void action(HBreak instruction, LocalsHandler locals));
-  void forEachContinue(
-      void action(HContinue instruction, LocalsHandler locals));
-  bool hasAnyContinue();
-  bool hasAnyBreak();
-  void close();
-  final JumpTarget target;
-  List<LabelDefinition> labels();
-}
-
-// Insert break handler used to avoid null checks when a target isn't
-// used as the target of a break, and therefore doesn't need a break
-// handler associated with it.
-class NullJumpHandler implements JumpHandler {
-  final DiagnosticReporter reporter;
-
-  NullJumpHandler(this.reporter);
-
-  void generateBreak([LabelDefinition label]) {
-    reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
-        'NullJumpHandler.generateBreak should not be called.');
-  }
-
-  void generateContinue([LabelDefinition label]) {
-    reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
-        'NullJumpHandler.generateContinue should not be called.');
-  }
-
-  void forEachBreak(Function ignored) {}
-  void forEachContinue(Function ignored) {}
-  void close() {}
-  bool hasAnyContinue() => false;
-  bool hasAnyBreak() => false;
-
-  List<LabelDefinition> labels() => const <LabelDefinition>[];
-  JumpTarget get target => null;
-}
-
-// Records breaks until a target block is available.
-// Breaks are always forward jumps.
-// Continues in loops are implemented as breaks of the body.
-// Continues in switches is currently not handled.
-class TargetJumpHandler implements JumpHandler {
-  final SsaBuilder builder;
-  final JumpTarget target;
-  final List<JumpHandlerEntry> jumps;
-
-  TargetJumpHandler(SsaBuilder builder, this.target)
-      : this.builder = builder,
-        jumps = <JumpHandlerEntry>[] {
-    assert(builder.jumpTargets[target] == null);
-    builder.jumpTargets[target] = this;
-  }
-
-  void generateBreak([LabelDefinition label]) {
-    HInstruction breakInstruction;
-    if (label == null) {
-      breakInstruction = new HBreak(target);
-    } else {
-      breakInstruction = new HBreak.toLabel(label);
-    }
-    LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
-    builder.close(breakInstruction);
-    jumps.add(new JumpHandlerEntry(breakInstruction, locals));
-  }
-
-  void generateContinue([LabelDefinition label]) {
-    HInstruction continueInstruction;
-    if (label == null) {
-      continueInstruction = new HContinue(target);
-    } else {
-      continueInstruction = new HContinue.toLabel(label);
-      // Switch case continue statements must be handled by the
-      // [SwitchCaseJumpHandler].
-      assert(label.target.statement is! ast.SwitchCase);
-    }
-    LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
-    builder.close(continueInstruction);
-    jumps.add(new JumpHandlerEntry(continueInstruction, locals));
-  }
-
-  void forEachBreak(Function action) {
-    for (JumpHandlerEntry entry in jumps) {
-      if (entry.isBreak()) action(entry.jumpInstruction, entry.locals);
-    }
-  }
-
-  void forEachContinue(Function action) {
-    for (JumpHandlerEntry entry in jumps) {
-      if (entry.isContinue()) action(entry.jumpInstruction, entry.locals);
-    }
-  }
-
-  bool hasAnyContinue() {
-    for (JumpHandlerEntry entry in jumps) {
-      if (entry.isContinue()) return true;
-    }
-    return false;
-  }
-
-  bool hasAnyBreak() {
-    for (JumpHandlerEntry entry in jumps) {
-      if (entry.isBreak()) return true;
-    }
-    return false;
-  }
-
-  void close() {
-    // The mapping from TargetElement to JumpHandler is no longer needed.
-    builder.jumpTargets.remove(target);
-  }
-
-  List<LabelDefinition> labels() {
-    List<LabelDefinition> result = null;
-    for (LabelDefinition element in target.labels) {
-      if (result == null) result = <LabelDefinition>[];
-      result.add(element);
-    }
-    return (result == null) ? const <LabelDefinition>[] : result;
-  }
-}
-
-/// Special [JumpHandler] implementation used to handle continue statements
-/// targeting switch cases.
-class SwitchCaseJumpHandler extends TargetJumpHandler {
-  /// Map from switch case targets to indices used to encode the flow of the
-  /// switch case loop.
-  final Map<JumpTarget, int> targetIndexMap = new Map<JumpTarget, int>();
-
-  SwitchCaseJumpHandler(
-      SsaBuilder builder, JumpTarget target, ast.SwitchStatement node)
-      : super(builder, target) {
-    // The switch case indices must match those computed in
-    // [SsaFromAstMixin.buildSwitchCaseConstants].
-    // Switch indices are 1-based so we can bypass the synthetic loop when no
-    // cases match simply by branching on the index (which defaults to null).
-    int switchIndex = 1;
-    for (ast.SwitchCase switchCase in node.cases) {
-      for (ast.Node labelOrCase in switchCase.labelsAndCases) {
-        ast.Node label = labelOrCase.asLabel();
-        if (label != null) {
-          LabelDefinition labelElement =
-              builder.elements.getLabelDefinition(label);
-          if (labelElement != null && labelElement.isContinueTarget) {
-            JumpTarget continueTarget = labelElement.target;
-            targetIndexMap[continueTarget] = switchIndex;
-            assert(builder.jumpTargets[continueTarget] == null);
-            builder.jumpTargets[continueTarget] = this;
-          }
-        }
-      }
-      switchIndex++;
-    }
-  }
-
-  void generateBreak([LabelDefinition label]) {
-    if (label == null) {
-      // Creates a special break instruction for the synthetic loop generated
-      // for a switch statement with continue statements. See
-      // [SsaFromAstMixin.buildComplexSwitchStatement] for detail.
-
-      HInstruction breakInstruction =
-          new HBreak(target, breakSwitchContinueLoop: true);
-      LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
-      builder.close(breakInstruction);
-      jumps.add(new JumpHandlerEntry(breakInstruction, locals));
-    } else {
-      super.generateBreak(label);
-    }
-  }
-
-  bool isContinueToSwitchCase(LabelDefinition label) {
-    return label != null && targetIndexMap.containsKey(label.target);
-  }
-
-  void generateContinue([LabelDefinition label]) {
-    if (isContinueToSwitchCase(label)) {
-      // Creates the special instructions 'label = i; continue l;' used in
-      // switch statements with continue statements. See
-      // [SsaFromAstMixin.buildComplexSwitchStatement] for detail.
-
-      assert(label != null);
-      HInstruction value = builder.graph
-          .addConstantInt(targetIndexMap[label.target], builder.compiler);
-      builder.localsHandler.updateLocal(target, value);
-
-      assert(label.target.labels.contains(label));
-      HInstruction continueInstruction = new HContinue(target);
-      LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
-      builder.close(continueInstruction);
-      jumps.add(new JumpHandlerEntry(continueInstruction, locals));
-    } else {
-      super.generateContinue(label);
-    }
-  }
-
-  void close() {
-    // The mapping from TargetElement to JumpHandler is no longer needed.
-    for (JumpTarget target in targetIndexMap.keys) {
-      builder.jumpTargets.remove(target);
-    }
-    super.close();
-  }
-}
-
 /**
  * This class builds SSA nodes for functions represented in AST.
  */
@@ -376,7 +158,6 @@
   // used only for codegen, but currently we want to experiment using it for
   // code-analysis too.
   final CodegenRegistry registry;
-  final Compiler compiler;
   final GlobalTypeInferenceResults inferenceResults;
   final JavaScriptBackend backend;
   final ConstantSystem constantSystem;
@@ -397,13 +178,6 @@
   bool inExpressionOfThrow = false;
 
   /**
-   * The loop nesting is consulted when inlining a function invocation in
-   * [tryInlineMethod]. The inlining heuristics take this information into
-   * account.
-   */
-  int loopNesting = 0;
-
-  /**
    * This stack contains declaration elements of the functions being built
    * or inlined by this builder.
    */
@@ -411,8 +185,6 @@
 
   HInstruction rethrowableException;
 
-  Map<JumpTarget, JumpHandler> jumpTargets = <JumpTarget, JumpHandler>{};
-
   /// Returns `true` if the current element is an `async` function.
   bool get isBuildingAsyncFunction {
     Element element = sourceElement;
@@ -420,6 +192,9 @@
         element.asyncMarker == AsyncMarker.ASYNC);
   }
 
+  /// Handles the building of loops.
+  LoopHandler<ast.Node> loopHandler;
+
   // TODO(sigmund): make most args optional
   SsaBuilder(
       this.target,
@@ -428,13 +203,13 @@
       JavaScriptBackend backend,
       this.nativeEmitter,
       SourceInformationStrategy sourceInformationFactory)
-      : this.compiler = backend.compiler,
-        this.infoReporter = backend.compiler.dumpInfoTask,
+      : this.infoReporter = backend.compiler.dumpInfoTask,
         this.backend = backend,
         this.constantSystem = backend.constantSystem,
         this.rti = backend.rti,
         this.inferenceResults = backend.compiler.globalInference.results {
     assert(target.isImplementation);
+    compiler = backend.compiler;
     graph.element = target;
     sourceElementStack.add(target);
     sourceInformationBuilder =
@@ -442,6 +217,7 @@
     graph.sourceInformation =
         sourceInformationBuilder.buildVariableDeclaration();
     localsHandler = new LocalsHandler(this, target, null, compiler);
+    loopHandler = new SsaLoopHandler(this);
   }
 
   BackendHelpers get helpers => backend.helpers;
@@ -556,7 +332,7 @@
    */
   List<HInstruction> completeDynamicSendArgumentsList(Selector selector,
       FunctionElement function, List<HInstruction> providedArguments) {
-    assert(selector.applies(function, compiler.world));
+    assert(selector.applies(function, backend));
     FunctionSignature signature = function.functionSignature;
     List<HInstruction> compiledArguments = new List<HInstruction>(
         signature.parameterCount + 1); // Plus one for receiver.
@@ -632,7 +408,7 @@
 
     FunctionElement function = element;
     ResolvedAst functionResolvedAst = function.resolvedAst;
-    bool insideLoop = loopNesting > 0 || graph.calledInLoop;
+    bool insideLoop = loopDepth > 0 || graph.calledInLoop;
 
     // Bail out early if the inlining decision is in the cache and we can't
     // inline (no need to check the hard constraints).
@@ -650,8 +426,9 @@
               element.isGenerativeConstructorBody,
           message: "Missing selector for inlining of $element."));
       if (selector != null) {
-        if (!selector.applies(function, compiler.world)) return false;
-        if (mask != null && !mask.canHit(function, selector, compiler.world)) {
+        if (!selector.applies(function, backend)) return false;
+        if (mask != null &&
+            !mask.canHit(function, selector, compiler.closedWorld)) {
           return false;
         }
       }
@@ -896,7 +673,7 @@
    */
   HGraph buildMethod(FunctionElement functionElement) {
     assert(invariant(functionElement, functionElement.isImplementation));
-    graph.calledInLoop = compiler.world.isCalledInLoop(functionElement);
+    graph.calledInLoop = compiler.closedWorld.isCalledInLoop(functionElement);
     ast.FunctionExpression function = resolvedAst.node;
     assert(function != null);
     assert(elements.getFunctionDefinition(function) != null);
@@ -1484,8 +1261,8 @@
     }, includeSuperAndInjectedMembers: true);
 
     InterfaceType type = classElement.thisType;
-    TypeMask ssaType =
-        new TypeMask.nonNullExact(classElement.declaration, compiler.world);
+    TypeMask ssaType = new TypeMask.nonNullExact(
+        classElement.declaration, compiler.closedWorld);
     List<DartType> instantiatedTypes;
     addInlinedInstantiation(type);
     if (!currentInlinedInstantiations.isEmpty) {
@@ -1600,7 +1377,7 @@
         HInvokeConstructorBody invoke = new HInvokeConstructorBody(
             body.declaration, bodyCallInputs, backend.nonNullType);
         invoke.sideEffects =
-            compiler.world.getSideEffectsOfElement(constructor);
+            compiler.closedWorld.getSideEffectsOfElement(constructor);
         add(invoke);
       }
     }
@@ -1742,7 +1519,8 @@
     type = type.unaliased;
     assert(assertTypeInContext(type, original));
     if (type.isInterfaceType && !type.treatAsRaw) {
-      TypeMask subtype = new TypeMask.subtype(type.element, compiler.world);
+      TypeMask subtype =
+          new TypeMask.subtype(type.element, compiler.closedWorld);
       HInstruction representations = buildTypeArgumentRepresentations(type);
       add(representations);
       return new HTypeConversion.withTypeRepresentation(
@@ -1783,7 +1561,7 @@
     if (type.isObject) return original;
     // The type element is either a class or the void element.
     Element element = type.element;
-    TypeMask mask = new TypeMask.subtype(element, compiler.world);
+    TypeMask mask = new TypeMask.subtype(element, compiler.closedWorld);
     return new HTypeKnown.pinned(mask, original);
   }
 
@@ -1951,275 +1729,6 @@
     }
   }
 
-  /**
-   * Creates a new loop-header block. The previous [current] block
-   * is closed with an [HGoto] and replaced by the newly created block.
-   * Also notifies the locals handler that we're entering a loop.
-   */
-  JumpHandler beginLoopHeader(ast.Node node) {
-    assert(!isAborted());
-    HBasicBlock previousBlock = close(new HGoto());
-
-    JumpHandler jumpHandler = createJumpHandler(node, isLoopJump: true);
-    HBasicBlock loopEntry =
-        graph.addNewLoopHeaderBlock(jumpHandler.target, jumpHandler.labels());
-    previousBlock.addSuccessor(loopEntry);
-    open(loopEntry);
-
-    localsHandler.beginLoopHeader(loopEntry);
-    return jumpHandler;
-  }
-
-  /**
-   * Ends the loop:
-   * - creates a new block and adds it as successor to the [branchExitBlock] and
-   *   any blocks that end in break.
-   * - opens the new block (setting as [current]).
-   * - notifies the locals handler that we're exiting a loop.
-   * [savedLocals] are the locals from the end of the loop condition.
-   * [branchExitBlock] is the exit (branching) block of the condition. Generally
-   * this is not the top of the loop, since this would lead to critical edges.
-   * It is null for degenerate do-while loops that have
-   * no back edge because they abort (throw/return/break in the body and have
-   * no continues).
-   */
-  void endLoop(HBasicBlock loopEntry, HBasicBlock branchExitBlock,
-      JumpHandler jumpHandler, LocalsHandler savedLocals) {
-    HBasicBlock loopExitBlock = addNewBlock();
-
-    List<LocalsHandler> breakHandlers = <LocalsHandler>[];
-    // Collect data for the successors and the phis at each break.
-    jumpHandler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) {
-      breakInstruction.block.addSuccessor(loopExitBlock);
-      breakHandlers.add(locals);
-    });
-
-    // The exit block is a successor of the loop condition if it is reached.
-    // We don't add the successor in the case of a while/for loop that aborts
-    // because the caller of endLoop will be wiring up a special empty else
-    // block instead.
-    if (branchExitBlock != null) {
-      branchExitBlock.addSuccessor(loopExitBlock);
-    }
-    // Update the phis at the loop entry with the current values of locals.
-    localsHandler.endLoop(loopEntry);
-
-    // Start generating code for the exit block.
-    open(loopExitBlock);
-
-    // Create a new localsHandler for the loopExitBlock with the correct phis.
-    if (!breakHandlers.isEmpty) {
-      if (branchExitBlock != null) {
-        // Add the values of the locals at the end of the condition block to
-        // the phis.  These are the values that flow to the exit if the
-        // condition fails.
-        breakHandlers.add(savedLocals);
-      }
-      localsHandler = savedLocals.mergeMultiple(breakHandlers, loopExitBlock);
-    } else {
-      localsHandler = savedLocals;
-    }
-  }
-
-  HSubGraphBlockInformation wrapStatementGraph(SubGraph statements) {
-    if (statements == null) return null;
-    return new HSubGraphBlockInformation(statements);
-  }
-
-  HSubExpressionBlockInformation wrapExpressionGraph(SubExpression expression) {
-    if (expression == null) return null;
-    return new HSubExpressionBlockInformation(expression);
-  }
-
-  // For while loops, initializer and update are null.
-  // The condition function must return a boolean result.
-  // None of the functions must leave anything on the stack.
-  void handleLoop(ast.Node loop, void initialize(), HInstruction condition(),
-      void update(), void body()) {
-    // Generate:
-    //  <initializer>
-    //  loop-entry:
-    //    if (!<condition>) goto loop-exit;
-    //    <body>
-    //    <updates>
-    //    goto loop-entry;
-    //  loop-exit:
-
-    localsHandler.startLoop(loop);
-
-    // The initializer.
-    SubExpression initializerGraph = null;
-    HBasicBlock startBlock;
-    if (initialize != null) {
-      HBasicBlock initializerBlock = openNewBlock();
-      startBlock = initializerBlock;
-      initialize();
-      assert(!isAborted());
-      initializerGraph = new SubExpression(initializerBlock, current);
-    }
-
-    loopNesting++;
-    JumpHandler jumpHandler = beginLoopHeader(loop);
-    HLoopInformation loopInfo = current.loopInformation;
-    HBasicBlock conditionBlock = current;
-    if (startBlock == null) startBlock = conditionBlock;
-
-    HInstruction conditionInstruction = condition();
-    HBasicBlock conditionEndBlock =
-        close(new HLoopBranch(conditionInstruction));
-    SubExpression conditionExpression =
-        new SubExpression(conditionBlock, conditionEndBlock);
-
-    // Save the values of the local variables at the end of the condition
-    // block.  These are the values that will flow to the loop exit if the
-    // condition fails.
-    LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
-
-    // The body.
-    HBasicBlock beginBodyBlock = addNewBlock();
-    conditionEndBlock.addSuccessor(beginBodyBlock);
-    open(beginBodyBlock);
-
-    localsHandler.enterLoopBody(loop);
-    body();
-
-    SubGraph bodyGraph = new SubGraph(beginBodyBlock, lastOpenedBlock);
-    HBasicBlock bodyBlock = current;
-    if (current != null) close(new HGoto());
-
-    SubExpression updateGraph;
-
-    bool loopIsDegenerate = !jumpHandler.hasAnyContinue() && bodyBlock == null;
-    if (!loopIsDegenerate) {
-      // Update.
-      // We create an update block, even when we are in a while loop. There the
-      // update block is the jump-target for continue statements. We could avoid
-      // the creation if there is no continue, but for now we always create it.
-      HBasicBlock updateBlock = addNewBlock();
-
-      List<LocalsHandler> continueHandlers = <LocalsHandler>[];
-      jumpHandler
-          .forEachContinue((HContinue instruction, LocalsHandler locals) {
-        instruction.block.addSuccessor(updateBlock);
-        continueHandlers.add(locals);
-      });
-
-      if (bodyBlock != null) {
-        continueHandlers.add(localsHandler);
-        bodyBlock.addSuccessor(updateBlock);
-      }
-
-      open(updateBlock);
-      localsHandler =
-          continueHandlers[0].mergeMultiple(continueHandlers, updateBlock);
-
-      List<LabelDefinition> labels = jumpHandler.labels();
-      JumpTarget target = elements.getTargetDefinition(loop);
-      if (!labels.isEmpty) {
-        beginBodyBlock.setBlockFlow(
-            new HLabeledBlockInformation(
-                new HSubGraphBlockInformation(bodyGraph), jumpHandler.labels(),
-                isContinue: true),
-            updateBlock);
-      } else if (target != null && target.isContinueTarget) {
-        beginBodyBlock.setBlockFlow(
-            new HLabeledBlockInformation.implicit(
-                new HSubGraphBlockInformation(bodyGraph), target,
-                isContinue: true),
-            updateBlock);
-      }
-
-      localsHandler.enterLoopUpdates(loop);
-
-      update();
-
-      HBasicBlock updateEndBlock = close(new HGoto());
-      // The back-edge completing the cycle.
-      updateEndBlock.addSuccessor(conditionBlock);
-      updateGraph = new SubExpression(updateBlock, updateEndBlock);
-
-      // Avoid a critical edge from the condition to the loop-exit body.
-      HBasicBlock conditionExitBlock = addNewBlock();
-      open(conditionExitBlock);
-      close(new HGoto());
-      conditionEndBlock.addSuccessor(conditionExitBlock);
-
-      endLoop(conditionBlock, conditionExitBlock, jumpHandler, savedLocals);
-
-      conditionBlock.postProcessLoopHeader();
-      HLoopBlockInformation info = new HLoopBlockInformation(
-          _loopKind(loop),
-          wrapExpressionGraph(initializerGraph),
-          wrapExpressionGraph(conditionExpression),
-          wrapStatementGraph(bodyGraph),
-          wrapExpressionGraph(updateGraph),
-          conditionBlock.loopInformation.target,
-          conditionBlock.loopInformation.labels,
-          sourceInformationBuilder.buildLoop(loop));
-
-      startBlock.setBlockFlow(info, current);
-      loopInfo.loopBlockInformation = info;
-    } else {
-      // The body of the for/while loop always aborts, so there is no back edge.
-      // We turn the code into:
-      // if (condition) {
-      //   body;
-      // } else {
-      //   // We always create an empty else block to avoid critical edges.
-      // }
-      //
-      // If there is any break in the body, we attach a synthetic
-      // label to the if.
-      HBasicBlock elseBlock = addNewBlock();
-      open(elseBlock);
-      close(new HGoto());
-      // Pass the elseBlock as the branchBlock, because that's the block we go
-      // to just before leaving the 'loop'.
-      endLoop(conditionBlock, elseBlock, jumpHandler, savedLocals);
-
-      SubGraph elseGraph = new SubGraph(elseBlock, elseBlock);
-      // Remove the loop information attached to the header.
-      conditionBlock.loopInformation = null;
-
-      // Remove the [HLoopBranch] instruction and replace it with
-      // [HIf].
-      HInstruction condition = conditionEndBlock.last.inputs[0];
-      conditionEndBlock.addAtExit(new HIf(condition));
-      conditionEndBlock.addSuccessor(elseBlock);
-      conditionEndBlock.remove(conditionEndBlock.last);
-      HIfBlockInformation info = new HIfBlockInformation(
-          wrapExpressionGraph(conditionExpression),
-          wrapStatementGraph(bodyGraph),
-          wrapStatementGraph(elseGraph));
-
-      conditionEndBlock.setBlockFlow(info, current);
-      HIf ifBlock = conditionEndBlock.last;
-      ifBlock.blockInformation = conditionEndBlock.blockFlow;
-
-      // If the body has any break, attach a synthesized label to the
-      // if block.
-      if (jumpHandler.hasAnyBreak()) {
-        JumpTarget target = elements.getTargetDefinition(loop);
-        LabelDefinition label = target.addLabel(null, 'loop');
-        label.setBreakTarget();
-        SubGraph labelGraph = new SubGraph(conditionBlock, current);
-        HLabeledBlockInformation labelInfo = new HLabeledBlockInformation(
-            new HSubGraphBlockInformation(labelGraph),
-            <LabelDefinition>[label]);
-
-        conditionBlock.setBlockFlow(labelInfo, current);
-
-        jumpHandler.forEachBreak((HBreak breakInstruction, _) {
-          HBasicBlock block = breakInstruction.block;
-          block.addAtExit(new HBreak.toLabel(label));
-          block.remove(breakInstruction);
-        });
-      }
-    }
-    jumpHandler.close();
-    loopNesting--;
-  }
-
   visitFor(ast.For node) {
     assert(isReachable);
     assert(node.body != null);
@@ -2254,7 +1763,8 @@
       visit(node.body);
     }
 
-    handleLoop(node, buildInitializer, buildCondition, buildUpdate, buildBody);
+    loopHandler.handleLoop(
+        node, buildInitializer, buildCondition, buildUpdate, buildBody);
   }
 
   visitWhile(ast.While node) {
@@ -2264,7 +1774,7 @@
       return popBoolified();
     }
 
-    handleLoop(node, () {}, buildCondition, () {}, () {
+    loopHandler.handleLoop(node, () {}, buildCondition, () {}, () {
       visit(node.body);
     });
   }
@@ -2273,8 +1783,8 @@
     assert(isReachable);
     LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
     localsHandler.startLoop(node);
-    loopNesting++;
-    JumpHandler jumpHandler = beginLoopHeader(node);
+    loopDepth++;
+    JumpHandler jumpHandler = loopHandler.beginLoopHeader(node);
     HLoopInformation loopInfo = current.loopInformation;
     HBasicBlock loopEntryBlock = current;
     HBasicBlock bodyEntryBlock = current;
@@ -2361,7 +1871,8 @@
       close(new HGoto());
       conditionEndBlock.addSuccessor(conditionExitBlock);
 
-      endLoop(loopEntryBlock, conditionExitBlock, jumpHandler, localsHandler);
+      loopHandler.endLoop(
+          loopEntryBlock, conditionExitBlock, jumpHandler, localsHandler);
 
       loopEntryBlock.postProcessLoopHeader();
       SubGraph bodyGraph = new SubGraph(loopEntryBlock, bodyExitBlock);
@@ -2384,7 +1895,7 @@
       if (jumpHandler.hasAnyBreak()) {
         // Null branchBlock because the body of the do-while loop always aborts,
         // so we never get to the condition.
-        endLoop(loopEntryBlock, null, jumpHandler, localsHandler);
+        loopHandler.endLoop(loopEntryBlock, null, jumpHandler, localsHandler);
 
         // Since the body of the loop has a break, we attach a synthesized label
         // to the body.
@@ -2403,7 +1914,7 @@
       }
     }
     jumpHandler.close();
-    loopNesting--;
+    loopDepth--;
   }
 
   visitFunctionExpression(ast.FunctionExpression node) {
@@ -2428,7 +1939,7 @@
     });
 
     TypeMask type =
-        new TypeMask.nonNullExact(closureClassElement, compiler.world);
+        new TypeMask.nonNullExact(closureClassElement, compiler.closedWorld);
     push(new HCreate(closureClassElement, capturedVariables, type)
       ..sourceInformation = sourceInformationBuilder.buildCreate(node));
 
@@ -2704,7 +2215,8 @@
     // handler in the case of lists, because the constant handler
     // does not look at elements in the list.
     TypeMask type = TypeMaskFactory.inferredTypeForElement(field, compiler);
-    if (!type.containsAll(compiler.world) && !instruction.isConstantNull()) {
+    if (!type.containsAll(compiler.closedWorld) &&
+        !instruction.isConstantNull()) {
       // TODO(13429): The inferrer should know that an element
       // cannot be null.
       instruction.instructionType = type.nonNullable();
@@ -3048,7 +2560,8 @@
       add(representations);
       js.Name operator = backend.namer.operatorIs(element);
       HInstruction isFieldName = addConstantStringFromName(operator);
-      HInstruction asFieldName = compiler.world.hasAnyStrictSubtype(element)
+      HInstruction asFieldName = compiler.closedWorld
+              .hasAnyStrictSubtype(element)
           ? addConstantStringFromName(backend.namer.substitutionName(element))
           : graph.addConstantNull(compiler);
       List<HInstruction> inputs = <HInstruction>[
@@ -3072,7 +2585,7 @@
   }
 
   HInstruction buildFunctionType(FunctionType type) {
-    type.accept(new TypeBuilder(compiler.world), this);
+    type.accept(new TypeBuilder(compiler.closedWorld), this);
     return pop();
   }
 
@@ -3688,8 +3201,7 @@
     // TODO(5347): Try to avoid the need for calling [implementation] before
     // calling [makeStaticArgumentList].
     Selector selector = elements.getSelector(node);
-    assert(invariant(
-        node, selector.applies(function.implementation, compiler.world),
+    assert(invariant(node, selector.applies(function.implementation, backend),
         message: "$selector does not apply to ${function.implementation}"));
     List<HInstruction> inputs = makeStaticArgumentList(
         selector.callStructure, node.arguments, function.implementation);
@@ -3854,10 +3366,11 @@
   }
 
   bool needsSubstitutionForTypeVariableAccess(ClassElement cls) {
-    ClassWorld classWorld = compiler.world;
-    if (classWorld.isUsedAsMixin(cls)) return true;
+    ClosedWorld closedWorld = compiler.closedWorld;
+    if (closedWorld.isUsedAsMixin(cls)) return true;
 
-    return compiler.world.anyStrictSubclassOf(cls, (ClassElement subclass) {
+    return compiler.closedWorld.anyStrictSubclassOf(cls,
+        (ClassElement subclass) {
       return !rti.isTrivialSubstitution(subclass, cls);
     });
   }
@@ -4038,12 +3551,12 @@
               originalElement, send, compiler)) {
         isFixedList = true;
         TypeMask inferred = _inferredTypeOfNewList(send);
-        return inferred.containsAll(compiler.world)
+        return inferred.containsAll(compiler.closedWorld)
             ? backend.fixedArrayType
             : inferred;
       } else if (isGrowableListConstructorCall) {
         TypeMask inferred = _inferredTypeOfNewList(send);
-        return inferred.containsAll(compiler.world)
+        return inferred.containsAll(compiler.closedWorld)
             ? backend.extendableArrayType
             : inferred;
       } else if (Elements.isConstructorOfTypedArraySubclass(
@@ -4052,8 +3565,9 @@
         TypeMask inferred = _inferredTypeOfNewList(send);
         ClassElement cls = element.enclosingClass;
         assert(backend.isNative(cls.thisType.element));
-        return inferred.containsAll(compiler.world)
-            ? new TypeMask.nonNullExact(cls.thisType.element, compiler.world)
+        return inferred.containsAll(compiler.closedWorld)
+            ? new TypeMask.nonNullExact(
+                cls.thisType.element, compiler.closedWorld)
             : inferred;
       } else if (element.isGenerativeConstructor) {
         ClassElement cls = element.enclosingClass;
@@ -4062,7 +3576,7 @@
           return new TypeMask.nonNullEmpty();
         } else {
           return new TypeMask.nonNullExact(
-              cls.thisType.element, compiler.world);
+              cls.thisType.element, compiler.closedWorld);
         }
       } else {
         return TypeMaskFactory.inferredReturnTypeForElement(
@@ -4686,10 +4200,11 @@
     bool isOptimizableOperationOnIndexable(Selector selector, Element element) {
       bool isLength = selector.isGetter && selector.name == "length";
       if (isLength || selector.isIndex) {
-        return compiler.world.isSubtypeOf(
+        return compiler.closedWorld.isSubtypeOf(
             element.enclosingClass.declaration, helpers.jsIndexableClass);
       } else if (selector.isIndexSet) {
-        return compiler.world.isSubtypeOf(element.enclosingClass.declaration,
+        return compiler.closedWorld.isSubtypeOf(
+            element.enclosingClass.declaration,
             helpers.jsMutableIndexableClass);
       } else {
         return false;
@@ -4712,7 +4227,7 @@
       return false;
     }
 
-    Element element = compiler.world.locateSingleElement(selector, mask);
+    Element element = compiler.closedWorld.locateSingleElement(selector, mask);
     if (element != null &&
         !element.isField &&
         !(element.isGetter && selector.isCall) &&
@@ -4859,7 +4374,7 @@
       typeMask =
           TypeMaskFactory.inferredReturnTypeForElement(element, compiler);
     }
-    bool targetCanThrow = !compiler.world.getCannotThrow(element);
+    bool targetCanThrow = !compiler.closedWorld.getCannotThrow(element);
     // TODO(5346): Try to avoid the need for calling [declaration] before
     var instruction;
     if (backend.isJsInterop(element)) {
@@ -4874,7 +4389,8 @@
         instruction.instantiatedTypes =
             new List<DartType>.from(currentInlinedInstantiations);
       }
-      instruction.sideEffects = compiler.world.getSideEffectsOfElement(element);
+      instruction.sideEffects =
+          compiler.closedWorld.getSideEffectsOfElement(element);
     }
     if (location == null) {
       push(instruction);
@@ -4908,7 +4424,7 @@
         selector, inputs, type, sourceInformation,
         isSetter: selector.isSetter || selector.isIndexSet);
     instruction.sideEffects =
-        compiler.world.getSideEffectsOfSelector(selector, null);
+        compiler.closedWorld.getSideEffectsOfSelector(selector, null);
     return instruction;
   }
 
@@ -4938,7 +4454,7 @@
     void generateSuperSendSet() {
       Selector setterSelector = elements.getSelector(node);
       if (Elements.isUnresolved(element) ||
-          !setterSelector.applies(element, compiler.world)) {
+          !setterSelector.applies(element, compiler.backend)) {
         generateSuperNoSuchMethodSend(node, setterSelector, setterInputs);
         pop();
       } else {
@@ -5917,7 +5433,7 @@
     HInstruction awaited = pop();
     // TODO(herhut): Improve this type.
     push(new HAwait(awaited,
-        new TypeMask.subclass(coreClasses.objectClass, compiler.world)));
+        new TypeMask.subclass(coreClasses.objectClass, compiler.closedWorld)));
   }
 
   visitTypeAnnotation(ast.TypeAnnotation node) {
@@ -5977,7 +5493,9 @@
     }
 
     TypeMask type = _inferredTypeOfNewList(node);
-    if (!type.containsAll(compiler.world)) instruction.instructionType = type;
+    if (!type.containsAll(compiler.closedWorld)) {
+      instruction.instructionType = type;
+    }
     stack.add(instruction);
   }
 
@@ -6047,7 +5565,7 @@
    * a special "null handler" is returned.
    *
    * [isLoopJump] is [:true:] when the jump handler is for a loop. This is used
-   * to distinguish the synthetized loop created for a switch statement with
+   * to distinguish the synthesized loop created for a switch statement with
    * continue statements from simple switch statements.
    */
   JumpHandler createJumpHandler(ast.Statement node, {bool isLoopJump}) {
@@ -6081,8 +5599,10 @@
       TypeMask mask = inferenceResults.typeOfIteratorMoveNext(node, elements);
       pushInvokeDynamic(node, selector, mask, [streamIterator]);
       HInstruction future = pop();
-      push(new HAwait(future,
-          new TypeMask.subclass(coreClasses.objectClass, compiler.world)));
+      push(new HAwait(
+          future,
+          new TypeMask.subclass(
+              coreClasses.objectClass, compiler.closedWorld)));
       return popBoolified();
     }
 
@@ -6114,12 +5634,14 @@
     void buildUpdate() {}
 
     buildProtectedByFinally(() {
-      handleLoop(
+      loopHandler.handleLoop(
           node, buildInitializer, buildCondition, buildUpdate, buildBody);
     }, () {
       pushInvokeDynamic(node, Selectors.cancel, null, [streamIterator]);
-      push(new HAwait(pop(),
-          new TypeMask.subclass(coreClasses.objectClass, compiler.world)));
+      push(new HAwait(
+          pop(),
+          new TypeMask.subclass(
+              coreClasses.objectClass, compiler.closedWorld)));
       pop();
     });
   }
@@ -6137,11 +5659,11 @@
 
     TypeMask mask = inferenceResults.typeOfIterator(node, elements);
 
-    ClassWorld classWorld = compiler.world;
+    ClosedWorld closedWorld = compiler.closedWorld;
     if (mask != null &&
-        mask.satisfies(helpers.jsIndexableClass, classWorld) &&
+        mask.satisfies(helpers.jsIndexableClass, closedWorld) &&
         // String is indexable but not iterable.
-        !mask.satisfies(helpers.jsStringClass, classWorld)) {
+        !mask.satisfies(helpers.jsStringClass, closedWorld)) {
       return buildSyncForInIndexable(node, mask);
     }
     buildSyncForInIterator(node);
@@ -6182,7 +5704,8 @@
       visit(node.body);
     }
 
-    handleLoop(node, buildInitializer, buildCondition, () {}, buildBody);
+    loopHandler.handleLoop(
+        node, buildInitializer, buildCondition, () {}, buildBody);
   }
 
   buildAssignLoopVariable(ast.ForIn node, HInstruction value) {
@@ -6301,7 +5824,8 @@
       localsHandler.updateLocal(indexVariable, addInstruction);
     }
 
-    handleLoop(node, buildInitializer, buildCondition, buildUpdate, buildBody);
+    loopHandler.handleLoop(
+        node, buildInitializer, buildCondition, buildUpdate, buildBody);
   }
 
   visitLabel(ast.Label node) {
@@ -6415,12 +5939,12 @@
     // The instruction type will always be a subtype of the mapLiteralClass, but
     // type inference might discover a more specific type, or find nothing (in
     // dart2js unit tests).
-    TypeMask mapType =
-        new TypeMask.nonNullSubtype(helpers.mapLiteralClass, compiler.world);
+    TypeMask mapType = new TypeMask.nonNullSubtype(
+        helpers.mapLiteralClass, compiler.closedWorld);
     TypeMask returnTypeMask =
         TypeMaskFactory.inferredReturnTypeForElement(constructor, compiler);
     TypeMask instructionType =
-        mapType.intersection(returnTypeMask, compiler.world);
+        mapType.intersection(returnTypeMask, compiler.closedWorld);
 
     addInlinedInstantiation(expectedType);
     pushInvokeStatic(node, constructor, inputs,
@@ -6645,7 +6169,7 @@
     }
 
     void buildLoop() {
-      handleLoop(node, () {}, buildCondition, () {}, buildSwitch);
+      loopHandler.handleLoop(node, () {}, buildCondition, () {}, buildSwitch);
     }
 
     if (hasDefault) {
@@ -7248,7 +6772,7 @@
     Selector selector = Selectors.toString_;
     TypeMask type = TypeMaskFactory.inferredTypeForSelector(
         selector, expression.instructionType, compiler);
-    if (type.containsOnlyString(compiler.world)) {
+    if (type.containsOnlyString(compiler.closedWorld)) {
       builder.pushInvokeDynamic(node, selector, expression.instructionType,
           <HInstruction>[expression]);
       append(builder.pop());
@@ -7458,20 +6982,20 @@
 }
 
 class TypeBuilder implements DartTypeVisitor<dynamic, SsaBuilder> {
-  final ClassWorld classWorld;
+  final ClosedWorld closedWorld;
 
-  TypeBuilder(this.classWorld);
+  TypeBuilder(this.closedWorld);
 
   void visit(DartType type, SsaBuilder builder) => type.accept(this, builder);
 
   void visitVoidType(VoidType type, SsaBuilder builder) {
     ClassElement cls = builder.backend.helpers.VoidRuntimeType;
-    builder.push(new HVoidType(type, new TypeMask.exact(cls, classWorld)));
+    builder.push(new HVoidType(type, new TypeMask.exact(cls, closedWorld)));
   }
 
   void visitTypeVariableType(TypeVariableType type, SsaBuilder builder) {
     ClassElement cls = builder.backend.helpers.RuntimeType;
-    TypeMask instructionType = new TypeMask.subclass(cls, classWorld);
+    TypeMask instructionType = new TypeMask.subclass(cls, closedWorld);
     if (!builder.sourceElement.enclosingElement.isClosure &&
         builder.sourceElement.isInstanceMember) {
       HInstruction receiver = builder.localsHandler.readThis();
@@ -7508,7 +7032,7 @@
 
     ClassElement cls = builder.backend.helpers.RuntimeFunctionType;
     builder.push(
-        new HFunctionType(inputs, type, new TypeMask.exact(cls, classWorld)));
+        new HFunctionType(inputs, type, new TypeMask.exact(cls, closedWorld)));
   }
 
   void visitMalformedType(MalformedType type, SsaBuilder builder) {
@@ -7532,7 +7056,7 @@
       cls = builder.backend.helpers.RuntimeTypeGeneric;
     }
     builder.push(
-        new HInterfaceType(inputs, type, new TypeMask.exact(cls, classWorld)));
+        new HInterfaceType(inputs, type, new TypeMask.exact(cls, closedWorld)));
   }
 
   void visitTypedefType(TypedefType type, SsaBuilder builder) {
@@ -7544,22 +7068,6 @@
   void visitDynamicType(DynamicType type, SsaBuilder builder) {
     JavaScriptBackend backend = builder.compiler.backend;
     ClassElement cls = backend.helpers.DynamicRuntimeType;
-    builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld)));
+    builder.push(new HDynamicType(type, new TypeMask.exact(cls, closedWorld)));
   }
 }
-
-/// Determine what kind of loop [node] represents. The result is one of the
-/// kinds defined in [HLoopBlockInformation].
-int _loopKind(ast.Node node) => node.accept(const _LoopTypeVisitor());
-
-class _LoopTypeVisitor extends ast.Visitor {
-  const _LoopTypeVisitor();
-  int visitNode(ast.Node node) => HLoopBlockInformation.NOT_A_LOOP;
-  int visitWhile(ast.While node) => HLoopBlockInformation.WHILE_LOOP;
-  int visitFor(ast.For node) => HLoopBlockInformation.FOR_LOOP;
-  int visitDoWhile(ast.DoWhile node) => HLoopBlockInformation.DO_WHILE_LOOP;
-  int visitAsyncForIn(ast.AsyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP;
-  int visitSyncForIn(ast.SyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP;
-  int visitSwitchStatement(ast.SwitchStatement node) =>
-      HLoopBlockInformation.SWITCH_CONTINUE_LOOP;
-}
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 2e4511c..2d4726d 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -13,13 +13,16 @@
 import '../io/source_information.dart';
 import '../js_backend/backend.dart' show JavaScriptBackend;
 import '../kernel/kernel.dart';
+import '../resolution/tree_elements.dart';
 import '../tree/dartstring.dart';
 import '../types/masks.dart';
 import '../universe/selector.dart';
 
 import 'graph_builder.dart';
 import 'kernel_ast_adapter.dart';
+import 'kernel_string_builder.dart';
 import 'locals_handler.dart';
+import 'loop_handler.dart';
 import 'nodes.dart';
 import 'ssa_branch_builder.dart';
 
@@ -48,21 +51,25 @@
   ir.Node target;
   final AstElement targetElement;
   final ResolvedAst resolvedAst;
-  final Compiler compiler;
   final CodegenRegistry registry;
 
   JavaScriptBackend get backend => compiler.backend;
 
+  TreeElements get elements => resolvedAst.elements;
+
   SourceInformationBuilder sourceInformationBuilder;
   KernelAstAdapter astAdapter;
+  LoopHandler<ir.Node> loopHandler;
 
   KernelSsaBuilder(
       this.targetElement,
       this.resolvedAst,
-      this.compiler,
+      Compiler compiler,
       this.registry,
       SourceInformationStrategy sourceInformationFactory,
       Kernel kernel) {
+    this.compiler = compiler;
+    this.loopHandler = new KernelLoopHandler(this);
     graph.element = targetElement;
     // TODO(het): Should sourceInformationBuilder be in GraphBuilder?
     this.sourceInformationBuilder =
@@ -199,6 +206,55 @@
   }
 
   @override
+  void visitForStatement(ir.ForStatement forStatement) {
+    assert(isReachable);
+    assert(forStatement.body != null);
+    void buildInitializer() {
+      for (ir.VariableDeclaration declaration in forStatement.variables) {
+        declaration.accept(this);
+      }
+    }
+
+    HInstruction buildCondition() {
+      if (forStatement.condition == null) {
+        return graph.addConstantBool(true, compiler);
+      }
+      forStatement.condition.accept(this);
+      return popBoolified();
+    }
+
+    void buildUpdate() {
+      for (ir.Expression expression in forStatement.updates) {
+        expression.accept(this);
+        assert(!isAborted());
+        // The result of the update instruction isn't used, and can just
+        // be dropped.
+        pop();
+      }
+    }
+
+    void buildBody() {
+      forStatement.body.accept(this);
+    }
+
+    loopHandler.handleLoop(
+        forStatement, buildInitializer, buildCondition, buildUpdate, buildBody);
+  }
+
+  @override
+  void visitWhileStatement(ir.WhileStatement whileStatement) {
+    assert(isReachable);
+    HInstruction buildCondition() {
+      whileStatement.condition.accept(this);
+      return popBoolified();
+    }
+
+    loopHandler.handleLoop(whileStatement, () {}, buildCondition, () {}, () {
+      whileStatement.body.accept(this);
+    });
+  }
+
+  @override
   void visitIfStatement(ir.IfStatement ifStatement) {
     SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler);
     brancher.handleIf(
@@ -514,7 +570,7 @@
         null,
         isSetter: selector.isSetter || selector.isIndexSet);
     instruction.sideEffects =
-        compiler.world.getSideEffectsOfSelector(selector, null);
+        compiler.closedWorld.getSideEffectsOfSelector(selector, null);
     push(instruction);
   }
 
@@ -523,7 +579,7 @@
     ir.Constructor target = invocation.target;
     List<HInstruction> arguments = _visitArguments(invocation.arguments);
     TypeMask typeMask = new TypeMask.nonNullExact(
-        astAdapter.getElement(target.enclosingClass), compiler.world);
+        astAdapter.getElement(target.enclosingClass), compiler.closedWorld);
     _pushStaticInvocation(target, arguments, typeMask);
   }
 
@@ -565,4 +621,11 @@
     not.operand.accept(this);
     push(new HNot(popBoolified(), backend.boolType));
   }
+
+  @override
+  void visitStringConcatenation(ir.StringConcatenation stringConcat) {
+    KernelStringBuilder stringBuilder = new KernelStringBuilder(this);
+    stringConcat.accept(stringBuilder);
+    stack.add(stringBuilder.result);
+  }
 }
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 6faf0b4..e677afd 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -22,7 +22,7 @@
 import '../universe/selector.dart' show Selector;
 import '../universe/use.dart' show DynamicUse, StaticUse, TypeUse;
 import '../util/util.dart';
-import '../world.dart' show ClassWorld;
+import '../world.dart' show ClosedWorld;
 import 'codegen_helpers.dart';
 import 'nodes.dart';
 import 'variable_allocator.dart';
@@ -1656,21 +1656,22 @@
       // type because our optimizations might end up in a state where the
       // invoke dynamic knows more than the receiver.
       ClassElement enclosing = node.element.enclosingClass;
-      if (compiler.world.isInstantiated(enclosing)) {
-        return new TypeMask.nonNullExact(enclosing.declaration, compiler.world);
+      if (compiler.closedWorld.isInstantiated(enclosing)) {
+        return new TypeMask.nonNullExact(
+            enclosing.declaration, compiler.closedWorld);
       } else {
         // The element is mixed in so a non-null subtype mask is the most
         // precise we have.
-        assert(invariant(node, compiler.world.isUsedAsMixin(enclosing),
+        assert(invariant(node, compiler.closedWorld.isUsedAsMixin(enclosing),
             message: "Element ${node.element} from $enclosing expected "
                 "to be mixed in."));
         return new TypeMask.nonNullSubtype(
-            enclosing.declaration, compiler.world);
+            enclosing.declaration, compiler.closedWorld);
       }
     }
     // If [JSInvocationMirror._invokeOn] is enabled, and this call
     // might hit a `noSuchMethod`, we register an untyped selector.
-    return compiler.world.extendMaskIfReachesAll(selector, mask);
+    return compiler.closedWorld.extendMaskIfReachesAll(selector, mask);
   }
 
   void registerMethodInvoke(HInvokeDynamic node) {
@@ -2703,18 +2704,18 @@
 
   js.Expression generateReceiverOrArgumentTypeTest(
       HInstruction input, TypeMask checkedType) {
-    ClassWorld classWorld = compiler.world;
+    ClosedWorld closedWorld = compiler.closedWorld;
     TypeMask inputType = input.instructionType;
     // Figure out if it is beneficial to turn this into a null check.
     // V8 generally prefers 'typeof' checks, but for integers and
     // indexable primitives we cannot compile this test into a single
     // typeof check so the null check is cheaper.
-    bool isIntCheck = checkedType.containsOnlyInt(classWorld);
+    bool isIntCheck = checkedType.containsOnlyInt(closedWorld);
     bool turnIntoNumCheck = isIntCheck && input.isIntegerOrNull(compiler);
     bool turnIntoNullCheck = !turnIntoNumCheck &&
         (checkedType.nullable() == inputType) &&
         (isIntCheck ||
-            checkedType.satisfies(helpers.jsIndexableClass, classWorld));
+            checkedType.satisfies(helpers.jsIndexableClass, closedWorld));
 
     if (turnIntoNullCheck) {
       use(input);
@@ -2724,15 +2725,15 @@
       // input is !int
       checkBigInt(input, '!==', input.sourceInformation);
       return pop();
-    } else if (turnIntoNumCheck || checkedType.containsOnlyNum(classWorld)) {
+    } else if (turnIntoNumCheck || checkedType.containsOnlyNum(closedWorld)) {
       // input is !num
       checkNum(input, '!==', input.sourceInformation);
       return pop();
-    } else if (checkedType.containsOnlyBool(classWorld)) {
+    } else if (checkedType.containsOnlyBool(closedWorld)) {
       // input is !bool
       checkBool(input, '!==', input.sourceInformation);
       return pop();
-    } else if (checkedType.containsOnlyString(classWorld)) {
+    } else if (checkedType.containsOnlyString(closedWorld)) {
       // input is !string
       checkString(input, '!==', input.sourceInformation);
       return pop();
@@ -2743,11 +2744,11 @@
 
   void visitTypeConversion(HTypeConversion node) {
     if (node.isArgumentTypeCheck || node.isReceiverTypeCheck) {
-      ClassWorld classWorld = compiler.world;
+      ClosedWorld closedWorld = compiler.closedWorld;
       // An int check if the input is not int or null, is not
       // sufficient for doing an argument or receiver check.
       assert(compiler.options.trustTypeAnnotations ||
-          !node.checkedType.containsOnlyInt(classWorld) ||
+          !node.checkedType.containsOnlyInt(closedWorld) ||
           node.checkedInput.isIntegerOrNull(compiler));
       js.Expression test = generateReceiverOrArgumentTypeTest(
           node.checkedInput, node.checkedType);
@@ -2857,15 +2858,15 @@
 
   void visitTypeInfoReadVariable(HTypeInfoReadVariable node) {
     TypeVariableElement element = node.variable.element;
-    ClassElement context = element.enclosingClass;
 
     int index = element.index;
-    use(node.inputs[0]);
+    HInstruction object = node.object;
+    use(object);
     js.Expression receiver = pop();
 
-    if (needsSubstitutionForTypeVariableAccess(context)) {
+    if (typeVariableAccessNeedsSubstitution(element, object.instructionType)) {
       js.Expression typeName =
-          js.quoteName(backend.namer.runtimeTypeName(context));
+          js.quoteName(backend.namer.runtimeTypeName(element.enclosingClass));
       Element helperElement = helpers.getRuntimeTypeArgument;
       registry.registerStaticUse(
           new StaticUse.staticInvoke(helperElement, CallStructure.THREE_ARGS));
@@ -2909,11 +2910,25 @@
     }
   }
 
-  bool needsSubstitutionForTypeVariableAccess(ClassElement cls) {
-    ClassWorld classWorld = compiler.world;
-    if (classWorld.isUsedAsMixin(cls)) return true;
+  bool typeVariableAccessNeedsSubstitution(
+      TypeVariableElement element, TypeMask receiverMask) {
+    ClassElement cls = element.enclosingClass;
+    ClosedWorld closedWorld = compiler.closedWorld;
 
-    return compiler.world.anyStrictSubclassOf(cls, (ClassElement subclass) {
+    // See if the receiver type narrows the set of classes to ones that can be
+    // indexed.
+    // TODO(sra): Currently the only convenient query is [singleClass]. We
+    // should iterate over all the concrete classes in [receiverMask].
+    ClassElement receiverClass = receiverMask.singleClass(closedWorld);
+    if (receiverClass != null) {
+      if (backend.rti.isTrivialSubstitution(receiverClass, cls)) {
+        return false;
+      }
+    }
+
+    if (closedWorld.isUsedAsMixin(cls)) return true;
+
+    return closedWorld.anyStrictSubclassOf(cls, (ClassElement subclass) {
       return !backend.rti.isTrivialSubstitution(subclass, cls);
     });
   }
diff --git a/pkg/compiler/lib/src/ssa/graph_builder.dart b/pkg/compiler/lib/src/ssa/graph_builder.dart
index f7578f3..9898c6a 100644
--- a/pkg/compiler/lib/src/ssa/graph_builder.dart
+++ b/pkg/compiler/lib/src/ssa/graph_builder.dart
@@ -2,9 +2,12 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import '../compiler.dart';
 import '../elements/elements.dart';
+import '../resolution/tree_elements.dart';
 import '../types/types.dart';
 
+import 'jump_handler.dart';
 import 'locals_handler.dart';
 import 'nodes.dart';
 
@@ -16,6 +19,13 @@
   /// Holds the resulting SSA graph.
   final HGraph graph = new HGraph();
 
+  // TODO(het): remove this
+  /// A reference to the compiler.
+  Compiler compiler;
+
+  /// The tree elements for the element being built into an SSA graph.
+  TreeElements get elements;
+
   /// Used to track the locals while building the graph.
   LocalsHandler localsHandler;
 
@@ -24,6 +34,15 @@
   /// We build the SSA graph by simulating a stack machine.
   List<HInstruction> stack = <HInstruction>[];
 
+  /// The count of nested loops we are currently building.
+  ///
+  /// The loop nesting is consulted when inlining a function invocation. The
+  /// inlining heuristics take this information into account.
+  int loopDepth = 0;
+
+  /// A mapping from jump targets to their handlers.
+  Map<JumpTarget, JumpHandler> jumpTargets = <JumpTarget, JumpHandler>{};
+
   void push(HInstruction instruction) {
     add(instruction);
     stack.add(instruction);
@@ -133,4 +152,14 @@
     lastAddedParameter = result;
     return result;
   }
+
+  HSubGraphBlockInformation wrapStatementGraph(SubGraph statements) {
+    if (statements == null) return null;
+    return new HSubGraphBlockInformation(statements);
+  }
+
+  HSubExpressionBlockInformation wrapExpressionGraph(SubExpression expression) {
+    if (expression == null) return null;
+    return new HSubExpressionBlockInformation(expression);
+  }
 }
diff --git a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
index 10202de..eafe01b 100644
--- a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
+++ b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
@@ -49,7 +49,7 @@
 
   BackendHelpers get helpers => backend.helpers;
 
-  ClassWorld get classWorld => compiler.world;
+  ClassWorld get classWorld => compiler.closedWorld;
 
   void visitGraph(HGraph graph) {
     this.graph = graph;
diff --git a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
index cf05b2e..463c31c 100644
--- a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
+++ b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
@@ -10,7 +10,7 @@
 import '../types/types.dart';
 import '../universe/call_structure.dart';
 import '../universe/selector.dart';
-import '../world.dart' show World;
+import '../world.dart' show ClosedWorld;
 import 'nodes.dart';
 import 'types.dart';
 
@@ -660,7 +660,7 @@
     if (right.isConstantNull() || left.isPrimitiveOrNull(compiler)) {
       return newBuiltinVariant(instruction, compiler);
     }
-    World world = compiler.world;
+    ClosedWorld world = compiler.closedWorld;
     JavaScriptBackend backend = compiler.backend;
     Iterable<Element> matches =
         world.allFunctions.filter(instruction.selector, instructionType);
diff --git a/pkg/compiler/lib/src/ssa/jump_handler.dart b/pkg/compiler/lib/src/ssa/jump_handler.dart
new file mode 100644
index 0000000..a50d496
--- /dev/null
+++ b/pkg/compiler/lib/src/ssa/jump_handler.dart
@@ -0,0 +1,234 @@
+// Copyright (c) 2016, 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 '../common.dart';
+import '../elements/elements.dart';
+import '../tree/tree.dart' as ast;
+
+import 'builder.dart';
+import 'graph_builder.dart';
+import 'locals_handler.dart';
+import 'nodes.dart';
+
+/// A single break/continue instruction.
+class JumpHandlerEntry {
+  final HJump jumpInstruction;
+  final LocalsHandler locals;
+  bool isBreak() => jumpInstruction is HBreak;
+  bool isContinue() => jumpInstruction is HContinue;
+  JumpHandlerEntry(this.jumpInstruction, this.locals);
+}
+
+abstract class JumpHandler {
+  factory JumpHandler(GraphBuilder builder, JumpTarget target) {
+    return new TargetJumpHandler(builder, target);
+  }
+  void generateBreak([LabelDefinition label]);
+  void generateContinue([LabelDefinition label]);
+  void forEachBreak(void action(HBreak instruction, LocalsHandler locals));
+  void forEachContinue(
+      void action(HContinue instruction, LocalsHandler locals));
+  bool hasAnyContinue();
+  bool hasAnyBreak();
+  void close();
+  final JumpTarget target;
+  List<LabelDefinition> labels();
+}
+
+/// Jump handler used to avoid null checks when a target isn't used as the
+/// target of a break, and therefore doesn't need a break handler associated
+/// with it.
+class NullJumpHandler implements JumpHandler {
+  final DiagnosticReporter reporter;
+
+  NullJumpHandler(this.reporter);
+
+  void generateBreak([LabelDefinition label]) {
+    reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
+        'NullJumpHandler.generateBreak should not be called.');
+  }
+
+  void generateContinue([LabelDefinition label]) {
+    reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
+        'NullJumpHandler.generateContinue should not be called.');
+  }
+
+  void forEachBreak(Function ignored) {}
+  void forEachContinue(Function ignored) {}
+  void close() {}
+  bool hasAnyContinue() => false;
+  bool hasAnyBreak() => false;
+
+  List<LabelDefinition> labels() => const <LabelDefinition>[];
+  JumpTarget get target => null;
+}
+
+/// Jump handler that records breaks until a target block is available.
+///
+/// Breaks are always forward jumps. Continues in loops are implemented as
+/// breaks of the body. Continues in switches is currently not handled.
+class TargetJumpHandler implements JumpHandler {
+  final GraphBuilder builder;
+  final JumpTarget target;
+  final List<JumpHandlerEntry> jumps;
+
+  TargetJumpHandler(GraphBuilder builder, this.target)
+      : this.builder = builder,
+        jumps = <JumpHandlerEntry>[] {
+    assert(builder.jumpTargets[target] == null);
+    builder.jumpTargets[target] = this;
+  }
+
+  void generateBreak([LabelDefinition label]) {
+    HInstruction breakInstruction;
+    if (label == null) {
+      breakInstruction = new HBreak(target);
+    } else {
+      breakInstruction = new HBreak.toLabel(label);
+    }
+    LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
+    builder.close(breakInstruction);
+    jumps.add(new JumpHandlerEntry(breakInstruction, locals));
+  }
+
+  void generateContinue([LabelDefinition label]) {
+    HInstruction continueInstruction;
+    if (label == null) {
+      continueInstruction = new HContinue(target);
+    } else {
+      continueInstruction = new HContinue.toLabel(label);
+      // Switch case continue statements must be handled by the
+      // [SwitchCaseJumpHandler].
+      assert(label.target.statement is! ast.SwitchCase);
+    }
+    LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
+    builder.close(continueInstruction);
+    jumps.add(new JumpHandlerEntry(continueInstruction, locals));
+  }
+
+  void forEachBreak(Function action) {
+    for (JumpHandlerEntry entry in jumps) {
+      if (entry.isBreak()) action(entry.jumpInstruction, entry.locals);
+    }
+  }
+
+  void forEachContinue(Function action) {
+    for (JumpHandlerEntry entry in jumps) {
+      if (entry.isContinue()) action(entry.jumpInstruction, entry.locals);
+    }
+  }
+
+  bool hasAnyContinue() {
+    for (JumpHandlerEntry entry in jumps) {
+      if (entry.isContinue()) return true;
+    }
+    return false;
+  }
+
+  bool hasAnyBreak() {
+    for (JumpHandlerEntry entry in jumps) {
+      if (entry.isBreak()) return true;
+    }
+    return false;
+  }
+
+  void close() {
+    // The mapping from TargetElement to JumpHandler is no longer needed.
+    builder.jumpTargets.remove(target);
+  }
+
+  List<LabelDefinition> labels() {
+    List<LabelDefinition> result = null;
+    for (LabelDefinition element in target.labels) {
+      if (result == null) result = <LabelDefinition>[];
+      result.add(element);
+    }
+    return (result == null) ? const <LabelDefinition>[] : result;
+  }
+}
+
+/// Special [JumpHandler] implementation used to handle continue statements
+/// targeting switch cases.
+class SwitchCaseJumpHandler extends TargetJumpHandler {
+  /// Map from switch case targets to indices used to encode the flow of the
+  /// switch case loop.
+  final Map<JumpTarget, int> targetIndexMap = new Map<JumpTarget, int>();
+
+  SwitchCaseJumpHandler(
+      GraphBuilder builder, JumpTarget target, ast.SwitchStatement node)
+      : super(builder, target) {
+    // The switch case indices must match those computed in
+    // [SsaFromAstMixin.buildSwitchCaseConstants].
+    // Switch indices are 1-based so we can bypass the synthetic loop when no
+    // cases match simply by branching on the index (which defaults to null).
+    int switchIndex = 1;
+    for (ast.SwitchCase switchCase in node.cases) {
+      for (ast.Node labelOrCase in switchCase.labelsAndCases) {
+        ast.Node label = labelOrCase.asLabel();
+        if (label != null) {
+          LabelDefinition labelElement =
+              builder.elements.getLabelDefinition(label);
+          if (labelElement != null && labelElement.isContinueTarget) {
+            JumpTarget continueTarget = labelElement.target;
+            targetIndexMap[continueTarget] = switchIndex;
+            assert(builder.jumpTargets[continueTarget] == null);
+            builder.jumpTargets[continueTarget] = this;
+          }
+        }
+      }
+      switchIndex++;
+    }
+  }
+
+  void generateBreak([LabelDefinition label]) {
+    if (label == null) {
+      // Creates a special break instruction for the synthetic loop generated
+      // for a switch statement with continue statements. See
+      // [SsaFromAstMixin.buildComplexSwitchStatement] for detail.
+
+      HInstruction breakInstruction =
+          new HBreak(target, breakSwitchContinueLoop: true);
+      LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
+      builder.close(breakInstruction);
+      jumps.add(new JumpHandlerEntry(breakInstruction, locals));
+    } else {
+      super.generateBreak(label);
+    }
+  }
+
+  bool isContinueToSwitchCase(LabelDefinition label) {
+    return label != null && targetIndexMap.containsKey(label.target);
+  }
+
+  void generateContinue([LabelDefinition label]) {
+    if (isContinueToSwitchCase(label)) {
+      // Creates the special instructions 'label = i; continue l;' used in
+      // switch statements with continue statements. See
+      // [SsaFromAstMixin.buildComplexSwitchStatement] for detail.
+
+      assert(label != null);
+      // TODO(het): change the graph 'addConstantXXX' to take a ConstantSystem
+      // instead of a Compiler.
+      HInstruction value = builder.graph
+          .addConstantInt(targetIndexMap[label.target], builder.compiler);
+      builder.localsHandler.updateLocal(target, value);
+
+      assert(label.target.labels.contains(label));
+      HInstruction continueInstruction = new HContinue(target);
+      LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
+      builder.close(continueInstruction);
+      jumps.add(new JumpHandlerEntry(continueInstruction, locals));
+    } else {
+      super.generateContinue(label);
+    }
+  }
+
+  void close() {
+    // The mapping from TargetElement to JumpHandler is no longer needed.
+    for (JumpTarget target in targetIndexMap.keys) {
+      builder.jumpTargets.remove(target);
+    }
+    super.close();
+  }
+}
diff --git a/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart b/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart
index 4f31bb2..7f5b6f0 100644
--- a/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart
+++ b/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart
@@ -46,11 +46,14 @@
     for (LibraryElement libraryElement in kernel.libraries.keys) {
       _nodeToElement[kernel.libraries[libraryElement]] = libraryElement;
     }
+    for (LocalFunctionElement localFunction in kernel.localFunctions.keys) {
+      _nodeToElement[kernel.localFunctions[localFunction]] = localFunction;
+    }
     _typeConverter = new DartTypeConverter(this);
   }
 
   Compiler get _compiler => _backend.compiler;
-  TreeElements get _elements => _resolvedAst.elements;
+  TreeElements get elements => _resolvedAst.elements;
 
   ConstantValue getConstantForSymbol(ir.SymbolLiteral node) {
     ast.Node astNode = getNode(node);
@@ -74,7 +77,8 @@
   }
 
   bool getCanThrow(ir.Node procedure) {
-    return !_compiler.world.getCannotThrow(getElement(procedure));
+    FunctionElement function = getElement(procedure);
+    return !_compiler.closedWorld.getCannotThrow(function);
   }
 
   TypeMask returnTypeOf(ir.Member node) {
@@ -83,7 +87,7 @@
   }
 
   SideEffects getSideEffects(ir.Node node) {
-    return _compiler.world.getSideEffectsOfElement(getElement(node));
+    return _compiler.closedWorld.getSideEffectsOfElement(getElement(node));
   }
 
   CallStructure getCallStructure(ir.Arguments arguments) {
@@ -124,12 +128,12 @@
 
   TypeMask typeOfInvocation(ir.MethodInvocation invocation) {
     return _compiler.globalInference.results
-        .typeOfSend(getNode(invocation), _elements);
+        .typeOfSend(getNode(invocation), elements);
   }
 
   TypeMask typeOfGet(ir.PropertyGet getter) {
     return _compiler.globalInference.results
-        .typeOfSend(getNode(getter), _elements);
+        .typeOfSend(getNode(getter), elements);
   }
 
   TypeMask inferredTypeOf(ir.Member node) {
@@ -148,7 +152,7 @@
 
   ConstantValue getConstantFor(ir.Node node) {
     ConstantValue constantValue =
-        _backend.constants.getConstantValueForNode(getNode(node), _elements);
+        _backend.constants.getConstantValueForNode(getNode(node), elements);
     assert(invariant(getNode(node), constantValue != null,
         message: 'No constant computed for $node'));
     return constantValue;
@@ -164,6 +168,9 @@
     return _backend.isInterceptedSelector(selector);
   }
 
+  JumpTarget getTargetDefinition(ir.Node node) =>
+      elements.getTargetDefinition(getNode(node));
+
   ir.Procedure get mapLiteralConstructor =>
       kernel.functions[_backend.helpers.mapLiteralConstructor];
 
@@ -184,6 +191,8 @@
 
   DartTypeConverter(this.astAdapter);
 
+  DartType visitType(ir.DartType type) => type.accept(this);
+
   List<DartType> visitTypes(List<ir.DartType> types) {
     return new List.generate(
         types.length, (int index) => types[index].accept(this));
@@ -196,7 +205,16 @@
 
   @override
   DartType visitFunctionType(ir.FunctionType node) {
-    throw new UnimplementedError("Function types not currently supported");
+    return new FunctionType.synthesized(
+        visitType(node.returnType),
+        visitTypes(node.positionalParameters
+            .take(node.requiredParameterCount)
+            .toList()),
+        visitTypes(node.positionalParameters
+            .skip(node.requiredParameterCount)
+            .toList()),
+        node.namedParameters.keys.toList(),
+        visitTypes(node.namedParameters.values.toList()));
   }
 
   @override
diff --git a/pkg/compiler/lib/src/ssa/kernel_impact.dart b/pkg/compiler/lib/src/ssa/kernel_impact.dart
index 15efe23..a2f9279 100644
--- a/pkg/compiler/lib/src/ssa/kernel_impact.dart
+++ b/pkg/compiler/lib/src/ssa/kernel_impact.dart
@@ -5,6 +5,7 @@
 import 'package:kernel/ast.dart' as ir;
 
 import '../common.dart';
+import '../common/names.dart';
 import '../compiler.dart';
 import '../constants/expressions.dart';
 import '../dart_types.dart';
@@ -71,10 +72,17 @@
     return type;
   }
 
+  /// Add a checked-mode type use of return type and parameters of [node].
+  void checkFunctionTypes(ir.FunctionNode node) {
+    checkType(node.returnType);
+    node.positionalParameters.forEach((v) => checkType(v.type));
+    node.namedParameters.forEach((v) => checkType(v.type));
+  }
+
   ResolutionImpact buildField(ir.Field field) {
     checkType(field.type);
     if (field.initializer != null) {
-      field.initializer.accept(this);
+      visitNode(field.initializer);
     } else {
       impactBuilder.registerFeature(Feature.FIELD_WITHOUT_INITIALIZER);
     }
@@ -84,10 +92,8 @@
   ResolutionImpact buildProcedure(ir.Procedure procedure) {
     if (procedure.kind == ir.ProcedureKind.Method ||
         procedure.kind == ir.ProcedureKind.Operator) {
-      checkType(procedure.function.returnType);
-      procedure.function.positionalParameters.forEach((v) => checkType(v.type));
-      procedure.function.namedParameters.forEach((v) => checkType(v.type));
-      procedure.function.body.accept(this);
+      checkFunctionTypes(procedure.function);
+      visitNode(procedure.function.body);
     } else {
       compiler.reporter.internalError(
           resolvedAst.element,
@@ -97,8 +103,10 @@
     return impactBuilder;
   }
 
+  void visitNode(ir.Node node) => node?.accept(this);
+
   void visitNodes(Iterable<ir.Node> nodes) {
-    nodes.forEach((ir.Node node) => node.accept(this));
+    nodes.forEach(visitNode);
   }
 
   @override
@@ -106,19 +114,19 @@
 
   @override
   void visitExpressionStatement(ir.ExpressionStatement exprStatement) {
-    exprStatement.expression.accept(this);
+    visitNode(exprStatement.expression);
   }
 
   @override
   void visitReturnStatement(ir.ReturnStatement returnStatement) {
-    returnStatement.expression?.accept(this);
+    visitNode(returnStatement.expression);
   }
 
   @override
   void visitIfStatement(ir.IfStatement ifStatement) {
-    ifStatement.condition.accept(this);
-    ifStatement.then.accept(this);
-    ifStatement.otherwise?.accept(this);
+    visitNode(ifStatement.condition);
+    visitNode(ifStatement.then);
+    visitNode(ifStatement.otherwise);
   }
 
   @override
@@ -178,17 +186,13 @@
   }
 
   void visitMapEntry(ir.MapEntry entry) {
-    entry.key.accept(this);
-    entry.value.accept(this);
+    visitNode(entry.key);
+    visitNode(entry.value);
   }
 
   void _visitArguments(ir.Arguments arguments) {
-    for (ir.Expression argument in arguments.positional) {
-      argument.accept(this);
-    }
-    for (ir.NamedExpression argument in arguments.named) {
-      argument.value.accept(this);
-    }
+    arguments.positional.forEach(visitNode);
+    arguments.named.forEach(visitNode);
   }
 
   @override
@@ -237,45 +241,88 @@
 
   @override
   void visitStaticGet(ir.StaticGet node) {
-    Element target = astAdapter.getElement(node.target).declaration;
-    impactBuilder.registerStaticUse(new StaticUse.staticGet(target));
+    ir.Member target = node.target;
+    Element element = astAdapter.getElement(target).declaration;
+    if (target is ir.Procedure && target.kind == ir.ProcedureKind.Method) {
+      impactBuilder.registerStaticUse(new StaticUse.staticTearOff(element));
+    } else {
+      impactBuilder.registerStaticUse(new StaticUse.staticGet(element));
+    }
   }
 
   @override
   void visitMethodInvocation(ir.MethodInvocation invocation) {
-    invocation.receiver.accept(this);
+    var receiver = invocation.receiver;
+    if (receiver is ir.VariableGet &&
+        receiver.variable.isFinal &&
+        receiver.variable.parent is ir.FunctionDeclaration) {
+      // Invocation of a local function. No need for dynamic use.
+    } else {
+      visitNode(invocation.receiver);
+      impactBuilder.registerDynamicUse(
+          new DynamicUse(astAdapter.getSelector(invocation), null));
+    }
     _visitArguments(invocation.arguments);
-    impactBuilder.registerDynamicUse(
-        new DynamicUse(astAdapter.getSelector(invocation), null));
   }
 
   @override
   void visitPropertyGet(ir.PropertyGet node) {
-    node.receiver.accept(this);
+    visitNode(node.receiver);
     impactBuilder.registerDynamicUse(new DynamicUse(
         new Selector.getter(astAdapter.getName(node.name)), null));
   }
 
   @override
   void visitPropertySet(ir.PropertySet node) {
-    node.receiver.accept(this);
-    node.value.accept(this);
+    visitNode(node.receiver);
+    visitNode(node.value);
     impactBuilder.registerDynamicUse(new DynamicUse(
         new Selector.setter(astAdapter.getName(node.name)), null));
   }
 
   @override
-  void visitNot(ir.Not not) {
-    not.operand.accept(this);
-  }
-
-  @override
   void visitAssertStatement(ir.AssertStatement node) {
     impactBuilder.registerFeature(
         node.message != null ? Feature.ASSERT_WITH_MESSAGE : Feature.ASSERT);
-    node.visitChildren(this);
+    visitNode(node.condition);
+    visitNode(node.message);
   }
 
   @override
+  void visitStringConcatenation(ir.StringConcatenation node) {
+    impactBuilder.registerFeature(Feature.STRING_INTERPOLATION);
+    impactBuilder.registerFeature(Feature.STRING_JUXTAPOSITION);
+    visitNodes(node.expressions);
+  }
+
+  @override
+  void visitFunctionDeclaration(ir.FunctionDeclaration node) {
+    impactBuilder
+        .registerStaticUse(new StaticUse.closure(astAdapter.getElement(node)));
+    checkFunctionTypes(node.function);
+    visitNode(node.function.body);
+  }
+
+  @override
+  void visitFunctionExpression(ir.FunctionExpression node) {
+    impactBuilder
+        .registerStaticUse(new StaticUse.closure(astAdapter.getElement(node)));
+    checkFunctionTypes(node.function);
+    visitNode(node.function.body);
+  }
+
+  @override
+  void visitVariableDeclaration(ir.VariableDeclaration node) {
+    checkType(node.type);
+    if (node.initializer != null) {
+      visitNode(node.initializer);
+    } else {
+      impactBuilder.registerFeature(Feature.LOCAL_WITHOUT_INITIALIZER);
+    }
+  }
+
+  // TODO(johnniwinther): Make this throw and visit child nodes explicitly
+  // instead to ensure that we don't visit unwanted parts of the ir.
+  @override
   void defaultNode(ir.Node node) => node.visitChildren(this);
 }
diff --git a/pkg/compiler/lib/src/ssa/kernel_string_builder.dart b/pkg/compiler/lib/src/ssa/kernel_string_builder.dart
new file mode 100644
index 0000000..21da2e4
--- /dev/null
+++ b/pkg/compiler/lib/src/ssa/kernel_string_builder.dart
@@ -0,0 +1,75 @@
+// Copyright (c) 2016, 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:kernel/ast.dart' as ir;
+
+import '../compiler.dart';
+
+import 'builder_kernel.dart';
+import 'kernel_ast_adapter.dart';
+import 'nodes.dart';
+
+/// Visits and concatenates the expressions in a string concatenation.
+class KernelStringBuilder extends ir.Visitor {
+  final KernelSsaBuilder builder;
+  Compiler get compiler => builder.compiler;
+  KernelAstAdapter get astAdapter => builder.astAdapter;
+
+  /// The string value generated so far.
+  HInstruction result = null;
+
+  KernelStringBuilder(this.builder);
+
+  @override
+  void defaultNode(ir.Node node) {
+    compiler.reporter
+        .internalError(astAdapter.getNode(node), 'Unexpected node.');
+  }
+
+  @override
+  void defaultExpression(ir.Expression node) {
+    node.accept(builder);
+    HInstruction expression = builder.pop();
+
+    // We want to use HStringify when:
+    //   1. The value is known to be a primitive type, because it might get
+    //      constant-folded and codegen has some tricks with JavaScript
+    //      conversions.
+    //   2. The value can be primitive, because the library stringifier has
+    //      fast-path code for most primitives.
+    if (expression.canBePrimitive(compiler)) {
+      append(stringify(expression));
+      return;
+    }
+
+    // TODO(het): If toString method is guaranteed to return a string, then call
+    // it directly instead of stringify. Or, better yet, do this later in the
+    // optimization phase.
+
+    append(stringify(expression));
+  }
+
+  @override
+  void visitStringConcatenation(ir.StringConcatenation node) {
+    node.visitChildren(this);
+  }
+
+  void append(HInstruction expression) {
+    result = (result == null) ? expression : concat(result, expression);
+  }
+
+  HInstruction concat(HInstruction left, HInstruction right) {
+    HInstruction instruction =
+        new HStringConcat(left, right, builder.backend.stringType);
+    builder.add(instruction);
+    return instruction;
+  }
+
+  HInstruction stringify(HInstruction expression) {
+    HInstruction instruction =
+        new HStringify(expression, builder.backend.stringType);
+    builder.add(instruction);
+    return instruction;
+  }
+}
diff --git a/pkg/compiler/lib/src/ssa/locals_handler.dart b/pkg/compiler/lib/src/ssa/locals_handler.dart
index 581114a..2aa766c 100644
--- a/pkg/compiler/lib/src/ssa/locals_handler.dart
+++ b/pkg/compiler/lib/src/ssa/locals_handler.dart
@@ -13,7 +13,7 @@
 import '../native/native.dart' as native;
 import '../tree/tree.dart' as ast;
 import '../types/types.dart';
-import '../world.dart' show ClassWorld;
+import '../world.dart' show ClosedWorld;
 import 'builder.dart' show SyntheticLocal;
 import 'graph_builder.dart';
 import 'nodes.dart';
@@ -267,9 +267,9 @@
           new SyntheticLocal('receiver', executableContext);
       // Unlike `this`, receiver is nullable since direct calls to generative
       // constructor call the constructor with `null`.
-      ClassWorld classWorld = _compiler.world;
+      ClosedWorld closedWorld = _compiler.closedWorld;
       HParameterValue value =
-          new HParameterValue(parameter, new TypeMask.exact(cls, classWorld));
+          new HParameterValue(parameter, new TypeMask.exact(cls, closedWorld));
       builder.graph.explicitReceiverParameter = value;
       builder.graph.entry.addAtEntry(value);
     }
@@ -625,15 +625,17 @@
     if (result == null) {
       ThisLocal local = closureData.thisLocal;
       ClassElement cls = local.enclosingClass;
-      ClassWorld classWorld = _compiler.world;
-      if (classWorld.isUsedAsMixin(cls)) {
+      ClosedWorld closedWorld = _compiler.closedWorld;
+      if (closedWorld.isUsedAsMixin(cls)) {
         // If the enclosing class is used as a mixin, [:this:] can be
         // of the class that mixins the enclosing class. These two
         // classes do not have a subclass relationship, so, for
         // simplicity, we mark the type as an interface type.
-        result = new TypeMask.nonNullSubtype(cls.declaration, _compiler.world);
+        result =
+            new TypeMask.nonNullSubtype(cls.declaration, _compiler.closedWorld);
       } else {
-        result = new TypeMask.nonNullSubclass(cls.declaration, _compiler.world);
+        result = new TypeMask.nonNullSubclass(
+            cls.declaration, _compiler.closedWorld);
       }
       cachedTypeOfThis = result;
     }
diff --git a/pkg/compiler/lib/src/ssa/loop_handler.dart b/pkg/compiler/lib/src/ssa/loop_handler.dart
new file mode 100644
index 0000000..e897820
--- /dev/null
+++ b/pkg/compiler/lib/src/ssa/loop_handler.dart
@@ -0,0 +1,414 @@
+// Copyright (c) 2016, 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:kernel/ast.dart' as ir;
+
+import '../elements/elements.dart';
+import '../io/source_information.dart';
+import '../tree/tree.dart' as ast;
+
+import 'builder.dart';
+import 'builder_kernel.dart';
+import 'graph_builder.dart';
+import 'jump_handler.dart';
+import 'kernel_ast_adapter.dart';
+import 'locals_handler.dart';
+import 'nodes.dart';
+
+/// Builds the SSA graph for loop nodes.
+abstract class LoopHandler<T> {
+  final GraphBuilder builder;
+
+  LoopHandler(this.builder);
+
+  /// Builds a graph for the given [loop] node.
+  ///
+  /// For while loops, [initialize] and [update] are null.
+  /// The [condition] function must return a boolean result.
+  /// None of the functions must leave anything on the stack.
+  void handleLoop(T loop, void initialize(), HInstruction condition(),
+      void update(), void body()) {
+    // Generate:
+    //  <initializer>
+    //  loop-entry:
+    //    if (!<condition>) goto loop-exit;
+    //    <body>
+    //    <updates>
+    //    goto loop-entry;
+    //  loop-exit:
+
+    builder.localsHandler.startLoop(getNode(loop));
+
+    // The initializer.
+    SubExpression initializerGraph = null;
+    HBasicBlock startBlock;
+    if (initialize != null) {
+      HBasicBlock initializerBlock = builder.openNewBlock();
+      startBlock = initializerBlock;
+      initialize();
+      assert(!builder.isAborted());
+      initializerGraph = new SubExpression(initializerBlock, builder.current);
+    }
+
+    builder.loopDepth++;
+    JumpHandler jumpHandler = beginLoopHeader(loop);
+    HLoopInformation loopInfo = builder.current.loopInformation;
+    HBasicBlock conditionBlock = builder.current;
+    if (startBlock == null) startBlock = conditionBlock;
+
+    HInstruction conditionInstruction = condition();
+    HBasicBlock conditionEndBlock =
+        builder.close(new HLoopBranch(conditionInstruction));
+    SubExpression conditionExpression =
+        new SubExpression(conditionBlock, conditionEndBlock);
+
+    // Save the values of the local variables at the end of the condition
+    // block.  These are the values that will flow to the loop exit if the
+    // condition fails.
+    LocalsHandler savedLocals = new LocalsHandler.from(builder.localsHandler);
+
+    // The body.
+    HBasicBlock beginBodyBlock = builder.addNewBlock();
+    conditionEndBlock.addSuccessor(beginBodyBlock);
+    builder.open(beginBodyBlock);
+
+    builder.localsHandler.enterLoopBody(getNode(loop));
+    body();
+
+    SubGraph bodyGraph = new SubGraph(beginBodyBlock, builder.lastOpenedBlock);
+    HBasicBlock bodyBlock = builder.current;
+    if (builder.current != null) builder.close(new HGoto());
+
+    SubExpression updateGraph;
+
+    bool loopIsDegenerate = !jumpHandler.hasAnyContinue() && bodyBlock == null;
+    if (!loopIsDegenerate) {
+      // Update.
+      // We create an update block, even when we are in a while loop. There the
+      // update block is the jump-target for continue statements. We could avoid
+      // the creation if there is no continue, but for now we always create it.
+      HBasicBlock updateBlock = builder.addNewBlock();
+
+      List<LocalsHandler> continueHandlers = <LocalsHandler>[];
+      jumpHandler
+          .forEachContinue((HContinue instruction, LocalsHandler locals) {
+        instruction.block.addSuccessor(updateBlock);
+        continueHandlers.add(locals);
+      });
+
+      if (bodyBlock != null) {
+        continueHandlers.add(builder.localsHandler);
+        bodyBlock.addSuccessor(updateBlock);
+      }
+
+      builder.open(updateBlock);
+      builder.localsHandler =
+          continueHandlers[0].mergeMultiple(continueHandlers, updateBlock);
+
+      List<LabelDefinition> labels = jumpHandler.labels();
+      JumpTarget target = getTargetDefinition(loop);
+      if (!labels.isEmpty) {
+        beginBodyBlock.setBlockFlow(
+            new HLabeledBlockInformation(
+                new HSubGraphBlockInformation(bodyGraph), jumpHandler.labels(),
+                isContinue: true),
+            updateBlock);
+      } else if (target != null && target.isContinueTarget) {
+        beginBodyBlock.setBlockFlow(
+            new HLabeledBlockInformation.implicit(
+                new HSubGraphBlockInformation(bodyGraph), target,
+                isContinue: true),
+            updateBlock);
+      }
+
+      builder.localsHandler.enterLoopUpdates(getNode(loop));
+
+      update();
+
+      HBasicBlock updateEndBlock = builder.close(new HGoto());
+      // The back-edge completing the cycle.
+      updateEndBlock.addSuccessor(conditionBlock);
+      updateGraph = new SubExpression(updateBlock, updateEndBlock);
+
+      // Avoid a critical edge from the condition to the loop-exit body.
+      HBasicBlock conditionExitBlock = builder.addNewBlock();
+      builder.open(conditionExitBlock);
+      builder.close(new HGoto());
+      conditionEndBlock.addSuccessor(conditionExitBlock);
+
+      endLoop(conditionBlock, conditionExitBlock, jumpHandler, savedLocals);
+
+      conditionBlock.postProcessLoopHeader();
+      HLoopBlockInformation info = new HLoopBlockInformation(
+          loopKind(loop),
+          builder.wrapExpressionGraph(initializerGraph),
+          builder.wrapExpressionGraph(conditionExpression),
+          builder.wrapStatementGraph(bodyGraph),
+          builder.wrapExpressionGraph(updateGraph),
+          conditionBlock.loopInformation.target,
+          conditionBlock.loopInformation.labels,
+          loopSourceInformation(loop));
+
+      startBlock.setBlockFlow(info, builder.current);
+      loopInfo.loopBlockInformation = info;
+    } else {
+      // The body of the for/while loop always aborts, so there is no back edge.
+      // We turn the code into:
+      // if (condition) {
+      //   body;
+      // } else {
+      //   // We always create an empty else block to avoid critical edges.
+      // }
+      //
+      // If there is any break in the body, we attach a synthetic
+      // label to the if.
+      HBasicBlock elseBlock = builder.addNewBlock();
+      builder.open(elseBlock);
+      builder.close(new HGoto());
+      // Pass the elseBlock as the branchBlock, because that's the block we go
+      // to just before leaving the 'loop'.
+      endLoop(conditionBlock, elseBlock, jumpHandler, savedLocals);
+
+      SubGraph elseGraph = new SubGraph(elseBlock, elseBlock);
+      // Remove the loop information attached to the header.
+      conditionBlock.loopInformation = null;
+
+      // Remove the [HLoopBranch] instruction and replace it with
+      // [HIf].
+      HInstruction condition = conditionEndBlock.last.inputs[0];
+      conditionEndBlock.addAtExit(new HIf(condition));
+      conditionEndBlock.addSuccessor(elseBlock);
+      conditionEndBlock.remove(conditionEndBlock.last);
+      HIfBlockInformation info = new HIfBlockInformation(
+          builder.wrapExpressionGraph(conditionExpression),
+          builder.wrapStatementGraph(bodyGraph),
+          builder.wrapStatementGraph(elseGraph));
+
+      conditionEndBlock.setBlockFlow(info, builder.current);
+      HIf ifBlock = conditionEndBlock.last;
+      ifBlock.blockInformation = conditionEndBlock.blockFlow;
+
+      // If the body has any break, attach a synthesized label to the
+      // if block.
+      if (jumpHandler.hasAnyBreak()) {
+        JumpTarget target = getTargetDefinition(loop);
+        LabelDefinition label = target.addLabel(null, 'loop');
+        label.setBreakTarget();
+        SubGraph labelGraph = new SubGraph(conditionBlock, builder.current);
+        HLabeledBlockInformation labelInfo = new HLabeledBlockInformation(
+            new HSubGraphBlockInformation(labelGraph),
+            <LabelDefinition>[label]);
+
+        conditionBlock.setBlockFlow(labelInfo, builder.current);
+
+        jumpHandler.forEachBreak((HBreak breakInstruction, _) {
+          HBasicBlock block = breakInstruction.block;
+          block.addAtExit(new HBreak.toLabel(label));
+          block.remove(breakInstruction);
+        });
+      }
+    }
+    jumpHandler.close();
+    builder.loopDepth--;
+  }
+
+  /// Creates a new loop-header block. The previous [current] block
+  /// is closed with an [HGoto] and replaced by the newly created block.
+  /// Also notifies the locals handler that we're entering a loop.
+  JumpHandler beginLoopHeader(T node) {
+    assert(!builder.isAborted());
+    HBasicBlock previousBlock = builder.close(new HGoto());
+
+    JumpHandler jumpHandler = createJumpHandler(node, isLoopJump: true);
+    HBasicBlock loopEntry = builder.graph
+        .addNewLoopHeaderBlock(jumpHandler.target, jumpHandler.labels());
+    previousBlock.addSuccessor(loopEntry);
+    builder.open(loopEntry);
+
+    builder.localsHandler.beginLoopHeader(loopEntry);
+    return jumpHandler;
+  }
+
+  /// Ends the loop.
+  ///
+  /// It does this by:
+  /// - creating a new block and adding it as successor to the [branchExitBlock]
+  ///   and any blocks that end in break.
+  /// - opening the new block (setting as [current]).
+  /// - notifying the locals handler that we're exiting a loop.
+  ///
+  /// [savedLocals] are the locals from the end of the loop condition.
+  ///
+  /// [branchExitBlock] is the exit (branching) block of the condition.
+  /// Generally this is not the top of the loop, since this would lead to
+  /// critical edges. It is null for degenerate do-while loops that have no back
+  /// edge because they abort (throw/return/break in the body and have no
+  /// continues).
+  void endLoop(HBasicBlock loopEntry, HBasicBlock branchExitBlock,
+      JumpHandler jumpHandler, LocalsHandler savedLocals) {
+    HBasicBlock loopExitBlock = builder.addNewBlock();
+
+    List<LocalsHandler> breakHandlers = <LocalsHandler>[];
+    // Collect data for the successors and the phis at each break.
+    jumpHandler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) {
+      breakInstruction.block.addSuccessor(loopExitBlock);
+      breakHandlers.add(locals);
+    });
+
+    // The exit block is a successor of the loop condition if it is reached.
+    // We don't add the successor in the case of a while/for loop that aborts
+    // because the caller of endLoop will be wiring up a special empty else
+    // block instead.
+    if (branchExitBlock != null) {
+      branchExitBlock.addSuccessor(loopExitBlock);
+    }
+    // Update the phis at the loop entry with the current values of locals.
+    builder.localsHandler.endLoop(loopEntry);
+
+    // Start generating code for the exit block.
+    builder.open(loopExitBlock);
+
+    // Create a new localsHandler for the loopExitBlock with the correct phis.
+    if (!breakHandlers.isEmpty) {
+      if (branchExitBlock != null) {
+        // Add the values of the locals at the end of the condition block to
+        // the phis.  These are the values that flow to the exit if the
+        // condition fails.
+        breakHandlers.add(savedLocals);
+      }
+      builder.localsHandler =
+          savedLocals.mergeMultiple(breakHandlers, loopExitBlock);
+    } else {
+      builder.localsHandler = savedLocals;
+    }
+  }
+
+  /// Returns the jump target defined by [node].
+  JumpTarget getTargetDefinition(T node);
+
+  /// Returns the corresponding AST node for [node].
+  ast.Node getNode(T node);
+
+  /// Determine what kind of loop [node] represents.
+  ///
+  /// The result is one of the kinds defined in [HLoopBlockInformation].
+  int loopKind(T node);
+
+  /// Returns the source information for the loop [node].
+  SourceInformation loopSourceInformation(T node);
+
+  /// Creates a [JumpHandler] for a statement. The node must be a jump
+  /// target. If there are no breaks or continues targeting the statement,
+  /// a special "null handler" is returned.
+  ///
+  /// [isLoopJump] is [:true:] when the jump handler is for a loop. This is used
+  /// to distinguish the synthesized loop created for a switch statement with
+  /// continue statements from simple switch statements.
+  JumpHandler createJumpHandler(T node, {bool isLoopJump});
+}
+
+/// A loop handler for the builder that just uses AST nodes directly.
+class SsaLoopHandler extends LoopHandler<ast.Node> {
+  final SsaBuilder builder;
+
+  SsaLoopHandler(SsaBuilder builder)
+      : this.builder = builder,
+        super(builder);
+
+  @override
+  JumpTarget getTargetDefinition(ast.Node node) {
+    return builder.elements.getTargetDefinition(node);
+  }
+
+  @override
+  ast.Node getNode(ast.Node node) => node;
+
+  @override
+  int loopKind(ast.Node node) => node.accept(const _SsaLoopTypeVisitor());
+
+  @override
+  SourceInformation loopSourceInformation(ast.Node node) =>
+      builder.sourceInformationBuilder.buildLoop(node);
+
+  @override
+  JumpHandler createJumpHandler(ast.Node node, {bool isLoopJump}) =>
+      builder.createJumpHandler(node, isLoopJump: isLoopJump);
+}
+
+class _SsaLoopTypeVisitor extends ast.Visitor {
+  const _SsaLoopTypeVisitor();
+  int visitNode(ast.Node node) => HLoopBlockInformation.NOT_A_LOOP;
+  int visitWhile(ast.While node) => HLoopBlockInformation.WHILE_LOOP;
+  int visitFor(ast.For node) => HLoopBlockInformation.FOR_LOOP;
+  int visitDoWhile(ast.DoWhile node) => HLoopBlockInformation.DO_WHILE_LOOP;
+  int visitAsyncForIn(ast.AsyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP;
+  int visitSyncForIn(ast.SyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP;
+  int visitSwitchStatement(ast.SwitchStatement node) =>
+      HLoopBlockInformation.SWITCH_CONTINUE_LOOP;
+}
+
+// TODO(het): Since kernel simplifies loop breaks and continues, we should
+// rewrite the loop handler from scratch to account for the simplified structure
+class KernelLoopHandler extends LoopHandler<ir.Node> {
+  final KernelSsaBuilder builder;
+
+  KernelAstAdapter get astAdapter => builder.astAdapter;
+
+  KernelLoopHandler(KernelSsaBuilder builder)
+      : this.builder = builder,
+        super(builder);
+
+  @override
+  JumpHandler createJumpHandler(ir.Node node, {bool isLoopJump}) {
+    JumpTarget element = getTargetDefinition(node);
+    if (element == null || !identical(element.statement, node)) {
+      // No breaks or continues to this node.
+      return new NullJumpHandler(builder.compiler.reporter);
+    }
+    if (isLoopJump && node is ast.SwitchStatement) {
+      // Create a special jump handler for loops created for switch statements
+      // with continue statements.
+      return new SwitchCaseJumpHandler(builder, element, getNode(node));
+    }
+    return new JumpHandler(builder, element);
+  }
+
+  @override
+  ast.Node getNode(ir.Node node) => astAdapter.getNode(node);
+
+  @override
+  JumpTarget getTargetDefinition(ir.Node node) =>
+      astAdapter.getTargetDefinition(node);
+
+  @override
+  int loopKind(ir.Node node) => node.accept(new _KernelLoopTypeVisitor());
+
+  // TODO(het): return the actual source information
+  @override
+  SourceInformation loopSourceInformation(ir.Node node) => null;
+}
+
+class _KernelLoopTypeVisitor extends ir.Visitor<int> {
+  @override
+  int defaultNode(ir.Node node) => HLoopBlockInformation.NOT_A_LOOP;
+
+  @override
+  int visitWhileStatement(ir.WhileStatement node) =>
+      HLoopBlockInformation.WHILE_LOOP;
+
+  @override
+  int visitForStatement(ir.ForStatement node) => HLoopBlockInformation.FOR_LOOP;
+
+  @override
+  int visitDoStatement(ir.DoStatement node) =>
+      HLoopBlockInformation.DO_WHILE_LOOP;
+
+  @override
+  int visitForInStatement(ir.ForInStatement node) =>
+      HLoopBlockInformation.FOR_IN_LOOP;
+
+  @override
+  int visitSwitchStatement(ir.SwitchStatement node) =>
+      HLoopBlockInformation.SWITCH_CONTINUE_LOOP;
+}
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index e3342cd..ddeaf26 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -20,7 +20,7 @@
 import '../universe/selector.dart' show Selector;
 import '../universe/side_effects.dart' show SideEffects;
 import '../util/util.dart';
-import '../world.dart' show ClassWorld;
+import '../world.dart' show ClosedWorld;
 import 'invoke_dynamic_specializers.dart';
 import 'validate.dart';
 
@@ -926,20 +926,22 @@
 
   /// Returns `true` if [typeMask] contains [cls].
   static bool containsType(
-      TypeMask typeMask, ClassElement cls, ClassWorld classWorld) {
-    return classWorld.isInstantiated(cls) && typeMask.contains(cls, classWorld);
+      TypeMask typeMask, ClassElement cls, ClosedWorld closedWorld) {
+    return closedWorld.isInstantiated(cls) &&
+        typeMask.contains(cls, closedWorld);
   }
 
   /// Returns `true` if [typeMask] contains only [cls].
   static bool containsOnlyType(
-      TypeMask typeMask, ClassElement cls, ClassWorld classWorld) {
-    return classWorld.isInstantiated(cls) && typeMask.containsOnly(cls);
+      TypeMask typeMask, ClassElement cls, ClosedWorld closedWorld) {
+    return closedWorld.isInstantiated(cls) && typeMask.containsOnly(cls);
   }
 
   /// Returns `true` if [typeMask] is an instance of [cls].
   static bool isInstanceOf(
-      TypeMask typeMask, ClassElement cls, ClassWorld classWorld) {
-    return classWorld.isImplemented(cls) && typeMask.satisfies(cls, classWorld);
+      TypeMask typeMask, ClassElement cls, ClosedWorld closedWorld) {
+    return closedWorld.isImplemented(cls) &&
+        typeMask.satisfies(cls, closedWorld);
   }
 
   bool canBePrimitive(Compiler compiler) {
@@ -951,182 +953,183 @@
   }
 
   bool canBePrimitiveNumber(Compiler compiler) {
-    ClassWorld classWorld = compiler.world;
+    ClosedWorld closedWorld = compiler.closedWorld;
     JavaScriptBackend backend = compiler.backend;
     BackendHelpers helpers = backend.helpers;
     // TODO(sra): It should be possible to test only jsDoubleClass and
     // jsUInt31Class, since all others are superclasses of these two.
-    return containsType(instructionType, helpers.jsNumberClass, classWorld) ||
-        containsType(instructionType, helpers.jsIntClass, classWorld) ||
-        containsType(instructionType, helpers.jsPositiveIntClass, classWorld) ||
-        containsType(instructionType, helpers.jsUInt32Class, classWorld) ||
-        containsType(instructionType, helpers.jsUInt31Class, classWorld) ||
-        containsType(instructionType, helpers.jsDoubleClass, classWorld);
+    return containsType(instructionType, helpers.jsNumberClass, closedWorld) ||
+        containsType(instructionType, helpers.jsIntClass, closedWorld) ||
+        containsType(
+            instructionType, helpers.jsPositiveIntClass, closedWorld) ||
+        containsType(instructionType, helpers.jsUInt32Class, closedWorld) ||
+        containsType(instructionType, helpers.jsUInt31Class, closedWorld) ||
+        containsType(instructionType, helpers.jsDoubleClass, closedWorld);
   }
 
   bool canBePrimitiveBoolean(Compiler compiler) {
-    ClassWorld classWorld = compiler.world;
+    ClosedWorld closedWorld = compiler.closedWorld;
     JavaScriptBackend backend = compiler.backend;
     BackendHelpers helpers = backend.helpers;
-    return containsType(instructionType, helpers.jsBoolClass, classWorld);
+    return containsType(instructionType, helpers.jsBoolClass, closedWorld);
   }
 
   bool canBePrimitiveArray(Compiler compiler) {
-    ClassWorld classWorld = compiler.world;
+    ClosedWorld closedWorld = compiler.closedWorld;
     JavaScriptBackend backend = compiler.backend;
     BackendHelpers helpers = backend.helpers;
-    return containsType(instructionType, helpers.jsArrayClass, classWorld) ||
-        containsType(instructionType, helpers.jsFixedArrayClass, classWorld) ||
+    return containsType(instructionType, helpers.jsArrayClass, closedWorld) ||
+        containsType(instructionType, helpers.jsFixedArrayClass, closedWorld) ||
         containsType(
-            instructionType, helpers.jsExtendableArrayClass, classWorld) ||
+            instructionType, helpers.jsExtendableArrayClass, closedWorld) ||
         containsType(
-            instructionType, helpers.jsUnmodifiableArrayClass, classWorld);
+            instructionType, helpers.jsUnmodifiableArrayClass, closedWorld);
   }
 
   bool isIndexablePrimitive(Compiler compiler) {
-    ClassWorld classWorld = compiler.world;
+    ClosedWorld closedWorld = compiler.closedWorld;
     JavaScriptBackend backend = compiler.backend;
     BackendHelpers helpers = backend.helpers;
-    return instructionType.containsOnlyString(classWorld) ||
-        isInstanceOf(instructionType, helpers.jsIndexableClass, classWorld);
+    return instructionType.containsOnlyString(closedWorld) ||
+        isInstanceOf(instructionType, helpers.jsIndexableClass, closedWorld);
   }
 
   bool isFixedArray(Compiler compiler) {
-    ClassWorld classWorld = compiler.world;
+    ClosedWorld closedWorld = compiler.closedWorld;
     JavaScriptBackend backend = compiler.backend;
     BackendHelpers helpers = backend.helpers;
     // TODO(sra): Recognize the union of these types as well.
     return containsOnlyType(
-            instructionType, helpers.jsFixedArrayClass, classWorld) ||
+            instructionType, helpers.jsFixedArrayClass, closedWorld) ||
         containsOnlyType(
-            instructionType, helpers.jsUnmodifiableArrayClass, classWorld);
+            instructionType, helpers.jsUnmodifiableArrayClass, closedWorld);
   }
 
   bool isExtendableArray(Compiler compiler) {
-    ClassWorld classWorld = compiler.world;
+    ClosedWorld closedWorld = compiler.closedWorld;
     JavaScriptBackend backend = compiler.backend;
     BackendHelpers helpers = backend.helpers;
     return containsOnlyType(
-        instructionType, helpers.jsExtendableArrayClass, classWorld);
+        instructionType, helpers.jsExtendableArrayClass, closedWorld);
   }
 
   bool isMutableArray(Compiler compiler) {
-    ClassWorld classWorld = compiler.world;
+    ClosedWorld closedWorld = compiler.closedWorld;
     JavaScriptBackend backend = compiler.backend;
     BackendHelpers helpers = backend.helpers;
     return isInstanceOf(
-        instructionType, helpers.jsMutableArrayClass, classWorld);
+        instructionType, helpers.jsMutableArrayClass, closedWorld);
   }
 
   bool isReadableArray(Compiler compiler) {
-    ClassWorld classWorld = compiler.world;
+    ClosedWorld closedWorld = compiler.closedWorld;
     JavaScriptBackend backend = compiler.backend;
     BackendHelpers helpers = backend.helpers;
-    return isInstanceOf(instructionType, helpers.jsArrayClass, classWorld);
+    return isInstanceOf(instructionType, helpers.jsArrayClass, closedWorld);
   }
 
   bool isMutableIndexable(Compiler compiler) {
-    ClassWorld classWorld = compiler.world;
+    ClosedWorld closedWorld = compiler.closedWorld;
     JavaScriptBackend backend = compiler.backend;
     BackendHelpers helpers = backend.helpers;
     return isInstanceOf(
-        instructionType, helpers.jsMutableIndexableClass, classWorld);
+        instructionType, helpers.jsMutableIndexableClass, closedWorld);
   }
 
   bool isArray(Compiler compiler) => isReadableArray(compiler);
 
   bool canBePrimitiveString(Compiler compiler) {
-    ClassWorld classWorld = compiler.world;
+    ClosedWorld closedWorld = compiler.closedWorld;
     JavaScriptBackend backend = compiler.backend;
     BackendHelpers helpers = backend.helpers;
-    return containsType(instructionType, helpers.jsStringClass, classWorld);
+    return containsType(instructionType, helpers.jsStringClass, closedWorld);
   }
 
   bool isInteger(Compiler compiler) {
-    ClassWorld classWorld = compiler.world;
-    return instructionType.containsOnlyInt(classWorld) &&
+    ClosedWorld closedWorld = compiler.closedWorld;
+    return instructionType.containsOnlyInt(closedWorld) &&
         !instructionType.isNullable;
   }
 
   bool isUInt32(Compiler compiler) {
-    ClassWorld classWorld = compiler.world;
+    ClosedWorld closedWorld = compiler.closedWorld;
     JavaScriptBackend backend = compiler.backend;
     BackendHelpers helpers = backend.helpers;
     return !instructionType.isNullable &&
-        isInstanceOf(instructionType, helpers.jsUInt32Class, classWorld);
+        isInstanceOf(instructionType, helpers.jsUInt32Class, closedWorld);
   }
 
   bool isUInt31(Compiler compiler) {
-    ClassWorld classWorld = compiler.world;
+    ClosedWorld closedWorld = compiler.closedWorld;
     JavaScriptBackend backend = compiler.backend;
     BackendHelpers helpers = backend.helpers;
     return !instructionType.isNullable &&
-        isInstanceOf(instructionType, helpers.jsUInt31Class, classWorld);
+        isInstanceOf(instructionType, helpers.jsUInt31Class, closedWorld);
   }
 
   bool isPositiveInteger(Compiler compiler) {
-    ClassWorld classWorld = compiler.world;
+    ClosedWorld closedWorld = compiler.closedWorld;
     JavaScriptBackend backend = compiler.backend;
     BackendHelpers helpers = backend.helpers;
     return !instructionType.isNullable &&
-        isInstanceOf(instructionType, helpers.jsPositiveIntClass, classWorld);
+        isInstanceOf(instructionType, helpers.jsPositiveIntClass, closedWorld);
   }
 
   bool isPositiveIntegerOrNull(Compiler compiler) {
-    ClassWorld classWorld = compiler.world;
+    ClosedWorld closedWorld = compiler.closedWorld;
     JavaScriptBackend backend = compiler.backend;
     BackendHelpers helpers = backend.helpers;
     return isInstanceOf(
-        instructionType, helpers.jsPositiveIntClass, classWorld);
+        instructionType, helpers.jsPositiveIntClass, closedWorld);
   }
 
   bool isIntegerOrNull(Compiler compiler) {
-    ClassWorld classWorld = compiler.world;
-    return instructionType.containsOnlyInt(classWorld);
+    ClosedWorld closedWorld = compiler.closedWorld;
+    return instructionType.containsOnlyInt(closedWorld);
   }
 
   bool isNumber(Compiler compiler) {
-    ClassWorld classWorld = compiler.world;
-    return instructionType.containsOnlyNum(classWorld) &&
+    ClosedWorld closedWorld = compiler.closedWorld;
+    return instructionType.containsOnlyNum(closedWorld) &&
         !instructionType.isNullable;
   }
 
   bool isNumberOrNull(Compiler compiler) {
-    ClassWorld classWorld = compiler.world;
-    return instructionType.containsOnlyNum(classWorld);
+    ClosedWorld closedWorld = compiler.closedWorld;
+    return instructionType.containsOnlyNum(closedWorld);
   }
 
   bool isDouble(Compiler compiler) {
-    ClassWorld classWorld = compiler.world;
-    return instructionType.containsOnlyDouble(classWorld) &&
+    ClosedWorld closedWorld = compiler.closedWorld;
+    return instructionType.containsOnlyDouble(closedWorld) &&
         !instructionType.isNullable;
   }
 
   bool isDoubleOrNull(Compiler compiler) {
-    ClassWorld classWorld = compiler.world;
-    return instructionType.containsOnlyDouble(classWorld);
+    ClosedWorld closedWorld = compiler.closedWorld;
+    return instructionType.containsOnlyDouble(closedWorld);
   }
 
   bool isBoolean(Compiler compiler) {
-    ClassWorld classWorld = compiler.world;
-    return instructionType.containsOnlyBool(classWorld) &&
+    ClosedWorld closedWorld = compiler.closedWorld;
+    return instructionType.containsOnlyBool(closedWorld) &&
         !instructionType.isNullable;
   }
 
   bool isBooleanOrNull(Compiler compiler) {
-    ClassWorld classWorld = compiler.world;
-    return instructionType.containsOnlyBool(classWorld);
+    ClosedWorld closedWorld = compiler.closedWorld;
+    return instructionType.containsOnlyBool(closedWorld);
   }
 
   bool isString(Compiler compiler) {
-    ClassWorld classWorld = compiler.world;
-    return instructionType.containsOnlyString(classWorld) &&
+    ClosedWorld closedWorld = compiler.closedWorld;
+    return instructionType.containsOnlyString(closedWorld) &&
         !instructionType.isNullable;
   }
 
   bool isStringOrNull(Compiler compiler) {
-    ClassWorld classWorld = compiler.world;
-    return instructionType.containsOnlyString(classWorld);
+    ClosedWorld closedWorld = compiler.closedWorld;
+    return instructionType.containsOnlyString(closedWorld);
   }
 
   bool isPrimitive(Compiler compiler) {
@@ -1378,7 +1381,7 @@
       throw 'creating compound check to $type (this = ${this})';
     } else {
       TypeMask subtype =
-          new TypeMask.subtype(element.declaration, compiler.world);
+          new TypeMask.subtype(element.declaration, compiler.closedWorld);
       return new HTypeConversion(type, kind, subtype, this);
     }
   }
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index 3ac8e27..627e7195 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
+import '../common/names.dart' show Selectors;
 import '../common/tasks.dart' show CompilerTask;
 import '../compiler.dart' show Compiler;
 import '../constants/constant_system.dart';
@@ -19,7 +20,7 @@
 import '../universe/selector.dart' show Selector;
 import '../universe/side_effects.dart' show SideEffects;
 import '../util/util.dart';
-import '../world.dart' show ClassWorld, World;
+import '../world.dart' show ClosedWorld;
 import 'interceptor_simplifier.dart';
 import 'nodes.dart';
 import 'types.dart';
@@ -126,7 +127,7 @@
 /// of identifying gvn-able lengths and mis-identifies some unions of fixed
 /// length indexables (see TODO) as not fixed length.
 bool isFixedLength(mask, Compiler compiler) {
-  ClassWorld classWorld = compiler.world;
+  ClosedWorld closedWorld = compiler.closedWorld;
   JavaScriptBackend backend = compiler.backend;
   if (mask.isContainer && mask.length != null) {
     // A container on which we have inferred the length.
@@ -135,7 +136,7 @@
   // TODO(sra): Recognize any combination of fixed length indexables.
   if (mask.containsOnly(backend.helpers.jsFixedArrayClass) ||
       mask.containsOnly(backend.helpers.jsUnmodifiableArrayClass) ||
-      mask.containsOnlyString(classWorld) ||
+      mask.containsOnlyString(closedWorld) ||
       backend.isTypedArray(mask)) {
     return true;
   }
@@ -191,7 +192,7 @@
           // If we can replace [instruction] with [replacement], then
           // [replacement]'s type can be narrowed.
           TypeMask newType = replacement.instructionType
-              .intersection(instruction.instructionType, compiler.world);
+              .intersection(instruction.instructionType, compiler.closedWorld);
           replacement.instructionType = newType;
         }
 
@@ -284,7 +285,7 @@
 
     // All values that cannot be 'true' are boolified to false.
     TypeMask mask = input.instructionType;
-    if (!mask.contains(helpers.jsBoolClass, compiler.world)) {
+    if (!mask.contains(helpers.jsBoolClass, compiler.closedWorld)) {
       return graph.addConstantBool(false, compiler);
     }
     return node;
@@ -334,14 +335,14 @@
       Element element = helpers.jsIndexableLength;
       bool isFixed = isFixedLength(actualReceiver.instructionType, compiler);
       TypeMask actualType = node.instructionType;
-      ClassWorld classWorld = compiler.world;
+      ClosedWorld closedWorld = compiler.closedWorld;
       TypeMask resultType = backend.positiveIntType;
       // If we already have computed a more specific type, keep that type.
       if (HInstruction.isInstanceOf(
-          actualType, helpers.jsUInt31Class, classWorld)) {
+          actualType, helpers.jsUInt31Class, closedWorld)) {
         resultType = backend.uint31Type;
       } else if (HInstruction.isInstanceOf(
-          actualType, helpers.jsUInt32Class, classWorld)) {
+          actualType, helpers.jsUInt32Class, closedWorld)) {
         resultType = backend.uint32Type;
       }
       HFieldGet result = new HFieldGet(element, actualReceiver, resultType,
@@ -374,10 +375,10 @@
     TypeMask mask = node.mask;
     HInstruction input = node.inputs[1];
 
-    World world = compiler.world;
+    ClosedWorld world = compiler.closedWorld;
 
     bool applies(Element element) {
-      return selector.applies(element, world) &&
+      return selector.applies(element, backend) &&
           (mask == null || mask.canHit(element, selector, world));
     }
 
@@ -426,7 +427,7 @@
         return result;
       }
     } else if (selector.isGetter) {
-      if (selector.applies(helpers.jsIndexableLength, world)) {
+      if (selector.applies(helpers.jsIndexableLength, backend)) {
         HInstruction optimized = tryOptimizeLengthInterceptedGetter(node);
         if (optimized != null) return optimized;
       }
@@ -444,7 +445,7 @@
 
     TypeMask receiverType = node.getDartReceiver(compiler).instructionType;
     Element element =
-        compiler.world.locateSingleElement(node.selector, receiverType);
+        compiler.closedWorld.locateSingleElement(node.selector, receiverType);
     // TODO(ngeoffray): Also fold if it's a getter or variable.
     if (element != null &&
         element.isFunction
@@ -643,7 +644,7 @@
     // Intersection of int and double return conflicting, so
     // we don't optimize on numbers to preserve the runtime semantics.
     if (!(left.isNumberOrNull(compiler) && right.isNumberOrNull(compiler))) {
-      if (leftType.isDisjoint(rightType, compiler.world)) {
+      if (leftType.isDisjoint(rightType, compiler.closedWorld)) {
         return makeFalse();
       }
     }
@@ -734,7 +735,7 @@
       return graph.addConstantBool(true, compiler);
     }
 
-    ClassWorld classWorld = compiler.world;
+    ClosedWorld closedWorld = compiler.closedWorld;
     HInstruction expression = node.expression;
     if (expression.isInteger(compiler)) {
       if (element == coreClasses.intClass ||
@@ -778,13 +779,13 @@
       // raw type.
     } else if (!RuntimeTypes.hasTypeArguments(type)) {
       TypeMask expressionMask = expression.instructionType;
-      assert(TypeMask.assertIsNormalized(expressionMask, classWorld));
+      assert(TypeMask.assertIsNormalized(expressionMask, closedWorld));
       TypeMask typeMask = (element == coreClasses.nullClass)
-          ? new TypeMask.subtype(element, classWorld)
-          : new TypeMask.nonNullSubtype(element, classWorld);
-      if (expressionMask.union(typeMask, classWorld) == typeMask) {
+          ? new TypeMask.subtype(element, closedWorld)
+          : new TypeMask.nonNullSubtype(element, closedWorld);
+      if (expressionMask.union(typeMask, closedWorld) == typeMask) {
         return graph.addConstantBool(true, compiler);
-      } else if (expressionMask.isDisjoint(typeMask, compiler.world)) {
+      } else if (expressionMask.isDisjoint(typeMask, compiler.closedWorld)) {
         return graph.addConstantBool(false, compiler);
       }
     }
@@ -815,11 +816,11 @@
   }
 
   HInstruction removeIfCheckAlwaysSucceeds(HCheck node, TypeMask checkedType) {
-    ClassWorld classWorld = compiler.world;
-    if (checkedType.containsAll(classWorld)) return node;
+    ClosedWorld closedWorld = compiler.closedWorld;
+    if (checkedType.containsAll(closedWorld)) return node;
     HInstruction input = node.checkedInput;
     TypeMask inputType = input.instructionType;
-    return inputType.isInMask(checkedType, classWorld) ? input : node;
+    return inputType.isInMask(checkedType, closedWorld) ? input : node;
   }
 
   HInstruction removeCheck(HCheck node) => node.checkedInput;
@@ -827,7 +828,7 @@
   VariableElement findConcreteFieldForDynamicAccess(
       HInstruction receiver, Selector selector) {
     TypeMask receiverType = receiver.instructionType;
-    return compiler.world.locateSingleField(selector, receiverType);
+    return compiler.closedWorld.locateSingleField(selector, receiverType);
   }
 
   HInstruction visitFieldGet(HFieldGet node) {
@@ -905,7 +906,7 @@
   }
 
   HInstruction directFieldGet(HInstruction receiver, Element field) {
-    bool isAssignable = !compiler.world.fieldNeverChanges(field);
+    bool isAssignable = !compiler.closedWorld.fieldNeverChanges(field);
 
     TypeMask type;
     if (backend.isNative(field.enclosingClass)) {
@@ -1013,22 +1014,51 @@
   HInstruction visitStringify(HStringify node) {
     HInstruction input = node.inputs[0];
     if (input.isString(compiler)) return input;
-    if (input.isConstant()) {
+
+    HInstruction tryConstant() {
+      if (!input.isConstant()) return null;
       HConstant constant = input;
-      if (!constant.constant.isPrimitive) return node;
+      if (!constant.constant.isPrimitive) return null;
       if (constant.constant.isInt) {
         // Only constant-fold int.toString() when Dart and JS results the same.
         // TODO(18103): We should be able to remove this work-around when issue
         // 18103 is resolved by providing the correct string.
         IntConstantValue intConstant = constant.constant;
         // Very conservative range.
-        if (!intConstant.isUInt32()) return node;
+        if (!intConstant.isUInt32()) return null;
       }
       PrimitiveConstantValue primitive = constant.constant;
       return graph.addConstant(
           constantSystem.createString(primitive.toDartString()), compiler);
     }
-    return node;
+
+    HInstruction tryToString() {
+      // If the `toString` method is guaranteed to return a string we can call
+      // it directly. Keep the stringifier for primitives (since they have fast
+      // path code in the stringifier) and for classes requiring interceptors
+      // (since SsaInstructionSimplifier runs after SsaSimplifyInterceptors).
+      if (input.canBePrimitive(compiler)) return null;
+      if (input.canBeNull()) return null;
+      Selector selector = Selectors.toString_;
+      TypeMask toStringType = TypeMaskFactory.inferredTypeForSelector(
+          selector, input.instructionType, compiler);
+      ClosedWorld closedWorld = compiler.closedWorld;
+      if (!toStringType.containsOnlyString(closedWorld)) return null;
+      // All intercepted classes extend `Interceptor`, so if the receiver can't
+      // be a class extending `Interceptor` then it can be called directly.
+      if (new TypeMask.nonNullSubclass(helpers.jsInterceptorClass, closedWorld)
+          .isDisjoint(input.instructionType, closedWorld)) {
+        HInstruction result = new HInvokeDynamicMethod(
+            selector,
+            input.instructionType, // receiver mask.
+            <HInstruction>[input, input], // [interceptor, receiver].
+            toStringType)..sourceInformation = node.sourceInformation;
+        return result;
+      }
+      return null;
+    }
+
+    return tryConstant() ?? tryToString() ?? node;
   }
 
   HInstruction visitOneShotInterceptor(HOneShotInterceptor node) {
@@ -1036,10 +1066,10 @@
   }
 
   bool needsSubstitutionForTypeVariableAccess(ClassElement cls) {
-    ClassWorld classWorld = compiler.world;
-    if (classWorld.isUsedAsMixin(cls)) return true;
+    ClosedWorld closedWorld = compiler.closedWorld;
+    if (closedWorld.isUsedAsMixin(cls)) return true;
 
-    return classWorld.anyStrictSubclassOf(cls, (ClassElement subclass) {
+    return closedWorld.anyStrictSubclassOf(cls, (ClassElement subclass) {
       return !backend.rti.isTrivialSubstitution(subclass, cls);
     });
   }
@@ -2056,7 +2086,7 @@
     if (ifUsers.isEmpty && notIfUsers.isEmpty) return;
 
     TypeMask convertedType =
-        new TypeMask.nonNullSubtype(element, compiler.world);
+        new TypeMask.nonNullSubtype(element, compiler.closedWorld);
     HInstruction input = instruction.expression;
 
     for (HIf ifUser in ifUsers) {
@@ -2243,9 +2273,9 @@
         // Assume the argument escapes. All we do with our initial allocation is
         // have it escape or store it into an object that escapes.
         return false;
-        // TODO(sra): Handle more functions. `setRuntimeTypeInfo` does not
-        // actually kill it's input, but we don't make use of that elsewhere so
-        // there is not point in checking here.
+        // TODO(sra): Handle library functions that we know do not modify or
+        // leak the inputs. For example `setRuntimeTypeInfo` is used to mark
+        // list literals with type information.
       }
       if (use is HPhi) {
         // The initial allocation (it's only alias) gets merged out of the model
@@ -2291,6 +2321,8 @@
   void visitLiteralList(HLiteralList instruction) {
     memorySet.registerAllocation(instruction);
     memorySet.killAffectedBy(instruction);
+    // TODO(sra): Set initial keyed values.
+    // TODO(sra): Set initial length.
   }
 
   void visitIndex(HIndex instruction) {
@@ -2310,10 +2342,31 @@
     memorySet.registerKeyedValueUpdate(
         receiver, instruction.index, instruction.value);
   }
+
+  // Pure operations that do not escape their inputs.
+  void visitBinaryArithmetic(HBinaryArithmetic instruction) {}
+  void visitConstant(HConstant instruction) {}
+  void visitIf(HIf instruction) {}
+  void visitInterceptor(HInterceptor instruction) {}
+  void visitIs(HIs instruction) {}
+  void visitIsViaInterceptor(HIsViaInterceptor instruction) {}
+  void visitNot(HNot instruction) {}
+  void visitParameterValue(HParameterValue instruction) {}
+  void visitRelational(HRelational instruction) {}
+  void visitStringConcat(HStringConcat instruction) {}
+  void visitTypeKnown(HTypeKnown instruction) {}
+  void visitTypeInfoReadRaw(HTypeInfoReadRaw instruction) {}
+  void visitTypeInfoReadVariable(HTypeInfoReadVariable instruction) {}
+  void visitTypeInfoExpression(HTypeInfoExpression instruction) {}
 }
 
 /**
  * Holds values of memory places.
+ *
+ * Generally, values that name a place (a receiver) have type refinements and
+ * other checks removed to ensure that checks and type refinements do not
+ * confuse aliasing.  Values stored into a memory place keep the type
+ * refinements to help further optimizations.
  */
 class MemorySet {
   final Compiler compiler;
@@ -2357,11 +2410,11 @@
     // Typed arrays of different types might have a shared buffer.
     if (couldBeTypedArray(first) && couldBeTypedArray(second)) return true;
     return !first.instructionType
-        .isDisjoint(second.instructionType, compiler.world);
+        .isDisjoint(second.instructionType, compiler.closedWorld);
   }
 
   bool isFinal(Element element) {
-    return compiler.world.fieldNeverChanges(element);
+    return compiler.closedWorld.fieldNeverChanges(element);
   }
 
   bool isConcrete(HInstruction instruction) {
@@ -2379,25 +2432,28 @@
    * Returns whether [receiver] escapes the current function.
    */
   bool escapes(HInstruction receiver) {
+    assert(receiver == null || receiver == receiver.nonCheck());
     return !nonEscapingReceivers.contains(receiver);
   }
 
   void registerAllocation(HInstruction instruction) {
+    assert(instruction == instruction.nonCheck());
     nonEscapingReceivers.add(instruction);
   }
 
   /**
-   * Sets `receiver.element` to contain [value]. Kills all potential
-   * places that may be affected by this update.
+   * Sets `receiver.element` to contain [value]. Kills all potential places that
+   * may be affected by this update.
    */
   void registerFieldValueUpdate(
       Element element, HInstruction receiver, HInstruction value) {
+    assert(receiver == null || receiver == receiver.nonCheck());
     if (backend.isNative(element)) {
       return; // TODO(14955): Remove this restriction?
     }
     // [value] is being set in some place in memory, we remove it from
     // the non-escaping set.
-    nonEscapingReceivers.remove(value);
+    nonEscapingReceivers.remove(value.nonCheck());
     Map<HInstruction, HInstruction> map =
         fieldValues.putIfAbsent(element, () => <HInstruction, HInstruction>{});
     map.forEach((key, value) {
@@ -2411,6 +2467,7 @@
    */
   void registerFieldValue(
       Element element, HInstruction receiver, HInstruction value) {
+    assert(receiver == null || receiver == receiver.nonCheck());
     if (backend.isNative(element)) {
       return; // TODO(14955): Remove this restriction?
     }
@@ -2420,27 +2477,26 @@
   }
 
   /**
-   * Returns the value stored in `receiver.element`. Returns null if
-   * we don't know.
+   * Returns the value stored in `receiver.element`. Returns `null` if we don't
+   * know.
    */
   HInstruction lookupFieldValue(Element element, HInstruction receiver) {
+    assert(receiver == null || receiver == receiver.nonCheck());
     Map<HInstruction, HInstruction> map = fieldValues[element];
     return (map == null) ? null : map[receiver];
   }
 
   /**
-   * Kill all places that may be affected by this [instruction]. Also
-   * update the set of non-escaping objects in case [instruction] has
-   * non-escaping objects in its inputs.
+   * Kill all places that may be affected by this [instruction]. Also update the
+   * set of non-escaping objects in case [instruction] has non-escaping objects
+   * in its inputs.
    */
   void killAffectedBy(HInstruction instruction) {
-    // Even if [instruction] does not have side effects, it may use
-    // non-escaping objects and store them in a new object, which
-    // make these objects escaping.
-    // TODO(ngeoffray): We need a new side effect flag to know whether
-    // an instruction allocates an object.
+    // Even if [instruction] does not have side effects, it may use non-escaping
+    // objects and store them in a new object, which make these objects
+    // escaping.
     instruction.inputs.forEach((input) {
-      nonEscapingReceivers.remove(input);
+      nonEscapingReceivers.remove(input.nonCheck());
     });
 
     if (instruction.sideEffects.changesInstanceProperty() ||
@@ -2491,7 +2547,7 @@
    */
   void registerKeyedValueUpdate(
       HInstruction receiver, HInstruction index, HInstruction value) {
-    nonEscapingReceivers.remove(value);
+    nonEscapingReceivers.remove(value.nonCheck());
     keyedValues.forEach((key, values) {
       if (mayAlias(receiver, key)) {
         // Typed arrays that are views of the same buffer may have different
@@ -2522,8 +2578,8 @@
       HBasicBlock block, int predecessorIndex) {
     if (first == null || second == null) return null;
     if (first == second) return first;
-    TypeMask phiType =
-        second.instructionType.union(first.instructionType, compiler.world);
+    TypeMask phiType = second.instructionType
+        .union(first.instructionType, compiler.closedWorld);
     if (first is HPhi && first.block == block) {
       HPhi phi = first;
       phi.addInput(second);
diff --git a/pkg/compiler/lib/src/ssa/ssa_tracer.dart b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
index d47e3ad..1768db1 100644
--- a/pkg/compiler/lib/src/ssa/ssa_tracer.dart
+++ b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
@@ -145,7 +145,7 @@
       prefix = 'd';
     } else if (instruction.isNumber(compiler)) {
       prefix = 'n';
-    } else if (instruction.instructionType.containsAll(compiler.world)) {
+    } else if (instruction.instructionType.containsAll(compiler.closedWorld)) {
       prefix = 'v';
     } else {
       prefix = 'U';
diff --git a/pkg/compiler/lib/src/ssa/types.dart b/pkg/compiler/lib/src/ssa/types.dart
index f43ca7e..edffc3a 100644
--- a/pkg/compiler/lib/src/ssa/types.dart
+++ b/pkg/compiler/lib/src/ssa/types.dart
@@ -34,7 +34,7 @@
     var typesReturned = nativeBehavior.typesReturned;
     if (typesReturned.isEmpty) return compiler.commonMasks.dynamicType;
 
-    ClassWorld world = compiler.world;
+    ClassWorld world = compiler.closedWorld;
     CommonMasks commonMasks = compiler.commonMasks;
     CoreClasses coreClasses = compiler.coreClasses;
 
@@ -53,7 +53,7 @@
 
     TypeMask result = typesReturned
         .map(fromNativeType)
-        .reduce((t1, t2) => t1.union(t2, compiler.world));
+        .reduce((t1, t2) => t1.union(t2, compiler.closedWorld));
     assert(!result.isEmpty);
     return result;
   }
diff --git a/pkg/compiler/lib/src/ssa/types_propagation.dart b/pkg/compiler/lib/src/ssa/types_propagation.dart
index 298d928..e9b4c98 100644
--- a/pkg/compiler/lib/src/ssa/types_propagation.dart
+++ b/pkg/compiler/lib/src/ssa/types_propagation.dart
@@ -24,7 +24,7 @@
 
   SsaTypePropagator(Compiler compiler)
       : this.compiler = compiler,
-        this.classWorld = compiler.world;
+        this.classWorld = compiler.closedWorld;
 
   TypeMask computeType(HInstruction instruction) {
     return instruction.accept(this);
@@ -268,7 +268,7 @@
           HTypeConversion.RECEIVER_TYPE_CHECK);
       return true;
     } else if (instruction.element == null) {
-      Iterable<Element> targets = compiler.world.allFunctions
+      Iterable<Element> targets = compiler.closedWorld.allFunctions
           .filter(instruction.selector, instruction.mask);
       if (targets.length == 1) {
         Element target = targets.first;
@@ -371,7 +371,7 @@
     if (!instruction.selector.isClosureCall) {
       TypeMask newType;
       TypeMask computeNewType() {
-        newType = compiler.world.allFunctions
+        newType = compiler.closedWorld.allFunctions
             .receiverType(instruction.selector, instruction.mask);
         newType = newType.intersection(receiverType, classWorld);
         return newType;
diff --git a/pkg/compiler/lib/src/string_validator.dart b/pkg/compiler/lib/src/string_validator.dart
index 60c3c78..b81661a 100644
--- a/pkg/compiler/lib/src/string_validator.dart
+++ b/pkg/compiler/lib/src/string_validator.dart
@@ -111,13 +111,10 @@
       Token token, int startOffset, String string, StringQuoting quoting) {
     // We need to check for invalid x and u escapes, for line
     // terminators in non-multiline strings, and for invalid Unicode
-    // scalar values (either directly or as u-escape values).  We also check
-    // for unpaired UTF-16 surrogates.
+    // code points (either directly or as u-escape values).
     int length = 0;
     int index = startOffset;
     bool containsEscape = false;
-    bool previousWasLeadSurrogate = false;
-    bool invalidUtf16 = false;
     var stringIter = string.codeUnits.iterator;
     for (HasNextIterator<int> iter = new HasNextIterator(stringIter);
         iter.hasNext;
@@ -199,26 +196,14 @@
           code = value;
         }
       }
-      if (code >= 0x10000) length++;
-      // This handles both unescaped characters and the value of unicode
-      // escapes.
-      if (previousWasLeadSurrogate) {
-        if (!isUtf16TrailSurrogate(code)) {
-          invalidUtf16 = true;
-          break;
+      if (code >= 0x10000) {
+        length++;
+        if (code > 0x10FFFF) {
+          stringParseError("Invalid code point", token, index);
+          return null;
         }
-        previousWasLeadSurrogate = false;
-      } else if (isUtf16LeadSurrogate(code)) {
-        previousWasLeadSurrogate = true;
-      } else if (!isUnicodeScalarValue(code)) {
-        invalidUtf16 = true;
-        break;
       }
     }
-    if (previousWasLeadSurrogate || invalidUtf16) {
-      stringParseError("Invalid Utf16 surrogate", token, index);
-      return null;
-    }
     // String literal successfully validated.
     if (quoting.raw || !containsEscape) {
       // A string without escapes could just as well have been raw.
diff --git a/pkg/compiler/lib/src/types/constants.dart b/pkg/compiler/lib/src/types/constants.dart
index b4689ce..8c3f6b7 100644
--- a/pkg/compiler/lib/src/types/constants.dart
+++ b/pkg/compiler/lib/src/types/constants.dart
@@ -24,7 +24,8 @@
     if (compiler.backend.isInterceptorClass(constant.type.element)) {
       return compiler.commonMasks.nonNullType;
     }
-    return new TypeMask.nonNullExact(constant.type.element, compiler.world);
+    return new TypeMask.nonNullExact(
+        constant.type.element, compiler.closedWorld);
   }
 
   @override
diff --git a/pkg/compiler/lib/src/types/flat_type_mask.dart b/pkg/compiler/lib/src/types/flat_type_mask.dart
index 380c2fb..1055af2 100644
--- a/pkg/compiler/lib/src/types/flat_type_mask.dart
+++ b/pkg/compiler/lib/src/types/flat_type_mask.dart
@@ -48,7 +48,8 @@
    * Ensures that the generated mask is normalized, i.e., a call to
    * [TypeMask.assertIsNormalized] with the factory's result returns `true`.
    */
-  factory FlatTypeMask.normalized(ClassElement base, int flags, World world) {
+  factory FlatTypeMask.normalized(
+      ClassElement base, int flags, ClosedWorld world) {
     if ((flags >> 1) == EMPTY || ((flags >> 1) == EXACT)) {
       return new FlatTypeMask.internal(base, flags);
     }
@@ -97,7 +98,7 @@
     return isNullable ? new FlatTypeMask.internal(base, flags & ~1) : this;
   }
 
-  bool contains(ClassElement type, ClassWorld classWorld) {
+  bool contains(ClassElement type, ClosedWorld closedWorld) {
     assert(type.isDeclaration);
     if (isEmptyOrNull) {
       return false;
@@ -106,42 +107,43 @@
     } else if (isExact) {
       return false;
     } else if (isSubclass) {
-      return classWorld.isSubclassOf(type, base);
+      return closedWorld.isSubclassOf(type, base);
     } else {
       assert(isSubtype);
-      return classWorld.isSubtypeOf(type, base);
+      return closedWorld.isSubtypeOf(type, base);
     }
   }
 
-  bool isSingleImplementationOf(ClassElement cls, ClassWorld classWorld) {
+  bool isSingleImplementationOf(ClassElement cls, ClosedWorld closedWorld) {
     // Special case basic types so that, for example, JSString is the
     // single implementation of String.
     // The general optimization is to realize there is only one class that
     // implements [base] and [base] is not instantiated. We however do
     // not track correctly the list of truly instantiated classes.
-    Backend backend = classWorld.backend;
-    if (containsOnlyString(classWorld)) {
-      return cls == classWorld.stringClass ||
+    Backend backend = closedWorld.backend;
+    if (containsOnlyString(closedWorld)) {
+      return cls == closedWorld.coreClasses.stringClass ||
           cls == backend.stringImplementation;
     }
-    if (containsOnlyBool(classWorld)) {
-      return cls == classWorld.boolClass || cls == backend.boolImplementation;
+    if (containsOnlyBool(closedWorld)) {
+      return cls == closedWorld.coreClasses.boolClass ||
+          cls == backend.boolImplementation;
     }
-    if (containsOnlyInt(classWorld)) {
-      return cls == classWorld.intClass ||
+    if (containsOnlyInt(closedWorld)) {
+      return cls == closedWorld.coreClasses.intClass ||
           cls == backend.intImplementation ||
           cls == backend.positiveIntImplementation ||
           cls == backend.uint32Implementation ||
           cls == backend.uint31Implementation;
     }
-    if (containsOnlyDouble(classWorld)) {
-      return cls == classWorld.doubleClass ||
+    if (containsOnlyDouble(closedWorld)) {
+      return cls == closedWorld.coreClasses.doubleClass ||
           cls == backend.doubleImplementation;
     }
     return false;
   }
 
-  bool isInMask(TypeMask other, ClassWorld classWorld) {
+  bool isInMask(TypeMask other, ClosedWorld closedWorld) {
     if (isEmptyOrNull) return isNullable ? other.isNullable : true;
     // The empty type contains no classes.
     if (other.isEmptyOrNull) return false;
@@ -149,7 +151,7 @@
     if (isNullable && !other.isNullable) return false;
     other = TypeMask.nonForwardingMask(other);
     // If other is union, delegate to UnionTypeMask.containsMask.
-    if (other is! FlatTypeMask) return other.containsMask(this, classWorld);
+    if (other is! FlatTypeMask) return other.containsMask(this, closedWorld);
     // The other must be flat, so compare base and flags.
     FlatTypeMask flatOther = other;
     ClassElement otherBase = flatOther.base;
@@ -157,7 +159,7 @@
     // TODO(herhut): Get rid of isSingleImplementationOf.
     if (flatOther.isExact) {
       return (isExact && base == otherBase) ||
-          isSingleImplementationOf(otherBase, classWorld);
+          isSingleImplementationOf(otherBase, closedWorld);
     }
     // If other is subclass, this has to be subclass, as well. Unless
     // flatOther.base covers all subtypes of this. Currently, we only
@@ -165,49 +167,50 @@
     // TODO(herhut): Add check whether flatOther.base is superclass of
     //               all subclasses of this.base.
     if (flatOther.isSubclass) {
-      if (isSubtype) return (otherBase == classWorld.objectClass);
-      return classWorld.isSubclassOf(base, otherBase);
+      if (isSubtype) return (otherBase == closedWorld.coreClasses.objectClass);
+      return closedWorld.isSubclassOf(base, otherBase);
     }
     assert(flatOther.isSubtype);
     // Check whether this TypeMask satisfies otherBase's interface.
-    return satisfies(otherBase, classWorld);
+    return satisfies(otherBase, closedWorld);
   }
 
-  bool containsMask(TypeMask other, ClassWorld classWorld) {
-    return other.isInMask(this, classWorld);
+  bool containsMask(TypeMask other, ClosedWorld closedWorld) {
+    return other.isInMask(this, closedWorld);
   }
 
-  bool containsOnlyInt(ClassWorld classWorld) {
-    Backend backend = classWorld.backend;
-    return base == classWorld.intClass ||
+  bool containsOnlyInt(ClosedWorld closedWorld) {
+    Backend backend = closedWorld.backend;
+    return base == closedWorld.coreClasses.intClass ||
         base == backend.intImplementation ||
         base == backend.positiveIntImplementation ||
         base == backend.uint31Implementation ||
         base == backend.uint32Implementation;
   }
 
-  bool containsOnlyDouble(ClassWorld classWorld) {
-    Backend backend = classWorld.backend;
-    return base == classWorld.doubleClass ||
+  bool containsOnlyDouble(ClosedWorld closedWorld) {
+    Backend backend = closedWorld.backend;
+    return base == closedWorld.coreClasses.doubleClass ||
         base == backend.doubleImplementation;
   }
 
-  bool containsOnlyNum(ClassWorld classWorld) {
-    Backend backend = classWorld.backend;
-    return containsOnlyInt(classWorld) ||
-        containsOnlyDouble(classWorld) ||
-        base == classWorld.numClass ||
+  bool containsOnlyNum(ClosedWorld closedWorld) {
+    Backend backend = closedWorld.backend;
+    return containsOnlyInt(closedWorld) ||
+        containsOnlyDouble(closedWorld) ||
+        base == closedWorld.coreClasses.numClass ||
         base == backend.numImplementation;
   }
 
-  bool containsOnlyBool(ClassWorld classWorld) {
-    Backend backend = classWorld.backend;
-    return base == classWorld.boolClass || base == backend.boolImplementation;
+  bool containsOnlyBool(ClosedWorld closedWorld) {
+    Backend backend = closedWorld.backend;
+    return base == closedWorld.coreClasses.boolClass ||
+        base == backend.boolImplementation;
   }
 
-  bool containsOnlyString(ClassWorld classWorld) {
-    Backend backend = classWorld.backend;
-    return base == classWorld.stringClass ||
+  bool containsOnlyString(ClosedWorld closedWorld) {
+    Backend backend = closedWorld.backend;
+    return base == closedWorld.coreClasses.stringClass ||
         base == backend.stringImplementation;
   }
 
@@ -216,10 +219,10 @@
     return base == cls;
   }
 
-  bool satisfies(ClassElement cls, ClassWorld classWorld) {
+  bool satisfies(ClassElement cls, ClosedWorld closedWorld) {
     assert(cls.isDeclaration);
     if (isEmptyOrNull) return false;
-    if (classWorld.isSubtypeOf(base, cls)) return true;
+    if (closedWorld.isSubtypeOf(base, cls)) return true;
     return false;
   }
 
@@ -227,13 +230,13 @@
    * Returns the [ClassElement] if this type represents a single class,
    * otherwise returns `null`.  This method is conservative.
    */
-  ClassElement singleClass(ClassWorld classWorld) {
+  ClassElement singleClass(ClosedWorld closedWorld) {
     if (isEmptyOrNull) return null;
     if (isNullable) return null; // It is Null and some other class.
     if (isExact) {
       return base;
     } else if (isSubclass) {
-      return classWorld.hasAnyStrictSubclass(base) ? null : base;
+      return closedWorld.hasAnyStrictSubclass(base) ? null : base;
     } else {
       assert(isSubtype);
       return null;
@@ -243,40 +246,40 @@
   /**
    * Returns whether or not this type mask contains all types.
    */
-  bool containsAll(ClassWorld classWorld) {
+  bool containsAll(ClosedWorld closedWorld) {
     if (isEmptyOrNull || isExact) return false;
-    return identical(base, classWorld.objectClass);
+    return identical(base, closedWorld.coreClasses.objectClass);
   }
 
-  TypeMask union(TypeMask other, ClassWorld classWorld) {
+  TypeMask union(TypeMask other, ClosedWorld closedWorld) {
     assert(other != null);
-    assert(TypeMask.assertIsNormalized(this, classWorld));
-    assert(TypeMask.assertIsNormalized(other, classWorld));
-    if (other is! FlatTypeMask) return other.union(this, classWorld);
+    assert(TypeMask.assertIsNormalized(this, closedWorld));
+    assert(TypeMask.assertIsNormalized(other, closedWorld));
+    if (other is! FlatTypeMask) return other.union(this, closedWorld);
     FlatTypeMask flatOther = other;
     if (isEmptyOrNull) {
       return isNullable ? flatOther.nullable() : flatOther;
     } else if (flatOther.isEmptyOrNull) {
       return flatOther.isNullable ? nullable() : this;
     } else if (base == flatOther.base) {
-      return unionSame(flatOther, classWorld);
-    } else if (classWorld.isSubclassOf(flatOther.base, base)) {
-      return unionStrictSubclass(flatOther, classWorld);
-    } else if (classWorld.isSubclassOf(base, flatOther.base)) {
-      return flatOther.unionStrictSubclass(this, classWorld);
-    } else if (classWorld.isSubtypeOf(flatOther.base, base)) {
-      return unionStrictSubtype(flatOther, classWorld);
-    } else if (classWorld.isSubtypeOf(base, flatOther.base)) {
-      return flatOther.unionStrictSubtype(this, classWorld);
+      return unionSame(flatOther, closedWorld);
+    } else if (closedWorld.isSubclassOf(flatOther.base, base)) {
+      return unionStrictSubclass(flatOther, closedWorld);
+    } else if (closedWorld.isSubclassOf(base, flatOther.base)) {
+      return flatOther.unionStrictSubclass(this, closedWorld);
+    } else if (closedWorld.isSubtypeOf(flatOther.base, base)) {
+      return unionStrictSubtype(flatOther, closedWorld);
+    } else if (closedWorld.isSubtypeOf(base, flatOther.base)) {
+      return flatOther.unionStrictSubtype(this, closedWorld);
     } else {
       return new UnionTypeMask._internal(<FlatTypeMask>[this, flatOther]);
     }
   }
 
-  TypeMask unionSame(FlatTypeMask other, ClassWorld classWorld) {
+  TypeMask unionSame(FlatTypeMask other, ClosedWorld closedWorld) {
     assert(base == other.base);
-    assert(TypeMask.assertIsNormalized(this, classWorld));
-    assert(TypeMask.assertIsNormalized(other, classWorld));
+    assert(TypeMask.assertIsNormalized(this, closedWorld));
+    assert(TypeMask.assertIsNormalized(other, closedWorld));
     // The two masks share the base type, so we must chose the least
     // constraining kind (the highest) of the two. If either one of
     // the masks are nullable the result should be nullable too.
@@ -289,17 +292,18 @@
     } else if (other.flags == combined) {
       return other;
     } else {
-      return new FlatTypeMask.normalized(base, combined, classWorld);
+      return new FlatTypeMask.normalized(base, combined, closedWorld);
     }
   }
 
-  TypeMask unionStrictSubclass(FlatTypeMask other, ClassWorld classWorld) {
+  TypeMask unionStrictSubclass(FlatTypeMask other, ClosedWorld closedWorld) {
     assert(base != other.base);
-    assert(classWorld.isSubclassOf(other.base, base));
-    assert(TypeMask.assertIsNormalized(this, classWorld));
-    assert(TypeMask.assertIsNormalized(other, classWorld));
+    assert(closedWorld.isSubclassOf(other.base, base));
+    assert(TypeMask.assertIsNormalized(this, closedWorld));
+    assert(TypeMask.assertIsNormalized(other, closedWorld));
     int combined;
-    if ((isExact && other.isExact) || base == classWorld.objectClass) {
+    if ((isExact && other.isExact) ||
+        base == closedWorld.coreClasses.objectClass) {
       // Since the other mask is a subclass of this mask, we need the
       // resulting union to be a subclass too. If either one of the
       // masks are nullable the result should be nullable too.
@@ -315,16 +319,16 @@
     // If we weaken the constraint on this type, we have to make sure that
     // the result is normalized.
     return (flags != combined)
-        ? new FlatTypeMask.normalized(base, combined, classWorld)
+        ? new FlatTypeMask.normalized(base, combined, closedWorld)
         : this;
   }
 
-  TypeMask unionStrictSubtype(FlatTypeMask other, ClassWorld classWorld) {
+  TypeMask unionStrictSubtype(FlatTypeMask other, ClosedWorld closedWorld) {
     assert(base != other.base);
-    assert(!classWorld.isSubclassOf(other.base, base));
-    assert(classWorld.isSubtypeOf(other.base, base));
-    assert(TypeMask.assertIsNormalized(this, classWorld));
-    assert(TypeMask.assertIsNormalized(other, classWorld));
+    assert(!closedWorld.isSubclassOf(other.base, base));
+    assert(closedWorld.isSubtypeOf(other.base, base));
+    assert(TypeMask.assertIsNormalized(this, closedWorld));
+    assert(TypeMask.assertIsNormalized(other, closedWorld));
     // Since the other mask is a subtype of this mask, we need the
     // resulting union to be a subtype too. If either one of the masks
     // are nullable the result should be nullable too.
@@ -332,37 +336,37 @@
     // We know there is at least one subtype, [other.base], so no need
     // to normalize.
     return (flags != combined)
-        ? new FlatTypeMask.normalized(base, combined, classWorld)
+        ? new FlatTypeMask.normalized(base, combined, closedWorld)
         : this;
   }
 
-  TypeMask intersection(TypeMask other, ClassWorld classWorld) {
+  TypeMask intersection(TypeMask other, ClosedWorld closedWorld) {
     assert(other != null);
-    if (other is! FlatTypeMask) return other.intersection(this, classWorld);
-    assert(TypeMask.assertIsNormalized(this, classWorld));
-    assert(TypeMask.assertIsNormalized(other, classWorld));
+    if (other is! FlatTypeMask) return other.intersection(this, closedWorld);
+    assert(TypeMask.assertIsNormalized(this, closedWorld));
+    assert(TypeMask.assertIsNormalized(other, closedWorld));
     FlatTypeMask flatOther = other;
     if (isEmptyOrNull) {
       return flatOther.isNullable ? this : nonNullable();
     } else if (flatOther.isEmptyOrNull) {
       return isNullable ? flatOther : other.nonNullable();
     } else if (base == flatOther.base) {
-      return intersectionSame(flatOther, classWorld);
-    } else if (classWorld.isSubclassOf(flatOther.base, base)) {
-      return intersectionStrictSubclass(flatOther, classWorld);
-    } else if (classWorld.isSubclassOf(base, flatOther.base)) {
-      return flatOther.intersectionStrictSubclass(this, classWorld);
-    } else if (classWorld.isSubtypeOf(flatOther.base, base)) {
-      return intersectionStrictSubtype(flatOther, classWorld);
-    } else if (classWorld.isSubtypeOf(base, flatOther.base)) {
-      return flatOther.intersectionStrictSubtype(this, classWorld);
+      return intersectionSame(flatOther, closedWorld);
+    } else if (closedWorld.isSubclassOf(flatOther.base, base)) {
+      return intersectionStrictSubclass(flatOther, closedWorld);
+    } else if (closedWorld.isSubclassOf(base, flatOther.base)) {
+      return flatOther.intersectionStrictSubclass(this, closedWorld);
+    } else if (closedWorld.isSubtypeOf(flatOther.base, base)) {
+      return intersectionStrictSubtype(flatOther, closedWorld);
+    } else if (closedWorld.isSubtypeOf(base, flatOther.base)) {
+      return flatOther.intersectionStrictSubtype(this, closedWorld);
     } else {
-      return intersectionDisjoint(flatOther, classWorld);
+      return intersectionDisjoint(flatOther, closedWorld);
     }
   }
 
-  bool isDisjoint(TypeMask other, ClassWorld classWorld) {
-    if (other is! FlatTypeMask) return other.isDisjoint(this, classWorld);
+  bool isDisjoint(TypeMask other, ClosedWorld closedWorld) {
+    if (other is! FlatTypeMask) return other.isDisjoint(this, closedWorld);
     FlatTypeMask flatOther = other;
 
     if (isNullable && flatOther.isNullable) return false;
@@ -370,39 +374,39 @@
     if (base == flatOther.base) return false;
     if (isExact && flatOther.isExact) return true;
 
-    if (isExact) return !flatOther.contains(base, classWorld);
-    if (flatOther.isExact) return !contains(flatOther.base, classWorld);
+    if (isExact) return !flatOther.contains(base, closedWorld);
+    if (flatOther.isExact) return !contains(flatOther.base, closedWorld);
 
     // Normalization guarantees that isExact === !isSubclass && !isSubtype.
     // Both are subclass or subtype masks, so if there is a subclass
     // relationship, they are not disjoint.
-    if (classWorld.isSubclassOf(flatOther.base, base)) return false;
-    if (classWorld.isSubclassOf(base, flatOther.base)) return false;
+    if (closedWorld.isSubclassOf(flatOther.base, base)) return false;
+    if (closedWorld.isSubclassOf(base, flatOther.base)) return false;
 
     // Two different base classes have no common subclass unless one is a
     // subclass of the other (checked above).
     if (isSubclass && flatOther.isSubclass) return true;
 
-    return _isDisjointHelper(this, flatOther, classWorld);
+    return _isDisjointHelper(this, flatOther, closedWorld);
   }
 
   static bool _isDisjointHelper(
-      FlatTypeMask a, FlatTypeMask b, ClassWorld classWorld) {
+      FlatTypeMask a, FlatTypeMask b, ClosedWorld closedWorld) {
     if (!a.isSubclass && b.isSubclass) {
-      return _isDisjointHelper(b, a, classWorld);
+      return _isDisjointHelper(b, a, closedWorld);
     }
     assert(a.isSubclass || a.isSubtype);
     assert(b.isSubtype);
     var elements = a.isSubclass
-        ? classWorld.strictSubclassesOf(a.base)
-        : classWorld.strictSubtypesOf(a.base);
+        ? closedWorld.strictSubclassesOf(a.base)
+        : closedWorld.strictSubtypesOf(a.base);
     for (var element in elements) {
-      if (classWorld.isSubtypeOf(element, b.base)) return false;
+      if (closedWorld.isSubtypeOf(element, b.base)) return false;
     }
     return true;
   }
 
-  TypeMask intersectionSame(FlatTypeMask other, ClassWorld classWorld) {
+  TypeMask intersectionSame(FlatTypeMask other, ClosedWorld closedWorld) {
     assert(base == other.base);
     // The two masks share the base type, so we must chose the most
     // constraining kind (the lowest) of the two. Only if both masks
@@ -416,14 +420,14 @@
     } else if (other.flags == combined) {
       return other;
     } else {
-      return new FlatTypeMask.normalized(base, combined, classWorld);
+      return new FlatTypeMask.normalized(base, combined, closedWorld);
     }
   }
 
   TypeMask intersectionStrictSubclass(
-      FlatTypeMask other, ClassWorld classWorld) {
+      FlatTypeMask other, ClosedWorld closedWorld) {
     assert(base != other.base);
-    assert(classWorld.isSubclassOf(other.base, base));
+    assert(closedWorld.isSubclassOf(other.base, base));
     // If this mask isn't at least a subclass mask, then the
     // intersection with the other mask is empty.
     if (isExact) return intersectionEmpty(other);
@@ -436,15 +440,15 @@
     if (other.flags == combined) {
       return other;
     } else {
-      return new FlatTypeMask.normalized(other.base, combined, classWorld);
+      return new FlatTypeMask.normalized(other.base, combined, closedWorld);
     }
   }
 
   TypeMask intersectionStrictSubtype(
-      FlatTypeMask other, ClassWorld classWorld) {
+      FlatTypeMask other, ClosedWorld closedWorld) {
     assert(base != other.base);
-    assert(classWorld.isSubtypeOf(other.base, base));
-    if (!isSubtype) return intersectionHelper(other, classWorld);
+    assert(closedWorld.isSubtypeOf(other.base, base));
+    if (!isSubtype) return intersectionHelper(other, closedWorld);
     // Only the other mask puts constraints on the intersection mask,
     // so base the combined flags on the other mask. Only if both
     // masks are nullable, will the result be nullable too.
@@ -454,21 +458,21 @@
     if (other.flags == combined) {
       return other;
     } else {
-      return new FlatTypeMask.normalized(other.base, combined, classWorld);
+      return new FlatTypeMask.normalized(other.base, combined, closedWorld);
     }
   }
 
-  TypeMask intersectionDisjoint(FlatTypeMask other, ClassWorld classWorld) {
+  TypeMask intersectionDisjoint(FlatTypeMask other, ClosedWorld closedWorld) {
     assert(base != other.base);
-    assert(!classWorld.isSubtypeOf(base, other.base));
-    assert(!classWorld.isSubtypeOf(other.base, base));
-    return intersectionHelper(other, classWorld);
+    assert(!closedWorld.isSubtypeOf(base, other.base));
+    assert(!closedWorld.isSubtypeOf(other.base, base));
+    return intersectionHelper(other, closedWorld);
   }
 
-  TypeMask intersectionHelper(FlatTypeMask other, ClassWorld classWorld) {
+  TypeMask intersectionHelper(FlatTypeMask other, ClosedWorld closedWorld) {
     assert(base != other.base);
-    assert(!classWorld.isSubclassOf(base, other.base));
-    assert(!classWorld.isSubclassOf(other.base, base));
+    assert(!closedWorld.isSubclassOf(base, other.base));
+    assert(!closedWorld.isSubclassOf(other.base, base));
     // If one of the masks are exact or if both of them are subclass
     // masks, then the intersection is empty.
     if (isExact || other.isExact) return intersectionEmpty(other);
@@ -476,7 +480,7 @@
     assert(isSubtype || other.isSubtype);
     int kind = (isSubclass || other.isSubclass) ? SUBCLASS : SUBTYPE;
     // Compute the set of classes that are contained in both type masks.
-    Set<ClassElement> common = commonContainedClasses(this, other, classWorld);
+    Set<ClassElement> common = commonContainedClasses(this, other, closedWorld);
     if (common == null || common.isEmpty) return intersectionEmpty(other);
     // Narrow down the candidates by only looking at common classes
     // that do not have a superclass or supertype that will be a
@@ -501,9 +505,9 @@
     // to normalize here, as we generate types based on new base classes.
     int combined = (kind << 1) | (flags & other.flags & 1);
     Iterable<TypeMask> masks = candidates.map((ClassElement cls) {
-      return new FlatTypeMask.normalized(cls, combined, classWorld);
+      return new FlatTypeMask.normalized(cls, combined, closedWorld);
     });
-    return UnionTypeMask.unionOf(masks, classWorld);
+    return UnionTypeMask.unionOf(masks, closedWorld);
   }
 
   TypeMask intersectionEmpty(FlatTypeMask other) {
@@ -538,8 +542,8 @@
    * invoked on this type mask. [selector] is used to ensure library
    * privacy is taken into account.
    */
-  bool canHit(Element element, Selector selector, ClassWorld classWorld) {
-    Backend backend = classWorld.backend;
+  bool canHit(Element element, Selector selector, ClosedWorld closedWorld) {
+    Backend backend = closedWorld.backend;
     assert(element.name == selector.name);
     if (isEmpty) return false;
     if (isNull) {
@@ -561,25 +565,25 @@
     } else if (isExact) {
       return hasElementIn(self, selector, element);
     } else if (isSubclass) {
-      assert(classWorld.isClosed);
+      assert(closedWorld.isClosed);
       return hasElementIn(self, selector, element) ||
           other.isSubclassOf(self) ||
-          classWorld.hasAnySubclassThatMixes(self, other);
+          closedWorld.hasAnySubclassThatMixes(self, other);
     } else {
       assert(isSubtype);
-      assert(classWorld.isClosed);
+      assert(closedWorld.isClosed);
       bool result = hasElementIn(self, selector, element) ||
           other.implementsInterface(self) ||
-          classWorld.hasAnySubclassThatImplements(other, base) ||
-          classWorld.hasAnySubclassOfMixinUseThatImplements(other, base);
+          closedWorld.hasAnySubclassThatImplements(other, base) ||
+          closedWorld.hasAnySubclassOfMixinUseThatImplements(other, base);
       if (result) return true;
       // If the class is used as a mixin, we have to check if the element
       // can be hit from any of the mixin applications.
-      Iterable<ClassElement> mixinUses = classWorld.mixinUsesOf(self);
+      Iterable<ClassElement> mixinUses = closedWorld.mixinUsesOf(self);
       return mixinUses.any((mixinApplication) =>
           hasElementIn(mixinApplication, selector, element) ||
           other.isSubclassOf(mixinApplication) ||
-          classWorld.hasAnySubclassThatMixes(mixinApplication, other));
+          closedWorld.hasAnySubclassThatMixes(mixinApplication, other));
     }
   }
 
@@ -588,7 +592,7 @@
    * will hit a method at runtime, and not go through [noSuchMethod].
    */
   static bool hasConcreteMatch(
-      ClassElement cls, Selector selector, ClassWorld world) {
+      ClassElement cls, Selector selector, ClosedWorld world) {
     assert(invariant(cls, world.isInstantiated(cls),
         message: '$cls has not been instantiated.'));
     Element element = findMatchIn(cls, selector);
@@ -598,10 +602,10 @@
       ClassElement enclosingClass = element.enclosingClass;
       return hasConcreteMatch(enclosingClass.superclass, selector, world);
     }
-    return selector.appliesUntyped(element, world);
+    return selector.appliesUntyped(element, world.backend);
   }
 
-  bool needsNoSuchMethodHandling(Selector selector, ClassWorld classWorld) {
+  bool needsNoSuchMethodHandling(Selector selector, ClosedWorld closedWorld) {
     // A call on an empty type mask is either dead code, or a call on
     // `null`.
     if (isEmptyOrNull) return false;
@@ -654,14 +658,14 @@
     bool needsNoSuchMethod(ClassElement cls) {
       // We can skip uninstantiated subclasses.
       // TODO(johnniwinther): Put filtering into the (Class)World.
-      if (!classWorld.isInstantiated(cls)) {
+      if (!closedWorld.isInstantiated(cls)) {
         return false;
       }
       // We can just skip abstract classes because we know no
       // instance of them will be created at runtime, and
       // therefore there is no instance that will require
       // [noSuchMethod] handling.
-      return !cls.isAbstract && !hasConcreteMatch(cls, selector, classWorld);
+      return !cls.isAbstract && !hasConcreteMatch(cls, selector, closedWorld);
     }
 
     bool baseNeedsNoSuchMethod = needsNoSuchMethod(base);
@@ -671,10 +675,10 @@
 
     Iterable<ClassElement> subclassesToCheck;
     if (isSubtype) {
-      subclassesToCheck = classWorld.strictSubtypesOf(base);
+      subclassesToCheck = closedWorld.strictSubtypesOf(base);
     } else {
       assert(isSubclass);
-      subclassesToCheck = classWorld.strictSubclassesOf(base);
+      subclassesToCheck = closedWorld.strictSubclassesOf(base);
     }
 
     return subclassesToCheck != null &&
@@ -684,7 +688,7 @@
   Element locateSingleElement(Selector selector, Compiler compiler) {
     if (isEmptyOrNull) return null;
     Iterable<Element> targets =
-        compiler.world.allFunctions.filter(selector, this);
+        compiler.closedWorld.allFunctions.filter(selector, this);
     if (targets.length != 1) return null;
     Element result = targets.first;
     ClassElement enclosing = result.enclosingClass;
@@ -692,17 +696,17 @@
     // all classes in the receiver type [this]. It could be found only in a
     // subclass or in an inheritance-wise unrelated class in case of subtype
     // selectors.
-    ClassWorld classWorld = compiler.world;
+    ClosedWorld closedWorld = compiler.closedWorld;
     if (isSubtype) {
-      // if (classWorld.isUsedAsMixin(enclosing)) {
-      if (classWorld.everySubtypeIsSubclassOfOrMixinUseOf(base, enclosing)) {
+      // if (closedWorld.isUsedAsMixin(enclosing)) {
+      if (closedWorld.everySubtypeIsSubclassOfOrMixinUseOf(base, enclosing)) {
         return result;
       }
       //}
       return null;
     } else {
       if (base.isSubclassOf(enclosing)) return result;
-      if (classWorld.isSubclassOfMixinUseOf(base, enclosing)) return result;
+      if (closedWorld.isSubclassOfMixinUseOf(base, enclosing)) return result;
     }
     return null;
   }
@@ -730,24 +734,24 @@
   }
 
   static Set<ClassElement> commonContainedClasses(
-      FlatTypeMask x, FlatTypeMask y, ClassWorld classWorld) {
-    Iterable<ClassElement> xSubset = containedSubset(x, classWorld);
+      FlatTypeMask x, FlatTypeMask y, ClosedWorld closedWorld) {
+    Iterable<ClassElement> xSubset = containedSubset(x, closedWorld);
     if (xSubset == null) return null;
-    Iterable<ClassElement> ySubset = containedSubset(y, classWorld);
+    Iterable<ClassElement> ySubset = containedSubset(y, closedWorld);
     if (ySubset == null) return null;
     return xSubset.toSet().intersection(ySubset.toSet());
   }
 
   static Iterable<ClassElement> containedSubset(
-      FlatTypeMask x, ClassWorld classWorld) {
+      FlatTypeMask x, ClosedWorld closedWorld) {
     ClassElement element = x.base;
     if (x.isExact) {
       return null;
     } else if (x.isSubclass) {
-      return classWorld.strictSubclassesOf(element);
+      return closedWorld.strictSubclassesOf(element);
     } else {
       assert(x.isSubtype);
-      return classWorld.strictSubtypesOf(element);
+      return closedWorld.strictSubtypesOf(element);
     }
   }
 }
diff --git a/pkg/compiler/lib/src/types/map_type_mask.dart b/pkg/compiler/lib/src/types/map_type_mask.dart
index 4645cd7..57f3c46 100644
--- a/pkg/compiler/lib/src/types/map_type_mask.dart
+++ b/pkg/compiler/lib/src/types/map_type_mask.dart
@@ -77,7 +77,10 @@
       return new MapTypeMask(
           newForwardTo, null, null, newKeyType, newValueType);
     } else if (other.isDictionary) {
-      assert(other.keyType == classWorld.compiler.commonMasks.stringType);
+      // TODO(johnniwinther): Find another way to check this invariant that
+      // doesn't need the compiler.
+      assert(
+          other.keyType == classWorld.backend.compiler.commonMasks.stringType);
       TypeMask newKeyType = keyType.union(other.keyType, classWorld);
       TypeMask newValueType =
           other.typeMap.values.fold(keyType, (p, n) => p.union(n, classWorld));
diff --git a/pkg/compiler/lib/src/types/masks.dart b/pkg/compiler/lib/src/types/masks.dart
index ee12b65..b498b80 100644
--- a/pkg/compiler/lib/src/types/masks.dart
+++ b/pkg/compiler/lib/src/types/masks.dart
@@ -18,7 +18,7 @@
         UniverseSelectorConstraints,
         SelectorConstraintsStrategy;
 import '../util/util.dart';
-import '../world.dart' show ClassWorld, World;
+import '../world.dart' show ClassWorld, ClosedWorld;
 import 'abstract_value_domain.dart' show AbstractValue;
 
 part 'container_type_mask.dart';
@@ -31,14 +31,13 @@
 part 'value_type_mask.dart';
 
 class CommonMasks {
-  final ClassWorld classWorld;
   // TODO(sigmund): once we split out the backend common elements, depend
   // directly on those instead.
   final Compiler compiler;
 
-  CommonMasks(Compiler compiler)
-      : this.classWorld = compiler.world,
-        compiler = compiler;
+  CommonMasks(this.compiler);
+
+  ClassWorld get classWorld => compiler.closedWorld;
 
   TypeMask _dynamicType;
   TypeMask _nonNullType;
@@ -64,10 +63,10 @@
   TypeMask _asyncStarStreamType;
 
   TypeMask get dynamicType => _dynamicType ??=
-      new TypeMask.subclass(classWorld.objectClass, classWorld);
+      new TypeMask.subclass(classWorld.coreClasses.objectClass, classWorld);
 
-  TypeMask get nonNullType => _nonNullType ??=
-      new TypeMask.nonNullSubclass(classWorld.objectClass, classWorld);
+  TypeMask get nonNullType => _nonNullType ??= new TypeMask.nonNullSubclass(
+      classWorld.coreClasses.objectClass, classWorld);
 
   TypeMask get intType => _intType ??= new TypeMask.nonNullSubclass(
       compiler.backend.intImplementation, classWorld);
diff --git a/pkg/compiler/lib/src/types/type_mask.dart b/pkg/compiler/lib/src/types/type_mask.dart
index d14bd95..cd92ed9 100644
--- a/pkg/compiler/lib/src/types/type_mask.dart
+++ b/pkg/compiler/lib/src/types/type_mask.dart
@@ -12,7 +12,7 @@
   Set<TypeMask> _masks;
 
   @override
-  bool applies(Element element, Selector selector, ClassWorld world) {
+  bool applies(Element element, Selector selector, ClosedWorld world) {
     if (isAll) return true;
     if (_masks == null) return false;
     for (TypeMask mask in _masks) {
@@ -22,9 +22,10 @@
   }
 
   @override
-  bool needsNoSuchMethodHandling(Selector selector, ClassWorld world) {
+  bool needsNoSuchMethodHandling(Selector selector, ClosedWorld world) {
     if (isAll) {
-      TypeMask mask = new TypeMask.subclass(world.objectClass, world);
+      TypeMask mask =
+          new TypeMask.subclass(world.coreClasses.objectClass, world);
       return mask.needsNoSuchMethodHandling(selector, world);
     }
     for (TypeMask mask in _masks) {
@@ -76,102 +77,102 @@
  */
 abstract class TypeMask implements ReceiverConstraint, AbstractValue {
   factory TypeMask(
-      ClassElement base, int kind, bool isNullable, ClassWorld classWorld) {
+      ClassElement base, int kind, bool isNullable, ClosedWorld closedWorld) {
     return new FlatTypeMask.normalized(
-        base, (kind << 1) | (isNullable ? 1 : 0), classWorld);
+        base, (kind << 1) | (isNullable ? 1 : 0), closedWorld);
   }
 
   const factory TypeMask.empty() = FlatTypeMask.empty;
 
-  factory TypeMask.exact(ClassElement base, ClassWorld classWorld) {
-    assert(invariant(base, classWorld.isInstantiated(base),
+  factory TypeMask.exact(ClassElement base, ClosedWorld closedWorld) {
+    assert(invariant(base, closedWorld.isInstantiated(base),
         message: () => "Cannot create exact type mask for uninstantiated "
-            "class $base.\n${classWorld.dump(base)}"));
+            "class $base.\n${closedWorld.dump(base)}"));
     return new FlatTypeMask.exact(base);
   }
 
-  factory TypeMask.exactOrEmpty(ClassElement base, ClassWorld classWorld) {
-    if (classWorld.isInstantiated(base)) return new FlatTypeMask.exact(base);
+  factory TypeMask.exactOrEmpty(ClassElement base, ClosedWorld closedWorld) {
+    if (closedWorld.isInstantiated(base)) return new FlatTypeMask.exact(base);
     return const TypeMask.empty();
   }
 
-  factory TypeMask.subclass(ClassElement base, ClassWorld classWorld) {
-    assert(invariant(base, classWorld.isInstantiated(base),
+  factory TypeMask.subclass(ClassElement base, ClosedWorld closedWorld) {
+    assert(invariant(base, closedWorld.isInstantiated(base),
         message: () => "Cannot create subclass type mask for uninstantiated "
-            "class $base.\n${classWorld.dump(base)}"));
-    ClassElement topmost = classWorld.getLubOfInstantiatedSubclasses(base);
+            "class $base.\n${closedWorld.dump(base)}"));
+    ClassElement topmost = closedWorld.getLubOfInstantiatedSubclasses(base);
     if (topmost == null) {
       return new TypeMask.empty();
-    } else if (classWorld.hasAnyStrictSubclass(topmost)) {
+    } else if (closedWorld.hasAnyStrictSubclass(topmost)) {
       return new FlatTypeMask.subclass(topmost);
     } else {
-      return new TypeMask.exact(topmost, classWorld);
+      return new TypeMask.exact(topmost, closedWorld);
     }
   }
 
-  factory TypeMask.subtype(ClassElement base, ClassWorld classWorld) {
-    ClassElement topmost = classWorld.getLubOfInstantiatedSubtypes(base);
+  factory TypeMask.subtype(ClassElement base, ClosedWorld closedWorld) {
+    ClassElement topmost = closedWorld.getLubOfInstantiatedSubtypes(base);
     if (topmost == null) {
       return new TypeMask.empty();
     }
-    if (classWorld.hasOnlySubclasses(topmost)) {
-      return new TypeMask.subclass(topmost, classWorld);
+    if (closedWorld.hasOnlySubclasses(topmost)) {
+      return new TypeMask.subclass(topmost, closedWorld);
     }
-    if (classWorld.hasAnyStrictSubtype(topmost)) {
+    if (closedWorld.hasAnyStrictSubtype(topmost)) {
       return new FlatTypeMask.subtype(topmost);
     } else {
-      return new TypeMask.exact(topmost, classWorld);
+      return new TypeMask.exact(topmost, closedWorld);
     }
   }
 
   const factory TypeMask.nonNullEmpty() = FlatTypeMask.nonNullEmpty;
 
-  factory TypeMask.nonNullExact(ClassElement base, ClassWorld classWorld) {
-    assert(invariant(base, classWorld.isInstantiated(base),
+  factory TypeMask.nonNullExact(ClassElement base, ClosedWorld closedWorld) {
+    assert(invariant(base, closedWorld.isInstantiated(base),
         message: () => "Cannot create exact type mask for uninstantiated "
-            "class $base.\n${classWorld.dump(base)}"));
+            "class $base.\n${closedWorld.dump(base)}"));
     return new FlatTypeMask.nonNullExact(base);
   }
 
   factory TypeMask.nonNullExactOrEmpty(
-      ClassElement base, ClassWorld classWorld) {
-    if (classWorld.isInstantiated(base)) {
+      ClassElement base, ClosedWorld closedWorld) {
+    if (closedWorld.isInstantiated(base)) {
       return new FlatTypeMask.nonNullExact(base);
     }
     return const TypeMask.nonNullEmpty();
   }
 
-  factory TypeMask.nonNullSubclass(ClassElement base, ClassWorld classWorld) {
-    assert(invariant(base, classWorld.isInstantiated(base),
+  factory TypeMask.nonNullSubclass(ClassElement base, ClosedWorld closedWorld) {
+    assert(invariant(base, closedWorld.isInstantiated(base),
         message: () => "Cannot create subclass type mask for uninstantiated "
-            "class $base.\n${classWorld.dump(base)}"));
-    ClassElement topmost = classWorld.getLubOfInstantiatedSubclasses(base);
+            "class $base.\n${closedWorld.dump(base)}"));
+    ClassElement topmost = closedWorld.getLubOfInstantiatedSubclasses(base);
     if (topmost == null) {
       return new TypeMask.nonNullEmpty();
-    } else if (classWorld.hasAnyStrictSubclass(topmost)) {
+    } else if (closedWorld.hasAnyStrictSubclass(topmost)) {
       return new FlatTypeMask.nonNullSubclass(topmost);
     } else {
-      return new TypeMask.nonNullExact(topmost, classWorld);
+      return new TypeMask.nonNullExact(topmost, closedWorld);
     }
   }
 
-  factory TypeMask.nonNullSubtype(ClassElement base, ClassWorld classWorld) {
-    ClassElement topmost = classWorld.getLubOfInstantiatedSubtypes(base);
+  factory TypeMask.nonNullSubtype(ClassElement base, ClosedWorld closedWorld) {
+    ClassElement topmost = closedWorld.getLubOfInstantiatedSubtypes(base);
     if (topmost == null) {
       return new TypeMask.nonNullEmpty();
     }
-    if (classWorld.hasOnlySubclasses(topmost)) {
-      return new TypeMask.nonNullSubclass(topmost, classWorld);
+    if (closedWorld.hasOnlySubclasses(topmost)) {
+      return new TypeMask.nonNullSubclass(topmost, closedWorld);
     }
-    if (classWorld.hasAnyStrictSubtype(topmost)) {
+    if (closedWorld.hasAnyStrictSubtype(topmost)) {
       return new FlatTypeMask.nonNullSubtype(topmost);
     } else {
-      return new TypeMask.nonNullExact(topmost, classWorld);
+      return new TypeMask.nonNullExact(topmost, closedWorld);
     }
   }
 
-  factory TypeMask.unionOf(Iterable<TypeMask> masks, ClassWorld classWorld) {
-    return UnionTypeMask.unionOf(masks, classWorld);
+  factory TypeMask.unionOf(Iterable<TypeMask> masks, ClosedWorld closedWorld) {
+    return UnionTypeMask.unionOf(masks, closedWorld);
   }
 
   /**
@@ -192,39 +193,39 @@
    * subclasses exist. We also normalize exact to empty if the corresponding
    * baseclass was never instantiated.
    */
-  static bool assertIsNormalized(TypeMask mask, ClassWorld classWorld) {
-    String reason = getNotNormalizedReason(mask, classWorld);
+  static bool assertIsNormalized(TypeMask mask, ClosedWorld closedWorld) {
+    String reason = getNotNormalizedReason(mask, closedWorld);
     return invariant(NO_LOCATION_SPANNABLE, reason == null,
         message: () => '$mask is not normalized: $reason');
   }
 
-  static String getNotNormalizedReason(TypeMask mask, ClassWorld classWorld) {
+  static String getNotNormalizedReason(TypeMask mask, ClosedWorld closedWorld) {
     mask = nonForwardingMask(mask);
     if (mask is FlatTypeMask) {
       if (mask.isEmptyOrNull) return null;
       if (mask.isExact) {
-        if (!classWorld.isInstantiated(mask.base)) {
+        if (!closedWorld.isInstantiated(mask.base)) {
           return 'Exact ${mask.base} is not instantiated.';
         }
         return null;
       }
       if (mask.isSubclass) {
-        if (!classWorld.hasAnyStrictSubclass(mask.base)) {
+        if (!closedWorld.hasAnyStrictSubclass(mask.base)) {
           return 'Subclass ${mask.base} does not have any subclasses.';
         }
         return null;
       }
       assert(mask.isSubtype);
-      if (!classWorld.hasAnyStrictSubtype(mask.base)) {
+      if (!closedWorld.hasAnyStrictSubtype(mask.base)) {
         return 'Subtype ${mask.base} does not have any subclasses.';
       }
-      if (classWorld.hasOnlySubclasses(mask.base)) {
+      if (closedWorld.hasOnlySubclasses(mask.base)) {
         return 'Subtype ${mask.base} only has subclasses.';
       }
       return null;
     } else if (mask is UnionTypeMask) {
       for (TypeMask submask in mask.disjointMasks) {
-        String submaskReason = getNotNormalizedReason(submask, classWorld);
+        String submaskReason = getNotNormalizedReason(submask, closedWorld);
         if (submaskReason != null) {
           return 'Submask $submask in $mask: $submaskReason.';
         }
@@ -281,11 +282,11 @@
   /// Returns `true` if this mask holds encodes an exact value within a type.
   bool get isValue;
 
-  bool containsOnlyInt(ClassWorld classWorld);
-  bool containsOnlyDouble(ClassWorld classWorld);
-  bool containsOnlyNum(ClassWorld classWorld);
-  bool containsOnlyBool(ClassWorld classWorld);
-  bool containsOnlyString(ClassWorld classWorld);
+  bool containsOnlyInt(ClosedWorld closedWorld);
+  bool containsOnlyDouble(ClosedWorld closedWorld);
+  bool containsOnlyNum(ClosedWorld closedWorld);
+  bool containsOnlyBool(ClosedWorld closedWorld);
+  bool containsOnlyString(ClosedWorld closedWorld);
   bool containsOnly(ClassElement element);
 
   /**
@@ -302,7 +303,7 @@
    * Enable [UnionTypeMask.PERFORM_EXTRA_CONTAINS_CHECK] to be notified of
    * false negatives.
    */
-  bool isInMask(TypeMask other, ClassWorld classWorld);
+  bool isInMask(TypeMask other, ClosedWorld closedWorld);
 
   /**
    * If this returns `true`, [other] is guaranteed to be a subtype of this mask,
@@ -310,48 +311,48 @@
    * Enable [UnionTypeMask.PERFORM_EXTRA_CONTAINS_CHECK] to be notified of
    * false negatives.
    */
-  bool containsMask(TypeMask other, ClassWorld classWorld);
+  bool containsMask(TypeMask other, ClosedWorld closedWorld);
 
   /**
    * Returns whether this type mask is an instance of [cls].
    */
-  bool satisfies(ClassElement cls, ClassWorld classWorld);
+  bool satisfies(ClassElement cls, ClosedWorld closedWorld);
 
   /**
    * Returns whether or not this type mask contains the given type.
    */
-  bool contains(ClassElement type, ClassWorld classWorld);
+  bool contains(ClassElement type, ClosedWorld closedWorld);
 
   /**
    * Returns whether or not this type mask contains all types.
    */
-  bool containsAll(ClassWorld classWorld);
+  bool containsAll(ClosedWorld closedWorld);
 
   /**
    * Returns the [ClassElement] if this type represents a single class,
    * otherwise returns `null`.  This method is conservative.
    */
-  ClassElement singleClass(ClassWorld classWorld);
+  ClassElement singleClass(ClosedWorld closedWorld);
 
   /**
    * Returns a type mask representing the union of [this] and [other].
    */
-  TypeMask union(TypeMask other, ClassWorld classWorld);
+  TypeMask union(TypeMask other, ClosedWorld closedWorld);
 
   /// Returns whether the intersection of this and [other] is empty.
-  bool isDisjoint(TypeMask other, ClassWorld classWorld);
+  bool isDisjoint(TypeMask other, ClosedWorld closedWorld);
 
   /**
    * Returns a type mask representing the intersection of [this] and [other].
    */
-  TypeMask intersection(TypeMask other, ClassWorld classWorld);
+  TypeMask intersection(TypeMask other, ClosedWorld closedWorld);
 
   /**
    * Returns whether [element] is a potential target when being
    * invoked on this type mask. [selector] is used to ensure library
    * privacy is taken into account.
    */
-  bool canHit(Element element, Selector selector, ClassWorld classWorld);
+  bool canHit(Element element, Selector selector, ClosedWorld closedWorld);
 
   /**
    * Returns the [element] that is known to always be hit at runtime
diff --git a/pkg/compiler/lib/src/types/union_type_mask.dart b/pkg/compiler/lib/src/types/union_type_mask.dart
index 32e4e2a..8e4aa39 100644
--- a/pkg/compiler/lib/src/types/union_type_mask.dart
+++ b/pkg/compiler/lib/src/types/union_type_mask.dart
@@ -19,30 +19,30 @@
     assert(disjointMasks.every((TypeMask mask) => !mask.isUnion));
   }
 
-  static TypeMask unionOf(Iterable<TypeMask> masks, ClassWorld classWorld) {
+  static TypeMask unionOf(Iterable<TypeMask> masks, ClosedWorld closedWorld) {
     assert(
-        masks.every((mask) => TypeMask.assertIsNormalized(mask, classWorld)));
+        masks.every((mask) => TypeMask.assertIsNormalized(mask, closedWorld)));
     List<FlatTypeMask> disjoint = <FlatTypeMask>[];
-    unionOfHelper(masks, disjoint, classWorld);
+    unionOfHelper(masks, disjoint, closedWorld);
     if (disjoint.isEmpty) return new TypeMask.nonNullEmpty();
     if (disjoint.length > MAX_UNION_LENGTH) {
-      return flatten(disjoint, classWorld);
+      return flatten(disjoint, closedWorld);
     }
     if (disjoint.length == 1) return disjoint[0];
     UnionTypeMask union = new UnionTypeMask._internal(disjoint);
-    assert(TypeMask.assertIsNormalized(union, classWorld));
+    assert(TypeMask.assertIsNormalized(union, closedWorld));
     return union;
   }
 
   static void unionOfHelper(Iterable<TypeMask> masks,
-      List<FlatTypeMask> disjoint, ClassWorld classWorld) {
+      List<FlatTypeMask> disjoint, ClosedWorld closedWorld) {
     // TODO(johnniwinther): Impose an order on the mask to ensure subclass masks
     // are preferred to subtype masks.
     for (TypeMask mask in masks) {
       mask = TypeMask.nonForwardingMask(mask);
       if (mask.isUnion) {
         UnionTypeMask union = mask;
-        unionOfHelper(union.disjointMasks, disjoint, classWorld);
+        unionOfHelper(union.disjointMasks, disjoint, closedWorld);
       } else if (mask.isEmpty) {
         continue;
       } else {
@@ -55,7 +55,7 @@
         for (int i = 0; i < disjoint.length; i++) {
           FlatTypeMask current = disjoint[i];
           if (current == null) continue;
-          TypeMask newMask = flatMask.union(current, classWorld);
+          TypeMask newMask = flatMask.union(current, closedWorld);
           // If we have found a disjoint union, continue iterating.
           if (newMask.isUnion) continue;
           covered = true;
@@ -87,7 +87,7 @@
     }
   }
 
-  static TypeMask flatten(List<FlatTypeMask> masks, ClassWorld classWorld) {
+  static TypeMask flatten(List<FlatTypeMask> masks, ClosedWorld closedWorld) {
     assert(masks.length > 1);
     // If either type mask is a subtype type mask, we cannot use a
     // subclass type mask to represent their union.
@@ -96,7 +96,7 @@
 
     List<ClassElement> masksBases = masks.map((mask) => mask.base).toList();
     Iterable<ClassElement> candidates =
-        classWorld.commonSupertypesOf(masksBases);
+        closedWorld.commonSupertypesOf(masksBases);
 
     // Compute the best candidate and its kind.
     ClassElement bestElement;
@@ -105,8 +105,8 @@
     for (ClassElement candidate in candidates) {
       bool isInstantiatedStrictSubclass(cls) =>
           cls != candidate &&
-          classWorld.isDirectlyInstantiated(cls) &&
-          classWorld.isSubclassOf(cls, candidate);
+          closedWorld.isDirectlyInstantiated(cls) &&
+          closedWorld.isSubclassOf(cls, candidate);
 
       int size;
       int kind;
@@ -119,11 +119,11 @@
         // TODO(sigmund, johnniwinther): computing length here (and below) is
         // expensive. If we can't prevent `flatten` from being called a lot, it
         // might be worth caching results.
-        size = classWorld.strictSubclassCount(candidate);
-        assert(size <= classWorld.strictSubtypeCount(candidate));
+        size = closedWorld.strictSubclassCount(candidate);
+        assert(size <= closedWorld.strictSubtypeCount(candidate));
       } else {
         kind = FlatTypeMask.SUBTYPE;
-        size = classWorld.strictSubtypeCount(candidate);
+        size = closedWorld.strictSubtypeCount(candidate);
       }
       // Update the best candidate if the new one is better.
       if (bestElement == null || size < bestSize) {
@@ -132,10 +132,10 @@
         bestKind = kind;
       }
     }
-    return new TypeMask(bestElement, bestKind, isNullable, classWorld);
+    return new TypeMask(bestElement, bestKind, isNullable, closedWorld);
   }
 
-  TypeMask union(var other, ClassWorld classWorld) {
+  TypeMask union(var other, ClosedWorld closedWorld) {
     other = TypeMask.nonForwardingMask(other);
     if (!other.isUnion && disjointMasks.contains(other)) return this;
 
@@ -146,10 +146,10 @@
       assert(other is UnionTypeMask);
       newList.addAll(other.disjointMasks);
     }
-    return new TypeMask.unionOf(newList, classWorld);
+    return new TypeMask.unionOf(newList, closedWorld);
   }
 
-  TypeMask intersection(var other, ClassWorld classWorld) {
+  TypeMask intersection(var other, ClosedWorld closedWorld) {
     other = TypeMask.nonForwardingMask(other);
     if (!other.isUnion && disjointMasks.contains(other)) return other;
     if (other.isUnion && this == other) return this;
@@ -161,19 +161,19 @@
           intersections.add(current);
         } else {
           for (FlatTypeMask flatOther in other.disjointMasks) {
-            intersections.add(current.intersection(flatOther, classWorld));
+            intersections.add(current.intersection(flatOther, closedWorld));
           }
         }
       } else {
-        intersections.add(current.intersection(other, classWorld));
+        intersections.add(current.intersection(other, closedWorld));
       }
     }
-    return new TypeMask.unionOf(intersections, classWorld);
+    return new TypeMask.unionOf(intersections, closedWorld);
   }
 
-  bool isDisjoint(TypeMask other, ClassWorld classWorld) {
+  bool isDisjoint(TypeMask other, ClosedWorld closedWorld) {
     for (var current in disjointMasks) {
-      if (!current.isDisjoint(other, classWorld)) return false;
+      if (!current.isDisjoint(other, closedWorld)) return false;
     }
     return true;
   }
@@ -212,34 +212,36 @@
    * - the cheap test matching against individual members of [disjointMasks]
    *   must have failed.
    */
-  bool slowContainsCheck(TypeMask other, ClassWorld classWorld) {
+  bool slowContainsCheck(TypeMask other, ClosedWorld closedWorld) {
     // Unions should never make it here.
     assert(!other.isUnion);
     // Ensure the cheap test fails.
-    assert(!disjointMasks.any((mask) => mask.containsMask(other, classWorld)));
+    assert(!disjointMasks.any((mask) => mask.containsMask(other, closedWorld)));
     // If we cover object, we should never get here.
-    assert(!contains(classWorld.objectClass, classWorld));
+    assert(!contains(closedWorld.coreClasses.objectClass, closedWorld));
     // Likewise, nullness should be covered.
     assert(isNullable || !other.isNullable);
     // The fast test is precise for exact types.
     if (other.isExact) return false;
     // We cannot contain object.
-    if (other.contains(classWorld.objectClass, classWorld)) return false;
+    if (other.contains(closedWorld.coreClasses.objectClass, closedWorld)) {
+      return false;
+    }
     FlatTypeMask flat = TypeMask.nonForwardingMask(other);
     // Check we cover the base class.
-    if (!contains(flat.base, classWorld)) return false;
+    if (!contains(flat.base, closedWorld)) return false;
     // Check for other members.
     Iterable<ClassElement> members;
     if (flat.isSubclass) {
-      members = classWorld.strictSubclassesOf(flat.base);
+      members = closedWorld.strictSubclassesOf(flat.base);
     } else {
       assert(flat.isSubtype);
-      members = classWorld.strictSubtypesOf(flat.base);
+      members = closedWorld.strictSubtypesOf(flat.base);
     }
-    return members.every((ClassElement cls) => this.contains(cls, classWorld));
+    return members.every((ClassElement cls) => this.contains(cls, closedWorld));
   }
 
-  bool isInMask(TypeMask other, ClassWorld classWorld) {
+  bool isInMask(TypeMask other, ClosedWorld closedWorld) {
     other = TypeMask.nonForwardingMask(other);
     if (isNullable && !other.isNullable) return false;
     if (other.isUnion) {
@@ -250,7 +252,7 @@
         // context, so we can safely ignore it here.
         FlatTypeMask maskDisregardNull = mask.nonNullable();
         return masks.any((FlatTypeMask other) {
-          return other.containsMask(maskDisregardNull, classWorld);
+          return other.containsMask(maskDisregardNull, closedWorld);
         });
       }
 
@@ -258,77 +260,77 @@
         bool contained = containedInAnyOf(disjointMask, union.disjointMasks);
         if (PERFORM_EXTRA_CONTAINS_CHECK &&
             !contained &&
-            union.slowContainsCheck(disjointMask, classWorld)) {
+            union.slowContainsCheck(disjointMask, closedWorld)) {
           throw "TypeMask based containment check failed for $this and $other.";
         }
         return contained;
       });
     }
-    return disjointMasks.every((mask) => mask.isInMask(other, classWorld));
+    return disjointMasks.every((mask) => mask.isInMask(other, closedWorld));
   }
 
-  bool containsMask(TypeMask other, ClassWorld classWorld) {
+  bool containsMask(TypeMask other, ClosedWorld closedWorld) {
     other = TypeMask.nonForwardingMask(other);
     if (other.isNullable && !isNullable) return false;
-    if (other.isUnion) return other.isInMask(this, classWorld);
+    if (other.isUnion) return other.isInMask(this, closedWorld);
     other = other.nonNullable(); // nullable is not canonicalized, so drop it.
     bool contained =
-        disjointMasks.any((mask) => mask.containsMask(other, classWorld));
+        disjointMasks.any((mask) => mask.containsMask(other, closedWorld));
     if (PERFORM_EXTRA_CONTAINS_CHECK &&
         !contained &&
-        slowContainsCheck(other, classWorld)) {
+        slowContainsCheck(other, closedWorld)) {
       throw "TypeMask based containment check failed for $this and $other.";
     }
     return contained;
   }
 
-  bool containsOnlyInt(ClassWorld classWorld) {
-    return disjointMasks.every((mask) => mask.containsOnlyInt(classWorld));
+  bool containsOnlyInt(ClosedWorld closedWorld) {
+    return disjointMasks.every((mask) => mask.containsOnlyInt(closedWorld));
   }
 
-  bool containsOnlyDouble(ClassWorld classWorld) {
-    return disjointMasks.every((mask) => mask.containsOnlyDouble(classWorld));
+  bool containsOnlyDouble(ClosedWorld closedWorld) {
+    return disjointMasks.every((mask) => mask.containsOnlyDouble(closedWorld));
   }
 
-  bool containsOnlyNum(ClassWorld classWorld) {
+  bool containsOnlyNum(ClosedWorld closedWorld) {
     return disjointMasks.every((mask) {
-      return mask.containsOnlyNum(classWorld);
+      return mask.containsOnlyNum(closedWorld);
     });
   }
 
-  bool containsOnlyBool(ClassWorld classWorld) {
-    return disjointMasks.every((mask) => mask.containsOnlyBool(classWorld));
+  bool containsOnlyBool(ClosedWorld closedWorld) {
+    return disjointMasks.every((mask) => mask.containsOnlyBool(closedWorld));
   }
 
-  bool containsOnlyString(ClassWorld classWorld) {
-    return disjointMasks.every((mask) => mask.containsOnlyString(classWorld));
+  bool containsOnlyString(ClosedWorld closedWorld) {
+    return disjointMasks.every((mask) => mask.containsOnlyString(closedWorld));
   }
 
   bool containsOnly(ClassElement element) {
     return disjointMasks.every((mask) => mask.containsOnly(element));
   }
 
-  bool satisfies(ClassElement cls, ClassWorld classWorld) {
-    return disjointMasks.every((mask) => mask.satisfies(cls, classWorld));
+  bool satisfies(ClassElement cls, ClosedWorld closedWorld) {
+    return disjointMasks.every((mask) => mask.satisfies(cls, closedWorld));
   }
 
-  bool contains(ClassElement type, ClassWorld classWorld) {
-    return disjointMasks.any((e) => e.contains(type, classWorld));
+  bool contains(ClassElement type, ClosedWorld closedWorld) {
+    return disjointMasks.any((e) => e.contains(type, closedWorld));
   }
 
-  bool containsAll(ClassWorld classWorld) {
-    return disjointMasks.any((mask) => mask.containsAll(classWorld));
+  bool containsAll(ClosedWorld closedWorld) {
+    return disjointMasks.any((mask) => mask.containsAll(closedWorld));
   }
 
-  ClassElement singleClass(ClassWorld classWorld) => null;
+  ClassElement singleClass(ClosedWorld closedWorld) => null;
 
-  bool needsNoSuchMethodHandling(Selector selector, ClassWorld classWorld) {
+  bool needsNoSuchMethodHandling(Selector selector, ClosedWorld closedWorld) {
     return disjointMasks
-        .any((e) => e.needsNoSuchMethodHandling(selector, classWorld));
+        .any((e) => e.needsNoSuchMethodHandling(selector, closedWorld));
   }
 
-  bool canHit(Element element, Selector selector, ClassWorld classWorld) {
-    return disjointMasks.any((e) => e.canHit(element, selector, classWorld));
+  bool canHit(Element element, Selector selector, ClosedWorld closedWorld) {
+    return disjointMasks.any((e) => e.canHit(element, selector, closedWorld));
   }
 
   Element locateSingleElement(Selector selector, Compiler compiler) {
diff --git a/pkg/compiler/lib/src/universe/feature.dart b/pkg/compiler/lib/src/universe/feature.dart
index a7fd61f..580da8b 100644
--- a/pkg/compiler/lib/src/universe/feature.dart
+++ b/pkg/compiler/lib/src/universe/feature.dart
@@ -43,6 +43,9 @@
   /// A field without an initializer.
   FIELD_WITHOUT_INITIALIZER,
 
+  /// A local variable without an initializer.
+  LOCAL_WITHOUT_INITIALIZER,
+
   /// A field whose initialization is not a constant.
   LAZY_FIELD,
 
diff --git a/pkg/compiler/lib/src/universe/function_set.dart b/pkg/compiler/lib/src/universe/function_set.dart
index afa0951..c34ae91 100644
--- a/pkg/compiler/lib/src/universe/function_set.dart
+++ b/pkg/compiler/lib/src/universe/function_set.dart
@@ -9,7 +9,7 @@
 import '../elements/elements.dart';
 import '../types/types.dart';
 import '../util/util.dart' show Hashing, Setlet;
-import '../world.dart' show ClassWorld;
+import '../world.dart' show ClosedWorld;
 import 'selector.dart' show Selector;
 import 'universe.dart' show ReceiverConstraint;
 
@@ -21,7 +21,7 @@
   final Map<String, FunctionSetNode> nodes = new Map<String, FunctionSetNode>();
   FunctionSet(this.compiler);
 
-  ClassWorld get classWorld => compiler.world;
+  ClosedWorld get closedWorld => compiler.closedWorld;
 
   FunctionSetNode newNode(String name) => new FunctionSetNode(name);
 
@@ -64,15 +64,17 @@
   /// set of classes that actually implement the selected member or implement
   /// the handling 'noSuchMethod' where the selected member is unimplemented.
   TypeMask receiverType(Selector selector, ReceiverConstraint constraint) {
-    return query(selector, constraint).computeMask(classWorld);
+    return query(selector, constraint).computeMask(closedWorld);
   }
 
-  SelectorMask _createSelectorMask(
-      Selector selector, ReceiverConstraint constraint, ClassWorld classWorld) {
+  SelectorMask _createSelectorMask(Selector selector,
+      ReceiverConstraint constraint, ClosedWorld closedWorld) {
     return constraint != null
         ? new SelectorMask(selector, constraint)
-        : new SelectorMask(selector,
-            new TypeMask.subclass(classWorld.objectClass, classWorld));
+        : new SelectorMask(
+            selector,
+            new TypeMask.subclass(
+                closedWorld.coreClasses.objectClass, closedWorld));
   }
 
   /// Returns the set of functions that can be the target of a call to
@@ -81,21 +83,21 @@
   FunctionSetQuery query(Selector selector, ReceiverConstraint constraint) {
     String name = selector.name;
     SelectorMask selectorMask =
-        _createSelectorMask(selector, constraint, classWorld);
+        _createSelectorMask(selector, constraint, closedWorld);
     SelectorMask noSuchMethodMask =
         new SelectorMask(Selectors.noSuchMethod_, selectorMask.constraint);
     FunctionSetNode node = nodes[name];
     FunctionSetNode noSuchMethods = nodes[Identifiers.noSuchMethod_];
     if (node != null) {
       return node.query(
-          selectorMask, classWorld, noSuchMethods, noSuchMethodMask);
+          selectorMask, closedWorld, noSuchMethods, noSuchMethodMask);
     }
     // If there is no method that matches [selector] we know we can
     // only hit [:noSuchMethod:].
     if (noSuchMethods == null) {
       return const EmptyFunctionSetQuery();
     }
-    return noSuchMethods.query(noSuchMethodMask, classWorld);
+    return noSuchMethods.query(noSuchMethodMask, closedWorld);
   }
 
   void forEach(Function action) {
@@ -122,13 +124,13 @@
 
   String get name => selector.name;
 
-  bool applies(Element element, ClassWorld classWorld) {
-    if (!selector.appliesUnnamed(element, classWorld)) return false;
-    return constraint.canHit(element, selector, classWorld);
+  bool applies(Element element, ClosedWorld closedWorld) {
+    if (!selector.appliesUnnamed(element, closedWorld.backend)) return false;
+    return constraint.canHit(element, selector, closedWorld);
   }
 
-  bool needsNoSuchMethodHandling(ClassWorld classWorld) {
-    return constraint.needsNoSuchMethodHandling(selector, classWorld);
+  bool needsNoSuchMethodHandling(ClosedWorld closedWorld) {
+    return constraint.needsNoSuchMethodHandling(selector, closedWorld);
   }
 
   bool operator ==(other) {
@@ -203,7 +205,7 @@
 
   /// Returns the set of functions that can be the target of [selectorMask]
   /// including no such method handling where applicable.
-  FunctionSetQuery query(SelectorMask selectorMask, ClassWorld classWorld,
+  FunctionSetQuery query(SelectorMask selectorMask, ClosedWorld closedWorld,
       [FunctionSetNode noSuchMethods, SelectorMask noSuchMethodMask]) {
     assert(selectorMask.name == name);
     FunctionSetQuery result = cache[selectorMask];
@@ -211,7 +213,7 @@
 
     Setlet<Element> functions;
     for (Element element in elements) {
-      if (selectorMask.applies(element, classWorld)) {
+      if (selectorMask.applies(element, closedWorld)) {
         if (functions == null) {
           // Defer the allocation of the functions set until we are
           // sure we need it. This allows us to return immutable empty
@@ -226,9 +228,9 @@
     // add [noSuchMethod] implementations that apply to [mask] as
     // potential targets.
     if (noSuchMethods != null &&
-        selectorMask.needsNoSuchMethodHandling(classWorld)) {
+        selectorMask.needsNoSuchMethodHandling(closedWorld)) {
       FunctionSetQuery noSuchMethodQuery =
-          noSuchMethods.query(noSuchMethodMask, classWorld);
+          noSuchMethods.query(noSuchMethodMask, closedWorld);
       if (!noSuchMethodQuery.functions.isEmpty) {
         if (functions == null) {
           functions = new Setlet<Element>.from(noSuchMethodQuery.functions);
@@ -250,7 +252,7 @@
   const FunctionSetQuery();
 
   /// Compute the type of all potential receivers of this function set.
-  TypeMask computeMask(ClassWorld classWorld);
+  TypeMask computeMask(ClosedWorld closedWorld);
 
   /// Returns all potential targets of this function set.
   Iterable<Element> get functions;
@@ -260,7 +262,8 @@
   const EmptyFunctionSetQuery();
 
   @override
-  TypeMask computeMask(ClassWorld classWorld) => const TypeMask.nonNullEmpty();
+  TypeMask computeMask(ClosedWorld closedWorld) =>
+      const TypeMask.nonNullEmpty();
 
   @override
   Iterable<Element> get functions => const <Element>[];
@@ -275,23 +278,24 @@
   FullFunctionSetQuery(this.functions);
 
   @override
-  TypeMask computeMask(ClassWorld classWorld) {
-    assert(classWorld.hasAnyStrictSubclass(classWorld.objectClass));
+  TypeMask computeMask(ClosedWorld closedWorld) {
+    assert(
+        closedWorld.hasAnyStrictSubclass(closedWorld.coreClasses.objectClass));
     if (_mask != null) return _mask;
     return _mask = new TypeMask.unionOf(
         functions.expand((element) {
           ClassElement cls = element.enclosingClass;
-          return [cls]..addAll(classWorld.mixinUsesOf(cls));
+          return [cls]..addAll(closedWorld.mixinUsesOf(cls));
         }).map((cls) {
-          if (classWorld.backend.isNullImplementation(cls)) {
+          if (closedWorld.backend.isNullImplementation(cls)) {
             return const TypeMask.empty();
-          } else if (classWorld.isInstantiated(cls.declaration)) {
-            return new TypeMask.nonNullSubclass(cls.declaration, classWorld);
+          } else if (closedWorld.isInstantiated(cls.declaration)) {
+            return new TypeMask.nonNullSubclass(cls.declaration, closedWorld);
           } else {
             // TODO(johnniwinther): Avoid the need for this case.
             return const TypeMask.empty();
           }
         }),
-        classWorld);
+        closedWorld);
   }
 }
diff --git a/pkg/compiler/lib/src/universe/selector.dart b/pkg/compiler/lib/src/universe/selector.dart
index 19ce7c6..14d8b3a 100644
--- a/pkg/compiler/lib/src/universe/selector.dart
+++ b/pkg/compiler/lib/src/universe/selector.dart
@@ -16,7 +16,7 @@
         LibraryElement,
         PublicName;
 import '../util/util.dart' show Hashing;
-import '../world.dart' show World;
+import '../common/resolution.dart' show Target;
 import 'call_structure.dart' show CallStructure;
 
 class SelectorKind {
@@ -217,20 +217,20 @@
     return kind;
   }
 
-  bool appliesUnnamed(Element element, World world) {
-    assert(sameNameHack(element, world));
-    return appliesUntyped(element, world);
+  bool appliesUnnamed(Element element, Target target) {
+    assert(sameNameHack(element));
+    return appliesUntyped(element, target);
   }
 
-  bool appliesUntyped(Element element, World world) {
-    assert(sameNameHack(element, world));
+  bool appliesUntyped(Element element, Target target) {
+    assert(sameNameHack(element));
     if (Elements.isUnresolved(element)) return false;
     if (memberName.isPrivate && memberName.library != element.library) {
       // TODO(johnniwinther): Maybe this should be
       // `memberName != element.memberName`.
       return false;
     }
-    if (world.isForeign(element)) return true;
+    if (target.isForeign(element)) return true;
     if (element.isSetter) return isSetter;
     if (element.isGetter) return isGetter || isCall;
     if (element.isField) {
@@ -248,14 +248,14 @@
     return callStructure.signatureApplies(function.functionSignature);
   }
 
-  bool sameNameHack(Element element, World world) {
+  bool sameNameHack(Element element) {
     // TODO(ngeoffray): Remove workaround checks.
     return element.isConstructor || name == element.name;
   }
 
-  bool applies(Element element, World world) {
-    if (!sameNameHack(element, world)) return false;
-    return appliesUnnamed(element, world);
+  bool applies(Element element, Target target) {
+    if (!sameNameHack(element)) return false;
+    return appliesUnnamed(element, target);
   }
 
   bool match(SelectorKind kind, Name memberName, CallStructure callStructure) {
diff --git a/pkg/compiler/lib/src/universe/universe.dart b/pkg/compiler/lib/src/universe/universe.dart
index cb574bb..957b02b 100644
--- a/pkg/compiler/lib/src/universe/universe.dart
+++ b/pkg/compiler/lib/src/universe/universe.dart
@@ -11,7 +11,7 @@
 import '../dart_types.dart';
 import '../elements/elements.dart';
 import '../util/util.dart';
-import '../world.dart' show ClassWorld, World;
+import '../world.dart' show ClassWorld, ClosedWorld, OpenWorld;
 import 'selector.dart' show Selector;
 import 'use.dart' show DynamicUse, DynamicUseKind, StaticUse, StaticUseKind;
 
@@ -106,8 +106,62 @@
 /// [ClassWorld]. The concepts here and in [ClassWorld] are very similar -- in
 /// the same way that the "universe expands" you can think of this as a mutable
 /// world that is expanding as we visit and discover parts of the program.
-/// TODO(sigmund): rename to "growing/expanding/mutable world"?
-class Universe {
+// TODO(sigmund): rename to "growing/expanding/mutable world"?
+// TODO(johnniwinther): Move common implementation to a [UniverseBase] when
+// universes and worlds have been unified.
+abstract class Universe {
+  /// All directly instantiated classes, that is, classes with a generative
+  /// constructor that has been called directly and not only through a
+  /// super-call.
+  // TODO(johnniwinther): Improve semantic precision.
+  Iterable<ClassElement> get directlyInstantiatedClasses;
+
+  /// All types that are checked either through is, as or checked mode checks.
+  Iterable<DartType> get isChecks;
+
+  /// Registers that [type] is checked in this universe. The unaliased type is
+  /// returned.
+  DartType registerIsCheck(DartType type, Compiler compiler);
+
+  /// All directly instantiated types, that is, the types of the directly
+  /// instantiated classes.
+  // TODO(johnniwinther): Improve semantic precision.
+  Iterable<DartType> get instantiatedTypes;
+
+  /// Returns `true` if [member] is invoked as a setter.
+  bool hasInvokedSetter(Element member, ClassWorld world);
+}
+
+abstract class ResolutionUniverse implements Universe {
+  /// Set of (live) local functions (closures) whose signatures reference type
+  /// variables.
+  ///
+  /// A live function is one whose enclosing member function has been enqueued.
+  Set<Element> get closuresWithFreeTypeVariables;
+
+  /// Set of (live) `call` methods whose signatures reference type variables.
+  ///
+  /// A live `call` method is one whose enclosing class has been instantiated.
+  Iterable<Element> get callMethodsWithFreeTypeVariables;
+
+  /// Set of all closures in the program. Used by the mirror tracking system
+  /// to find all live closure instances.
+  Iterable<LocalFunctionElement> get allClosures;
+
+  /// Set of methods in instantiated classes that are potentially closurized.
+  Iterable<Element> get closurizedMembers;
+
+  /// Returns `true` if [cls] is considered to be implemented by an
+  /// instantiated class, either directly, through subclasses or through
+  /// subtypes. The latter case only contains spurious information from
+  /// instantiations through factory constructors and mixins.
+  bool isImplemented(ClassElement cls);
+
+  /// Set of all fields that are statically known to be written to.
+  Iterable<Element> get fieldSetters;
+}
+
+class ResolutionUniverseImpl implements ResolutionUniverse {
   /// The set of all directly instantiated classes, that is, classes with a
   /// generative constructor that has been called directly and not only through
   /// a super-call.
@@ -137,8 +191,6 @@
    *
    * Invariant: Elements are declaration elements.
    */
-  final Set<FunctionElement> staticFunctionsNeedingGetter =
-      new Set<FunctionElement>();
   final Set<FunctionElement> methodsNeedingSuperGetter =
       new Set<FunctionElement>();
   final Map<String, Map<Selector, SelectorConstraints>> _invokedNames =
@@ -148,16 +200,7 @@
   final Map<String, Map<Selector, SelectorConstraints>> _invokedSetters =
       <String, Map<Selector, SelectorConstraints>>{};
 
-  /**
-   * Fields accessed. Currently only the codegen knows this
-   * information. The resolver is too conservative when seeing a
-   * getter and only registers an invoked getter.
-   */
-  final Set<Element> fieldGetters = new Set<Element>();
-
-  /**
-   * Fields set. See comment in [fieldGetters].
-   */
+  /// Fields set.
   final Set<Element> fieldSetters = new Set<Element>();
   final Set<DartType> isChecks = new Set<DartType>();
 
@@ -190,7 +233,7 @@
 
   final SelectorConstraintsStrategy selectorConstraintsStrategy;
 
-  Universe(this.selectorConstraintsStrategy);
+  ResolutionUniverseImpl(this.selectorConstraintsStrategy);
 
   /// All directly instantiated classes, that is, classes with a generative
   /// constructor that has been called directly and not only through a
@@ -256,10 +299,10 @@
   }
 
   bool _hasMatchingSelector(Map<Selector, SelectorConstraints> selectors,
-      Element member, World world) {
+      Element member, ClassWorld world) {
     if (selectors == null) return false;
     for (Selector selector in selectors.keys) {
-      if (selector.appliesUnnamed(member, world)) {
+      if (selector.appliesUnnamed(member, world.backend)) {
         SelectorConstraints masks = selectors[selector];
         if (masks.applies(member, selector, world)) {
           return true;
@@ -269,16 +312,256 @@
     return false;
   }
 
-  bool hasInvocation(Element member, World world) {
+  bool hasInvocation(Element member, OpenWorld world) {
     return _hasMatchingSelector(_invokedNames[member.name], member, world);
   }
 
-  bool hasInvokedGetter(Element member, World world) {
+  bool hasInvokedGetter(Element member, OpenWorld world) {
     return _hasMatchingSelector(_invokedGetters[member.name], member, world) ||
         member.isFunction && methodsNeedingSuperGetter.contains(member);
   }
 
-  bool hasInvokedSetter(Element member, World world) {
+  bool hasInvokedSetter(Element member, OpenWorld world) {
+    return _hasMatchingSelector(_invokedSetters[member.name], member, world);
+  }
+
+  bool registerDynamicUse(DynamicUse dynamicUse) {
+    switch (dynamicUse.kind) {
+      case DynamicUseKind.INVOKE:
+        return _registerNewSelector(dynamicUse, _invokedNames);
+      case DynamicUseKind.GET:
+        return _registerNewSelector(dynamicUse, _invokedGetters);
+      case DynamicUseKind.SET:
+        return _registerNewSelector(dynamicUse, _invokedSetters);
+    }
+  }
+
+  bool _registerNewSelector(DynamicUse dynamicUse,
+      Map<String, Map<Selector, SelectorConstraints>> selectorMap) {
+    Selector selector = dynamicUse.selector;
+    String name = selector.name;
+    ReceiverConstraint mask = dynamicUse.mask;
+    Map<Selector, SelectorConstraints> selectors = selectorMap.putIfAbsent(
+        name, () => new Maplet<Selector, SelectorConstraints>());
+    UniverseSelectorConstraints constraints =
+        selectors.putIfAbsent(selector, () {
+      return selectorConstraintsStrategy.createSelectorConstraints(selector);
+    });
+    return constraints.addReceiverConstraint(mask);
+  }
+
+  DartType registerIsCheck(DartType type, Compiler compiler) {
+    type.computeUnaliased(compiler.resolution);
+    type = type.unaliased;
+    // Even in checked mode, type annotations for return type and argument
+    // types do not imply type checks, so there should never be a check
+    // against the type variable of a typedef.
+    isChecks.add(type);
+    return type;
+  }
+
+  void registerStaticUse(StaticUse staticUse) {
+    Element element = staticUse.element;
+    if (Elements.isStaticOrTopLevel(element) && element.isField) {
+      allReferencedStaticFields.add(element);
+    }
+    switch (staticUse.kind) {
+      case StaticUseKind.SUPER_FIELD_SET:
+      case StaticUseKind.FIELD_SET:
+        fieldSetters.add(element);
+        break;
+      case StaticUseKind.SUPER_TEAR_OFF:
+        methodsNeedingSuperGetter.add(element);
+        break;
+      case StaticUseKind.GENERAL:
+      case StaticUseKind.STATIC_TEAR_OFF:
+      case StaticUseKind.FIELD_GET:
+        break;
+      case StaticUseKind.CLOSURE:
+        allClosures.add(element);
+        break;
+    }
+  }
+
+  void forgetElement(Element element, Compiler compiler) {
+    allClosures.remove(element);
+    slowDirectlyNestedClosures(element).forEach(compiler.forgetElement);
+    closurizedMembers.remove(element);
+    fieldSetters.remove(element);
+    _directlyInstantiatedClasses.remove(element);
+    if (element is ClassElement) {
+      assert(invariant(element, element.thisType.isRaw,
+          message: 'Generic classes not supported (${element.thisType}).'));
+      _instantiatedTypes..remove(element.rawType)..remove(element.thisType);
+    }
+  }
+
+  // TODO(ahe): Replace this method with something that is O(1), for example,
+  // by using a map.
+  List<LocalFunctionElement> slowDirectlyNestedClosures(Element element) {
+    // Return new list to guard against concurrent modifications.
+    return new List<LocalFunctionElement>.from(
+        allClosures.where((LocalFunctionElement closure) {
+      return closure.executableContext == element;
+    }));
+  }
+}
+
+/// Universe specific to codegen.
+///
+/// This adds additional access to liveness of selectors and elements.
+abstract class CodegenUniverse implements Universe {
+  void forEachInvokedName(
+      f(String name, Map<Selector, SelectorConstraints> selectors));
+
+  void forEachInvokedGetter(
+      f(String name, Map<Selector, SelectorConstraints> selectors));
+
+  void forEachInvokedSetter(
+      f(String name, Map<Selector, SelectorConstraints> selectors));
+
+  bool hasInvokedGetter(Element member, ClosedWorld world);
+
+  Map<Selector, SelectorConstraints> invocationsByName(String name);
+
+  Map<Selector, SelectorConstraints> getterInvocationsByName(String name);
+
+  Map<Selector, SelectorConstraints> setterInvocationsByName(String name);
+
+  Iterable<FunctionElement> get staticFunctionsNeedingGetter;
+  Iterable<FunctionElement> get methodsNeedingSuperGetter;
+
+  /// The set of all referenced static fields.
+  ///
+  /// Invariant: Elements are declaration elements.
+  Iterable<FieldElement> get allReferencedStaticFields;
+}
+
+class CodegenUniverseImpl implements CodegenUniverse {
+  /// The set of all directly instantiated classes, that is, classes with a
+  /// generative constructor that has been called directly and not only through
+  /// a super-call.
+  ///
+  /// Invariant: Elements are declaration elements.
+  // TODO(johnniwinther): [_directlyInstantiatedClasses] and
+  // [_instantiatedTypes] sets should be merged.
+  final Set<ClassElement> _directlyInstantiatedClasses =
+      new Set<ClassElement>();
+
+  /// The set of all directly instantiated types, that is, the types of the
+  /// directly instantiated classes.
+  ///
+  /// See [_directlyInstantiatedClasses].
+  final Set<DartType> _instantiatedTypes = new Set<DartType>();
+
+  /// Classes implemented by directly instantiated classes.
+  final Set<ClassElement> _implementedClasses = new Set<ClassElement>();
+
+  /// The set of all referenced static fields.
+  ///
+  /// Invariant: Elements are declaration elements.
+  final Set<FieldElement> allReferencedStaticFields = new Set<FieldElement>();
+
+  /**
+   * Documentation wanted -- johnniwinther
+   *
+   * Invariant: Elements are declaration elements.
+   */
+  final Set<FunctionElement> staticFunctionsNeedingGetter =
+      new Set<FunctionElement>();
+  final Set<FunctionElement> methodsNeedingSuperGetter =
+      new Set<FunctionElement>();
+  final Map<String, Map<Selector, SelectorConstraints>> _invokedNames =
+      <String, Map<Selector, SelectorConstraints>>{};
+  final Map<String, Map<Selector, SelectorConstraints>> _invokedGetters =
+      <String, Map<Selector, SelectorConstraints>>{};
+  final Map<String, Map<Selector, SelectorConstraints>> _invokedSetters =
+      <String, Map<Selector, SelectorConstraints>>{};
+
+  final Set<DartType> isChecks = new Set<DartType>();
+
+  final SelectorConstraintsStrategy selectorConstraintsStrategy;
+
+  CodegenUniverseImpl(this.selectorConstraintsStrategy);
+
+  /// All directly instantiated classes, that is, classes with a generative
+  /// constructor that has been called directly and not only through a
+  /// super-call.
+  // TODO(johnniwinther): Improve semantic precision.
+  Iterable<ClassElement> get directlyInstantiatedClasses {
+    return _directlyInstantiatedClasses;
+  }
+
+  /// All directly instantiated types, that is, the types of the directly
+  /// instantiated classes.
+  ///
+  /// See [directlyInstantiatedClasses].
+  // TODO(johnniwinther): Improve semantic precision.
+  Iterable<DartType> get instantiatedTypes => _instantiatedTypes;
+
+  /// Register [type] as (directly) instantiated.
+  ///
+  /// If [byMirrors] is `true`, the instantiation is through mirrors.
+  // TODO(johnniwinther): Fully enforce the separation between exact, through
+  // subclass and through subtype instantiated types/classes.
+  // TODO(johnniwinther): Support unknown type arguments for generic types.
+  void registerTypeInstantiation(InterfaceType type,
+      {bool byMirrors: false,
+      bool isNative: false,
+      void onImplemented(ClassElement cls)}) {
+    _instantiatedTypes.add(type);
+    ClassElement cls = type.element;
+    if (!cls.isAbstract
+        // We can't use the closed-world assumption with native abstract
+        // classes; a native abstract class may have non-abstract subclasses
+        // not declared to the program.  Instances of these classes are
+        // indistinguishable from the abstract class.
+        ||
+        isNative
+        // Likewise, if this registration comes from the mirror system,
+        // all bets are off.
+        // TODO(herhut): Track classes required by mirrors seperately.
+        ||
+        byMirrors) {
+      _directlyInstantiatedClasses.add(cls);
+    }
+
+    // TODO(johnniwinther): Replace this by separate more specific mappings that
+    // include the type arguments.
+    if (_implementedClasses.add(cls)) {
+      onImplemented(cls);
+      cls.allSupertypes.forEach((InterfaceType supertype) {
+        if (_implementedClasses.add(supertype.element)) {
+          onImplemented(supertype.element);
+        }
+      });
+    }
+  }
+
+  bool _hasMatchingSelector(Map<Selector, SelectorConstraints> selectors,
+      Element member, ClosedWorld world) {
+    if (selectors == null) return false;
+    for (Selector selector in selectors.keys) {
+      if (selector.appliesUnnamed(member, world.backend)) {
+        SelectorConstraints masks = selectors[selector];
+        if (masks.applies(member, selector, world)) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  bool hasInvocation(Element member, ClosedWorld world) {
+    return _hasMatchingSelector(_invokedNames[member.name], member, world);
+  }
+
+  bool hasInvokedGetter(Element member, ClosedWorld world) {
+    return _hasMatchingSelector(_invokedGetters[member.name], member, world) ||
+        member.isFunction && methodsNeedingSuperGetter.contains(member);
+  }
+
+  bool hasInvokedSetter(Element member, ClosedWorld world) {
     return _hasMatchingSelector(_invokedSetters[member.name], member, world);
   }
 
@@ -359,30 +642,19 @@
       case StaticUseKind.STATIC_TEAR_OFF:
         staticFunctionsNeedingGetter.add(element);
         break;
-      case StaticUseKind.FIELD_GET:
-        fieldGetters.add(element);
-        break;
-      case StaticUseKind.SUPER_FIELD_SET:
-      case StaticUseKind.FIELD_SET:
-        fieldSetters.add(element);
-        break;
       case StaticUseKind.SUPER_TEAR_OFF:
         methodsNeedingSuperGetter.add(element);
         break;
+      case StaticUseKind.SUPER_FIELD_SET:
+      case StaticUseKind.FIELD_SET:
       case StaticUseKind.GENERAL:
-        break;
       case StaticUseKind.CLOSURE:
-        allClosures.add(element);
+      case StaticUseKind.FIELD_GET:
         break;
     }
   }
 
   void forgetElement(Element element, Compiler compiler) {
-    allClosures.remove(element);
-    slowDirectlyNestedClosures(element).forEach(compiler.forgetElement);
-    closurizedMembers.remove(element);
-    fieldSetters.remove(element);
-    fieldGetters.remove(element);
     _directlyInstantiatedClasses.remove(element);
     if (element is ClassElement) {
       assert(invariant(element, element.thisType.isRaw,
@@ -390,14 +662,4 @@
       _instantiatedTypes..remove(element.rawType)..remove(element.thisType);
     }
   }
-
-  // TODO(ahe): Replace this method with something that is O(1), for example,
-  // by using a map.
-  List<LocalFunctionElement> slowDirectlyNestedClosures(Element element) {
-    // Return new list to guard against concurrent modifications.
-    return new List<LocalFunctionElement>.from(
-        allClosures.where((LocalFunctionElement closure) {
-      return closure.executableContext == element;
-    }));
-  }
 }
diff --git a/pkg/compiler/lib/src/universe/use.dart b/pkg/compiler/lib/src/universe/use.dart
index c1ab98f..a1756ed 100644
--- a/pkg/compiler/lib/src/universe/use.dart
+++ b/pkg/compiler/lib/src/universe/use.dart
@@ -38,7 +38,7 @@
   DynamicUse(this.selector, this.mask);
 
   bool appliesUnnamed(Element element, ClassWorld world) {
-    return selector.appliesUnnamed(element, world) &&
+    return selector.appliesUnnamed(element, world.backend) &&
         (mask == null || mask.canHit(element, selector, world));
   }
 
diff --git a/pkg/compiler/lib/src/universe/world_impact.dart b/pkg/compiler/lib/src/universe/world_impact.dart
index 99c1c3c..723a87a 100644
--- a/pkg/compiler/lib/src/universe/world_impact.dart
+++ b/pkg/compiler/lib/src/universe/world_impact.dart
@@ -61,12 +61,18 @@
   }
 }
 
-class WorldImpactBuilder {
+abstract class WorldImpactBuilder {
+  void registerDynamicUse(DynamicUse dynamicUse);
+  void registerTypeUse(TypeUse typeUse);
+  void registerStaticUse(StaticUse staticUse);
+}
+
+class WorldImpactBuilderImpl extends WorldImpact implements WorldImpactBuilder {
   // TODO(johnniwinther): Do we benefit from lazy initialization of the
   // [Setlet]s?
-  Setlet<DynamicUse> _dynamicUses;
-  Setlet<StaticUse> _staticUses;
-  Setlet<TypeUse> _typeUses;
+  Set<DynamicUse> _dynamicUses;
+  Set<StaticUse> _staticUses;
+  Set<TypeUse> _typeUses;
 
   void registerDynamicUse(DynamicUse dynamicUse) {
     assert(dynamicUse != null);
@@ -105,9 +111,60 @@
   }
 }
 
+/// [WorldImpactBuilder] that can create and collect a sequence of
+/// [WorldImpact]s.
+class StagedWorldImpactBuilder implements WorldImpactBuilder {
+  final bool collectImpacts;
+  WorldImpactBuilderImpl _currentBuilder;
+  List<WorldImpactBuilderImpl> _builders = <WorldImpactBuilderImpl>[];
+
+  StagedWorldImpactBuilder({this.collectImpacts: false});
+
+  void _ensureBuilder() {
+    if (_currentBuilder == null) {
+      _currentBuilder = new WorldImpactBuilderImpl();
+      if (collectImpacts) {
+        _builders.add(_currentBuilder);
+      }
+    }
+  }
+
+  @override
+  void registerTypeUse(TypeUse typeUse) {
+    _ensureBuilder();
+    _currentBuilder.registerTypeUse(typeUse);
+  }
+
+  @override
+  void registerDynamicUse(DynamicUse dynamicUse) {
+    _ensureBuilder();
+    _currentBuilder.registerDynamicUse(dynamicUse);
+  }
+
+  @override
+  void registerStaticUse(StaticUse staticUse) {
+    _ensureBuilder();
+    _currentBuilder.registerStaticUse(staticUse);
+  }
+
+  /// Returns the [WorldImpact] built so far with this builder. The builder
+  /// is reset, and if [collectImpacts] is `true` the impact is cached for
+  /// [worldImpacts].
+  WorldImpact flush() {
+    if (_currentBuilder == null) return const WorldImpact();
+    WorldImpact worldImpact = _currentBuilder;
+    _currentBuilder = null;
+    return worldImpact;
+  }
+
+  /// If [collectImpacts] is `true` this returns all [WorldImpact]s built with
+  /// this builder.
+  Iterable<WorldImpact> get worldImpacts => _builders;
+}
+
 /// Mutable implementation of [WorldImpact] used to transform
 /// [ResolutionImpact] or [CodegenImpact] to [WorldImpact].
-class TransformedWorldImpact implements WorldImpact {
+class TransformedWorldImpact implements WorldImpact, WorldImpactBuilder {
   final WorldImpact worldImpact;
 
   Setlet<StaticUse> _staticUses;
diff --git a/pkg/compiler/lib/src/use_unused_api.dart b/pkg/compiler/lib/src/use_unused_api.dart
index 5e0b379..da1cbdf 100644
--- a/pkg/compiler/lib/src/use_unused_api.dart
+++ b/pkg/compiler/lib/src/use_unused_api.dart
@@ -247,7 +247,7 @@
 usedByTests() {
   // TODO(ahe): We should try to avoid including API used only for tests. In
   // most cases, such API can be moved to a test library.
-  World world = null;
+  WorldImpl world = null;
   type_graph_inferrer.TypeGraphInferrer typeGraphInferrer = null;
   source_file_provider.SourceFileProvider sourceFileProvider = null;
   sourceFileProvider.getSourceFile(null);
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart
index 527240f..c348c77 100644
--- a/pkg/compiler/lib/src/world.dart
+++ b/pkg/compiler/lib/src/world.dart
@@ -20,7 +20,7 @@
         VariableElement;
 import 'js_backend/backend.dart' show JavaScriptBackend;
 import 'ordered_typeset.dart';
-import 'types/masks.dart' show TypeMask, FlatTypeMask;
+import 'types/masks.dart' show CommonMasks, FlatTypeMask, TypeMask;
 import 'universe/class_set.dart';
 import 'universe/function_set.dart' show FunctionSet;
 import 'universe/selector.dart' show Selector;
@@ -39,31 +39,45 @@
   // TODO(johnniwinther): Refine this into a `BackendClasses` interface.
   Backend get backend;
 
-  // TODO(johnniwinther): Remove the need for this getter.
+  CoreClasses get coreClasses;
+
+  /// Returns `true` if the class world is closed.
+  bool get isClosed;
+
+  /// Returns `true` if closed-world assumptions can be made, that is,
+  /// incremental compilation isn't enabled.
+  bool get hasClosedWorldAssumption;
+
+  /// Returns a string representation of the closed world.
+  ///
+  /// If [cls] is provided, the dump will contain only classes related to [cls].
+  String dump([ClassElement cls]);
+
+  /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies
+  /// of known classes.
+  ///
+  /// This method is only provided for testing. For queries on classes, use the
+  /// methods defined in [ClassWorld].
+  ClassHierarchyNode getClassHierarchyNode(ClassElement cls);
+
+  /// Returns [ClassSet] for [cls] used to model the extends and implements
+  /// relations of known classes.
+  ///
+  /// This method is only provided for testing. For queries on classes, use the
+  /// methods defined in [ClassWorld].
+  ClassSet getClassSet(ClassElement cls);
+
+  // TODO(johnniwinther): Find a better strategy for caching these.
   @deprecated
-  Compiler get compiler;
+  List<Map<ClassElement, TypeMask>> get canonicalizedTypeMasks;
+}
 
-  /// The [ClassElement] for the [Object] class defined in 'dart:core'.
-  ClassElement get objectClass;
-
-  /// The [ClassElement] for the [Function] class defined in 'dart:core'.
-  ClassElement get functionClass;
-
-  /// The [ClassElement] for the [bool] class defined in 'dart:core'.
-  ClassElement get boolClass;
-
-  /// The [ClassElement] for the [num] class defined in 'dart:core'.
-  ClassElement get numClass;
-
-  /// The [ClassElement] for the [int] class defined in 'dart:core'.
-  ClassElement get intClass;
-
-  /// The [ClassElement] for the [double] class defined in 'dart:core'.
-  ClassElement get doubleClass;
-
-  /// The [ClassElement] for the [String] class defined in 'dart:core'.
-  ClassElement get stringClass;
-
+/// The [ClosedWorld] represents the information known about a program when
+/// compiling with closed-world semantics.
+///
+/// This expands [ClassWorld] with information about live functions,
+/// side effects, and selectors with known single targets.
+abstract class ClosedWorld extends ClassWorld {
   /// Returns `true` if [cls] is either directly or indirectly instantiated.
   bool isInstantiated(ClassElement cls);
 
@@ -77,9 +91,6 @@
   /// Returns `true` if [cls] is implemented by an instantiated class.
   bool isImplemented(ClassElement cls);
 
-  /// Returns `true` if the class world is closed.
-  bool get isClosed;
-
   /// Return `true` if [x] is a subclass of [y].
   bool isSubclassOf(ClassElement x, ClassElement y);
 
@@ -178,25 +189,100 @@
   /// Returns `true` if any subclass of [superclass] implements [type].
   bool hasAnySubclassThatImplements(ClassElement superclass, ClassElement type);
 
-  /// Returns `true` if closed-world assumptions can be made, that is,
-  /// incremental compilation isn't enabled.
-  bool get hasClosedWorldAssumption;
+  /// Returns the [FunctionSet] containing all live functions in the closed
+  /// world.
+  FunctionSet get allFunctions;
 
-  /// Returns a string representation of the closed world.
-  ///
-  /// If [cls] is provided, the dump will contain only classes related to [cls].
-  String dump([ClassElement cls]);
+  /// Returns `true` if the field [element] is known to be effectively final.
+  bool fieldNeverChanges(Element element);
+
+  /// Extends the receiver type [mask] for calling [selector] to take live
+  /// `noSuchMethod` handlers into account.
+  TypeMask extendMaskIfReachesAll(Selector selector, TypeMask mask);
+
+  /// Returns all resolved typedefs.
+  Iterable<TypedefElement> get allTypedefs;
+
+  /// Returns the single [Element] that matches a call to [selector] on a
+  /// receiver of type [mask]. If multiple targets exist, `null` is returned.
+  Element locateSingleElement(Selector selector, TypeMask mask);
+
+  /// Returns the single field that matches a call to [selector] on a
+  /// receiver of type [mask]. If multiple targets exist or the single target
+  /// is not a field, `null` is returned.
+  VariableElement locateSingleField(Selector selector, TypeMask mask);
+
+  /// Returns the side effects of executing [element].
+  SideEffects getSideEffectsOfElement(Element element);
+
+  /// Returns the side effects of calling [selector] on a receiver of type
+  /// [mask].
+  SideEffects getSideEffectsOfSelector(Selector selector, TypeMask mask);
+
+  /// Returns `true` if [element] is guaranteed not to throw an exception.
+  bool getCannotThrow(Element element);
+
+  /// Returns `true` if [element] is called in a loop.
+  // TODO(johnniwinther): Is this 'potentially called' or 'known to be called'?
+  bool isCalledInLoop(Element element);
+
+  /// Returns `true` if [element] might be passed to `Function.apply`.
+  // TODO(johnniwinther): Is this 'passed invocation target` or
+  // `passed as argument`?
+  bool getMightBePassedToApply(Element element);
 }
 
-class World implements ClassWorld {
-  ClassElement get objectClass => coreClasses.objectClass;
-  ClassElement get functionClass => coreClasses.functionClass;
-  ClassElement get boolClass => coreClasses.boolClass;
-  ClassElement get numClass => coreClasses.numClass;
-  ClassElement get intClass => coreClasses.intClass;
-  ClassElement get doubleClass => coreClasses.doubleClass;
-  ClassElement get stringClass => coreClasses.stringClass;
-  ClassElement get nullClass => coreClasses.nullClass;
+/// Interface for computing side effects and uses of elements. This is used
+/// during type inference to compute the [ClosedWorld] for code generation.
+abstract class ClosedWorldRefiner {
+  /// Registers the side [effects] of executing [element].
+  void registerSideEffects(Element element, SideEffects effects);
+
+  /// Registers the executing of [element] as without side effects.
+  void registerSideEffectsFree(Element element);
+
+  /// Returns the currently known side effects of executing [element].
+  SideEffects getCurrentlyKnownSideEffects(Element element);
+
+  /// Registers that [element] might be passed to `Function.apply`.
+  // TODO(johnniwinther): Is this 'passed invocation target` or
+  // `passed as argument`?
+  void registerMightBePassedToApply(Element element);
+
+  /// Returns `true` if [element] might be passed to `Function.apply` given the
+  /// currently inferred information.
+  bool getCurrentlyKnownMightBePassedToApply(Element element);
+
+  /// Registers that [element] is called in a loop.
+  // TODO(johnniwinther): Is this 'potentially called' or 'known to be called'?
+  void addFunctionCalledInLoop(Element element);
+
+  /// Registers that [element] is guaranteed not to throw an exception.
+  void registerCannotThrow(Element element);
+
+  /// Adds the closure class [cls] to the inference world. The class is
+  /// considered directly instantiated.
+  void registerClosureClass(ClassElement cls);
+}
+
+abstract class OpenWorld implements ClassWorld {
+  /// Called to add [cls] to the set of known classes.
+  ///
+  /// This ensures that class hierarchy queries can be performed on [cls] and
+  /// classes that extend or implement it.
+  void registerClass(ClassElement cls);
+
+  void registerUsedElement(Element element);
+  void registerTypedef(TypedefElement typedef);
+
+  ClosedWorld closeWorld();
+
+  /// Returns an iterable over all mixin applications that mixin [cls].
+  Iterable<MixinApplicationElement> allMixinUsesOf(ClassElement cls);
+}
+
+class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld {
+  bool _closed = false;
 
   /// Cache of [FlatTypeMask]s grouped by the 8 possible values of the
   /// `FlatTypeMask.flags` property.
@@ -219,23 +305,25 @@
   /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an
   /// instance of [y].
   bool isSubtypeOf(ClassElement x, ClassElement y) {
+    assert(isClosed);
     assert(checkInvariants(x));
     assert(checkInvariants(y, mustBeInstantiated: false));
 
-    if (y == objectClass) return true;
-    if (x == objectClass) return false;
+    if (y == coreClasses.objectClass) return true;
+    if (x == coreClasses.objectClass) return false;
     if (x.asInstanceOf(y) != null) return true;
-    if (y != functionClass) return false;
+    if (y != coreClasses.functionClass) return false;
     return x.callType != null;
   }
 
   /// Return `true` if [x] is a (non-strict) subclass of [y].
   bool isSubclassOf(ClassElement x, ClassElement y) {
+    assert(isClosed);
     assert(checkInvariants(x));
     assert(checkInvariants(y));
 
-    if (y == objectClass) return true;
-    if (x == objectClass) return false;
+    if (y == coreClasses.objectClass) return true;
+    if (x == coreClasses.objectClass) return false;
     while (x != null && x.hierarchyDepth >= y.hierarchyDepth) {
       if (x == y) return true;
       x = x.superclass;
@@ -245,30 +333,35 @@
 
   @override
   bool isInstantiated(ClassElement cls) {
+    assert(isClosed);
     ClassHierarchyNode node = _classHierarchyNodes[cls.declaration];
     return node != null && node.isInstantiated;
   }
 
   @override
   bool isDirectlyInstantiated(ClassElement cls) {
+    assert(isClosed);
     ClassHierarchyNode node = _classHierarchyNodes[cls.declaration];
     return node != null && node.isDirectlyInstantiated;
   }
 
   @override
   bool isIndirectlyInstantiated(ClassElement cls) {
+    assert(isClosed);
     ClassHierarchyNode node = _classHierarchyNodes[cls.declaration];
     return node != null && node.isIndirectlyInstantiated;
   }
 
   /// Returns `true` if [cls] is implemented by an instantiated class.
   bool isImplemented(ClassElement cls) {
-    return compiler.resolverWorld.isImplemented(cls);
+    assert(isClosed);
+    return _compiler.resolverWorld.isImplemented(cls);
   }
 
   /// Returns an iterable over the directly instantiated classes that extend
   /// [cls] possibly including [cls] itself, if it is live.
   Iterable<ClassElement> subclassesOf(ClassElement cls) {
+    assert(isClosed);
     ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration];
     if (hierarchy == null) return const <ClassElement>[];
     return hierarchy.subclassesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED);
@@ -277,6 +370,7 @@
   /// Returns an iterable over the directly instantiated classes that extend
   /// [cls] _not_ including [cls] itself.
   Iterable<ClassElement> strictSubclassesOf(ClassElement cls) {
+    assert(isClosed);
     ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration];
     if (subclasses == null) return const <ClassElement>[];
     return subclasses.subclassesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED,
@@ -286,6 +380,7 @@
   /// Returns the number of live classes that extend [cls] _not_
   /// including [cls] itself.
   int strictSubclassCount(ClassElement cls) {
+    assert(isClosed);
     ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration];
     if (subclasses == null) return 0;
     return subclasses.instantiatedSubclassCount;
@@ -295,6 +390,7 @@
   /// itself.
   void forEachStrictSubclassOf(
       ClassElement cls, IterationStep f(ClassElement cls)) {
+    assert(isClosed);
     ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration];
     if (subclasses == null) return;
     subclasses.forEachSubclass(f, ClassHierarchyNode.DIRECTLY_INSTANTIATED,
@@ -304,6 +400,7 @@
   /// Returns `true` if [predicate] applies to any live class that extend [cls]
   /// _not_ including [cls] itself.
   bool anyStrictSubclassOf(ClassElement cls, bool predicate(ClassElement cls)) {
+    assert(isClosed);
     ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration];
     if (subclasses == null) return false;
     return subclasses.anySubclass(
@@ -314,6 +411,7 @@
   /// Returns an iterable over the directly instantiated that implement [cls]
   /// possibly including [cls] itself, if it is live.
   Iterable<ClassElement> subtypesOf(ClassElement cls) {
+    assert(isClosed);
     ClassSet classSet = _classSets[cls.declaration];
     if (classSet == null) {
       return const <ClassElement>[];
@@ -325,6 +423,7 @@
   /// Returns an iterable over the directly instantiated that implement [cls]
   /// _not_ including [cls].
   Iterable<ClassElement> strictSubtypesOf(ClassElement cls) {
+    assert(isClosed);
     ClassSet classSet = _classSets[cls.declaration];
     if (classSet == null) {
       return const <ClassElement>[];
@@ -337,6 +436,7 @@
   /// Returns the number of live classes that implement [cls] _not_
   /// including [cls] itself.
   int strictSubtypeCount(ClassElement cls) {
+    assert(isClosed);
     ClassSet classSet = _classSets[cls.declaration];
     if (classSet == null) return 0;
     return classSet.instantiatedSubtypeCount;
@@ -346,6 +446,7 @@
   /// itself.
   void forEachStrictSubtypeOf(
       ClassElement cls, IterationStep f(ClassElement cls)) {
+    assert(isClosed);
     ClassSet classSet = _classSets[cls.declaration];
     if (classSet == null) return;
     classSet.forEachSubtype(f, ClassHierarchyNode.DIRECTLY_INSTANTIATED,
@@ -355,6 +456,7 @@
   /// Returns `true` if [predicate] applies to any live class that extend [cls]
   /// _not_ including [cls] itself.
   bool anyStrictSubtypeOf(ClassElement cls, bool predicate(ClassElement cls)) {
+    assert(isClosed);
     ClassSet classSet = _classSets[cls.declaration];
     if (classSet == null) return false;
     return classSet.anySubtype(
@@ -364,6 +466,7 @@
 
   /// Returns `true` if [a] and [b] have any known common subtypes.
   bool haveAnyCommonSubtypes(ClassElement a, ClassElement b) {
+    assert(isClosed);
     ClassSet classSetA = _classSets[a.declaration];
     ClassSet classSetB = _classSets[b.declaration];
     if (classSetA == null || classSetB == null) return false;
@@ -380,6 +483,7 @@
   /// Returns `true` if any directly instantiated class other than [cls] extends
   /// [cls].
   bool hasAnyStrictSubclass(ClassElement cls) {
+    assert(isClosed);
     ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration];
     if (subclasses == null) return false;
     return subclasses.isIndirectlyInstantiated;
@@ -394,8 +498,9 @@
   /// Returns `true` if all directly instantiated classes that implement [cls]
   /// extend it.
   bool hasOnlySubclasses(ClassElement cls) {
+    assert(isClosed);
     // TODO(johnniwinther): move this to ClassSet?
-    if (cls == objectClass) return true;
+    if (cls == coreClasses.objectClass) return true;
     ClassSet classSet = _classSets[cls.declaration];
     if (classSet == null) {
       // Vacuously true.
@@ -406,6 +511,7 @@
 
   @override
   ClassElement getLubOfInstantiatedSubclasses(ClassElement cls) {
+    assert(isClosed);
     if (backend.isJsInterop(cls)) {
       return backend.helpers.jsJavaScriptObjectClass;
     }
@@ -417,6 +523,7 @@
 
   @override
   ClassElement getLubOfInstantiatedSubtypes(ClassElement cls) {
+    assert(isClosed);
     if (backend.isJsInterop(cls)) {
       return backend.helpers.jsJavaScriptObjectClass;
     }
@@ -426,6 +533,7 @@
 
   /// Returns an iterable over the common supertypes of the [classes].
   Iterable<ClassElement> commonSupertypesOf(Iterable<ClassElement> classes) {
+    assert(isClosed);
     Iterator<ClassElement> iterator = classes.iterator;
     if (!iterator.moveNext()) return const <ClassElement>[];
 
@@ -449,7 +557,7 @@
     List<ClassElement> commonSupertypes = <ClassElement>[];
     OUTER:
     for (Link<DartType> link = typeSet[depth];
-        link.head.element != objectClass;
+        link.head.element != coreClasses.objectClass;
         link = link.tail) {
       ClassElement cls = link.head.element;
       for (Link<OrderedTypeSet> link = otherTypeSets;
@@ -461,7 +569,7 @@
       }
       commonSupertypes.add(cls);
     }
-    commonSupertypes.add(objectClass);
+    commonSupertypes.add(coreClasses.objectClass);
     return commonSupertypes;
   }
 
@@ -502,12 +610,14 @@
 
   /// Returns `true` if [cls] is mixed into a live class.
   bool isUsedAsMixin(ClassElement cls) {
+    assert(isClosed);
     return !mixinUsesOf(cls).isEmpty;
   }
 
   /// Returns `true` if any live class that mixes in [cls] implements [type].
   bool hasAnySubclassOfMixinUseThatImplements(
       ClassElement cls, ClassElement type) {
+    assert(isClosed);
     return mixinUsesOf(cls)
         .any((use) => hasAnySubclassThatImplements(use, type));
   }
@@ -515,11 +625,13 @@
   /// Returns `true` if any live class that mixes in [mixin] is also a subclass
   /// of [superclass].
   bool hasAnySubclassThatMixes(ClassElement superclass, ClassElement mixin) {
+    assert(isClosed);
     return mixinUsesOf(mixin).any((each) => each.isSubclassOf(superclass));
   }
 
   /// Returns `true` if [cls] or any superclass mixes in [mixin].
   bool isSubclassOfMixinUseOf(ClassElement cls, ClassElement mixin) {
+    assert(isClosed);
     if (isUsedAsMixin(mixin)) {
       ClassElement current = cls.declaration;
       mixin = mixin.declaration;
@@ -538,6 +650,7 @@
   /// Returns `true` if every subtype of [x] is a subclass of [y] or a subclass
   /// of a mixin application of [y].
   bool everySubtypeIsSubclassOfOrMixinUseOf(ClassElement x, ClassElement y) {
+    assert(isClosed);
     x = x.declaration;
     y = y.declaration;
     Map<ClassElement, bool> secondMap =
@@ -549,18 +662,20 @@
   /// Returns `true` if any subclass of [superclass] implements [type].
   bool hasAnySubclassThatImplements(
       ClassElement superclass, ClassElement type) {
+    assert(isClosed);
     Set<ClassElement> subclasses = typesImplementedBySubclassesOf(superclass);
     if (subclasses == null) return false;
     return subclasses.contains(type);
   }
 
-  final Compiler compiler;
-  JavaScriptBackend get backend => compiler.backend;
+  final Compiler _compiler;
+  JavaScriptBackend get backend => _compiler.backend;
+  CommonMasks get commonMasks => _compiler.commonMasks;
   final FunctionSet allFunctions;
   final Set<Element> functionsCalledInLoop = new Set<Element>();
   final Map<Element, SideEffects> sideEffects = new Map<Element, SideEffects>();
 
-  final Set<TypedefElement> allTypedefs = new Set<TypedefElement>();
+  final Set<TypedefElement> _allTypedefs = new Set<TypedefElement>();
 
   final Map<ClassElement, Set<MixinApplicationElement>> _mixinUses =
       new Map<ClassElement, Set<MixinApplicationElement>>();
@@ -587,37 +702,49 @@
 
   final Set<Element> alreadyPopulated;
 
-  bool get isClosed => compiler.phase > Compiler.PHASE_RESOLVING;
+  bool get isClosed => _closed;
 
   // Used by selectors.
   bool isForeign(Element element) {
-    return compiler.backend.isForeign(element);
+    return backend.isForeign(element);
   }
 
   Set<ClassElement> typesImplementedBySubclassesOf(ClassElement cls) {
     return _typesImplementedBySubclasses[cls.declaration];
   }
 
-  World(Compiler compiler)
+  WorldImpl(Compiler compiler)
       : allFunctions = new FunctionSet(compiler),
-        this.compiler = compiler,
+        this._compiler = compiler,
         alreadyPopulated = compiler.cacheStrategy.newSet();
 
-  CoreClasses get coreClasses => compiler.coreClasses;
+  CoreClasses get coreClasses => _compiler.coreClasses;
 
-  DiagnosticReporter get reporter => compiler.reporter;
+  DiagnosticReporter get reporter => _compiler.reporter;
 
   /// Called to add [cls] to the set of known classes.
   ///
   /// This ensures that class hierarchy queries can be performed on [cls] and
   /// classes that extend or implement it.
-  void registerClass(ClassElement cls, {bool isDirectlyInstantiated: false}) {
+  void registerClass(ClassElement cls) => _registerClass(cls);
+
+  void registerClosureClass(ClassElement cls) {
+    _registerClass(cls, isDirectlyInstantiated: true);
+  }
+
+  void _registerClass(ClassElement cls, {bool isDirectlyInstantiated: false}) {
     _ensureClassSet(cls);
     if (isDirectlyInstantiated) {
       _updateClassHierarchyNodeForClass(cls, directlyInstantiated: true);
     }
   }
 
+  void registerTypedef(TypedefElement typdef) {
+    _allTypedefs.add(typdef);
+  }
+
+  Iterable<TypedefElement> get allTypedefs => _allTypedefs;
+
   /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies
   /// of known classes.
   ///
@@ -695,12 +822,12 @@
     }
   }
 
-  void populate() {
+  ClosedWorld closeWorld() {
     /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated`
     /// properties of the [ClassHierarchyNode] for [cls].
 
     void addSubtypes(ClassElement cls) {
-      if (compiler.options.hasIncrementalSupport &&
+      if (_compiler.options.hasIncrementalSupport &&
           !alreadyPopulated.add(cls)) {
         return;
       }
@@ -729,7 +856,10 @@
     // classes: if the superclass of these classes require RTI, then
     // they also need RTI, so that a constructor passes the type
     // variables to the super constructor.
-    compiler.resolverWorld.directlyInstantiatedClasses.forEach(addSubtypes);
+    _compiler.resolverWorld.directlyInstantiatedClasses.forEach(addSubtypes);
+
+    _closed = true;
+    return this;
   }
 
   @override
@@ -771,17 +901,17 @@
   }
 
   Element locateSingleElement(Selector selector, TypeMask mask) {
-    mask ??= compiler.commonMasks.dynamicType;
-    return mask.locateSingleElement(selector, compiler);
+    mask ??= commonMasks.dynamicType;
+    return mask.locateSingleElement(selector, _compiler);
   }
 
   TypeMask extendMaskIfReachesAll(Selector selector, TypeMask mask) {
     bool canReachAll = true;
     if (mask != null) {
-      canReachAll = compiler.enabledInvokeOn &&
+      canReachAll = _compiler.enabledInvokeOn &&
           mask.needsNoSuchMethodHandling(selector, this);
     }
-    return canReachAll ? compiler.commonMasks.dynamicType : mask;
+    return canReachAll ? commonMasks.dynamicType : mask;
   }
 
   void addFunctionCalledInLoop(Element element) {
@@ -806,8 +936,8 @@
       return true;
     }
     if (element.isInstanceMember) {
-      return !compiler.resolverWorld.hasInvokedSetter(element, this) &&
-          !compiler.resolverWorld.fieldSetters.contains(element);
+      return !_compiler.resolverWorld.hasInvokedSetter(element, this) &&
+          !_compiler.resolverWorld.fieldSetters.contains(element);
     }
     return false;
   }
@@ -826,6 +956,11 @@
     });
   }
 
+  @override
+  SideEffects getCurrentlyKnownSideEffects(Element element) {
+    return getSideEffectsOfElement(element);
+  }
+
   void registerSideEffects(Element element, SideEffects effects) {
     if (sideEffectsFreeElements.contains(element)) return;
     sideEffects[element.declaration] = effects;
@@ -885,5 +1020,10 @@
     return functionsThatMightBePassedToApply.contains(element);
   }
 
-  bool get hasClosedWorldAssumption => !compiler.options.hasIncrementalSupport;
+  @override
+  bool getCurrentlyKnownMightBePassedToApply(Element element) {
+    return getMightBePassedToApply(element);
+  }
+
+  bool get hasClosedWorldAssumption => !_compiler.options.hasIncrementalSupport;
 }
diff --git a/pkg/dev_compiler/STRONG_MODE.md b/pkg/dev_compiler/STRONG_MODE.md
index 9b0b792..5a83747 100644
--- a/pkg/dev_compiler/STRONG_MODE.md
+++ b/pkg/dev_compiler/STRONG_MODE.md
@@ -27,20 +27,20 @@
 However, in the following context, the info method prints “helloworld” in checked mode, without any static errors or warnings:
 
 ```dart
-import ‘dart:collection’;
-import ‘util.dart’;
+import 'dart:collection';
+import 'util.dart';
 
 class MyList extends ListBase<int> implements List {
    Object length;
 
    MyList(this.length);
 
-   operator[](index) => "world";
+   operator[](index) => 'world';
    operator[]=(index, value) {}
 }
 
 void main() {
-   List<int> list = new MyList("hello");
+   List<int> list = new MyList('hello');
    info(list);
 }
 ```
diff --git a/pkg/dev_compiler/lib/js/amd/dart_sdk.js b/pkg/dev_compiler/lib/js/amd/dart_sdk.js
index 8ec4be2..e4a67c2 100644
--- a/pkg/dev_compiler/lib/js/amd/dart_sdk.js
+++ b/pkg/dev_compiler/lib/js/amd/dart_sdk.js
@@ -4266,12 +4266,20 @@
   });
   _interceptors.JSMutableArray = JSMutableArray();
   _interceptors.JSFixedArray$ = dart.generic(E => {
-    class JSFixedArray extends _interceptors.JSMutableArray$(E) {}
+    class JSFixedArray extends _interceptors.JSMutableArray$(E) {
+      new() {
+        super.new();
+      }
+    }
     return JSFixedArray;
   });
   _interceptors.JSFixedArray = JSFixedArray();
   _interceptors.JSExtendableArray$ = dart.generic(E => {
-    class JSExtendableArray extends _interceptors.JSMutableArray$(E) {}
+    class JSExtendableArray extends _interceptors.JSMutableArray$(E) {
+      new() {
+        super.new();
+      }
+    }
     return JSExtendableArray;
   });
   _interceptors.JSExtendableArray = JSExtendableArray();
@@ -17068,6 +17076,7 @@
     class _ControllerStream extends async._StreamImpl$(T) {
       new(controller) {
         this[_controller$] = controller;
+        super.new();
       }
       [_createSubscription](onData, onError, onDone, cancelOnError) {
         return this[_controller$][_subscribe](onData, onError, onDone, cancelOnError);
@@ -20111,6 +20120,7 @@
       new(pending) {
         this[_pending] = pending;
         this[_isUsed] = false;
+        super.new();
       }
       [_createSubscription](onData, onError, onDone, cancelOnError) {
         if (dart.test(this[_isUsed])) dart.throw(new core.StateError("Stream has already been listened to."));
@@ -25577,7 +25587,7 @@
           count++;
           if (count > MAX_COUNT) {
             while (dart.notNull(length) > LENGTH_LIMIT - ELLIPSIS_SIZE - OVERHEAD && count > HEAD_COUNT) {
-              length = dart.notNull(length) - dart.notNull(core.int._check(dart.dsend(dart.dload(parts[dartx.removeLast](), 'length'), '+', OVERHEAD)));
+              length = dart.notNull(length) - dart.notNull(core.num._check(dart.dsend(dart.dload(parts[dartx.removeLast](), 'length'), '+', OVERHEAD)));
               count--;
             }
             parts[dartx.add]("...");
@@ -25595,7 +25605,7 @@
       length = dart.notNull(length) + (ELLIPSIS_SIZE + OVERHEAD);
     }
     while (dart.notNull(length) > LENGTH_LIMIT && dart.notNull(parts[dartx.length]) > HEAD_COUNT) {
-      length = dart.notNull(length) - dart.notNull(core.int._check(dart.dsend(dart.dload(parts[dartx.removeLast](), 'length'), '+', OVERHEAD)));
+      length = dart.notNull(length) - dart.notNull(core.num._check(dart.dsend(dart.dload(parts[dartx.removeLast](), 'length'), '+', OVERHEAD)));
       if (elision == null) {
         elision = "...";
         length = dart.notNull(length) + (ELLIPSIS_SIZE + OVERHEAD);
@@ -29213,6 +29223,7 @@
   convert._ErrorHandlingAsciiDecoderSink = class _ErrorHandlingAsciiDecoderSink extends convert.ByteConversionSinkBase {
     new(utf8Sink) {
       this[_utf8Sink] = utf8Sink;
+      super.new();
     }
     close() {
       this[_utf8Sink].close();
@@ -29247,6 +29258,7 @@
   convert._SimpleAsciiDecoderSink = class _SimpleAsciiDecoderSink extends convert.ByteConversionSinkBase {
     new(sink) {
       this[_sink$] = sink;
+      super.new();
     }
     close() {
       this[_sink$].close();
@@ -29535,6 +29547,9 @@
   });
   const _add$1 = Symbol('_add');
   convert._Base64EncoderSink = class _Base64EncoderSink extends convert.ByteConversionSinkBase {
+    new() {
+      super.new();
+    }
     add(source) {
       this[_add$1](source, 0, source[dartx.length], false);
     }
@@ -29557,6 +29572,7 @@
     new(sink, urlSafe) {
       this[_sink$] = sink;
       this[_encoder] = new convert._BufferCachingBase64Encoder(urlSafe);
+      super.new();
     }
     [_add$1](source, start, end, isLast) {
       let buffer = this[_encoder].encode(source, start, end, isLast);
@@ -29581,6 +29597,7 @@
     new(sink, urlSafe) {
       this[_sink$] = sink;
       this[_encoder] = new convert._Base64Encoder(urlSafe);
+      super.new();
     }
     [_add$1](source, start, end, isLast) {
       let buffer = this[_encoder].encode(source, start, end, isLast);
@@ -29932,6 +29949,7 @@
   convert._ByteAdapterSink = class _ByteAdapterSink extends convert.ByteConversionSinkBase {
     new(sink) {
       this[_sink$] = sink;
+      super.new();
     }
     add(chunk) {
       this[_sink$].add(chunk);
@@ -29956,6 +29974,7 @@
       this[_buffer] = typed_data.Uint8List.new(convert._ByteCallbackSink._INITIAL_BUFFER_SIZE);
       this[_callback] = callback;
       this[_bufferIndex] = 0;
+      super.new();
     }
     add(chunk) {
       let freeCount = dart.notNull(this[_buffer][dartx.length]) - dart.notNull(this[_bufferIndex]);
@@ -31301,6 +31320,7 @@
   convert._Latin1DecoderSink = class _Latin1DecoderSink extends convert.ByteConversionSinkBase {
     new(sink) {
       this[_sink$] = sink;
+      super.new();
     }
     close() {
       this[_sink$].close();
@@ -78396,13 +78416,13 @@
       let val = 0;
       for (let measurement of dimensions) {
         if (augmentingMeasurement == html$._MARGIN) {
-          val = dart.notNull(val) + dart.notNull(dart.asInt(new html$.Dimension.css(styles[dartx.getPropertyValue](dart.str`${augmentingMeasurement}-${measurement}`)).value));
+          val = dart.notNull(val) + dart.notNull(new html$.Dimension.css(styles[dartx.getPropertyValue](dart.str`${augmentingMeasurement}-${measurement}`)).value);
         }
         if (augmentingMeasurement == html$._CONTENT) {
-          val = dart.notNull(val) - dart.notNull(dart.asInt(new html$.Dimension.css(styles[dartx.getPropertyValue](dart.str`${html$._PADDING}-${measurement}`)).value));
+          val = dart.notNull(val) - dart.notNull(new html$.Dimension.css(styles[dartx.getPropertyValue](dart.str`${html$._PADDING}-${measurement}`)).value);
         }
         if (augmentingMeasurement != html$._MARGIN) {
-          val = dart.notNull(val) - dart.notNull(dart.asInt(new html$.Dimension.css(styles[dartx.getPropertyValue](dart.str`border-${measurement}-width`)).value));
+          val = dart.notNull(val) - dart.notNull(new html$.Dimension.css(styles[dartx.getPropertyValue](dart.str`border-${measurement}-width`)).value);
         }
       }
       return val;
diff --git a/pkg/dev_compiler/lib/js/common/dart_sdk.js b/pkg/dev_compiler/lib/js/common/dart_sdk.js
index 1b39b69..8b9f7f9 100644
--- a/pkg/dev_compiler/lib/js/common/dart_sdk.js
+++ b/pkg/dev_compiler/lib/js/common/dart_sdk.js
@@ -4266,12 +4266,20 @@
   });
   _interceptors.JSMutableArray = JSMutableArray();
   _interceptors.JSFixedArray$ = dart.generic(E => {
-    class JSFixedArray extends _interceptors.JSMutableArray$(E) {}
+    class JSFixedArray extends _interceptors.JSMutableArray$(E) {
+      new() {
+        super.new();
+      }
+    }
     return JSFixedArray;
   });
   _interceptors.JSFixedArray = JSFixedArray();
   _interceptors.JSExtendableArray$ = dart.generic(E => {
-    class JSExtendableArray extends _interceptors.JSMutableArray$(E) {}
+    class JSExtendableArray extends _interceptors.JSMutableArray$(E) {
+      new() {
+        super.new();
+      }
+    }
     return JSExtendableArray;
   });
   _interceptors.JSExtendableArray = JSExtendableArray();
@@ -17068,6 +17076,7 @@
     class _ControllerStream extends async._StreamImpl$(T) {
       new(controller) {
         this[_controller$] = controller;
+        super.new();
       }
       [_createSubscription](onData, onError, onDone, cancelOnError) {
         return this[_controller$][_subscribe](onData, onError, onDone, cancelOnError);
@@ -20111,6 +20120,7 @@
       new(pending) {
         this[_pending] = pending;
         this[_isUsed] = false;
+        super.new();
       }
       [_createSubscription](onData, onError, onDone, cancelOnError) {
         if (dart.test(this[_isUsed])) dart.throw(new core.StateError("Stream has already been listened to."));
@@ -25577,7 +25587,7 @@
           count++;
           if (count > MAX_COUNT) {
             while (dart.notNull(length) > LENGTH_LIMIT - ELLIPSIS_SIZE - OVERHEAD && count > HEAD_COUNT) {
-              length = dart.notNull(length) - dart.notNull(core.int._check(dart.dsend(dart.dload(parts[dartx.removeLast](), 'length'), '+', OVERHEAD)));
+              length = dart.notNull(length) - dart.notNull(core.num._check(dart.dsend(dart.dload(parts[dartx.removeLast](), 'length'), '+', OVERHEAD)));
               count--;
             }
             parts[dartx.add]("...");
@@ -25595,7 +25605,7 @@
       length = dart.notNull(length) + (ELLIPSIS_SIZE + OVERHEAD);
     }
     while (dart.notNull(length) > LENGTH_LIMIT && dart.notNull(parts[dartx.length]) > HEAD_COUNT) {
-      length = dart.notNull(length) - dart.notNull(core.int._check(dart.dsend(dart.dload(parts[dartx.removeLast](), 'length'), '+', OVERHEAD)));
+      length = dart.notNull(length) - dart.notNull(core.num._check(dart.dsend(dart.dload(parts[dartx.removeLast](), 'length'), '+', OVERHEAD)));
       if (elision == null) {
         elision = "...";
         length = dart.notNull(length) + (ELLIPSIS_SIZE + OVERHEAD);
@@ -29213,6 +29223,7 @@
   convert._ErrorHandlingAsciiDecoderSink = class _ErrorHandlingAsciiDecoderSink extends convert.ByteConversionSinkBase {
     new(utf8Sink) {
       this[_utf8Sink] = utf8Sink;
+      super.new();
     }
     close() {
       this[_utf8Sink].close();
@@ -29247,6 +29258,7 @@
   convert._SimpleAsciiDecoderSink = class _SimpleAsciiDecoderSink extends convert.ByteConversionSinkBase {
     new(sink) {
       this[_sink$] = sink;
+      super.new();
     }
     close() {
       this[_sink$].close();
@@ -29535,6 +29547,9 @@
   });
   const _add$1 = Symbol('_add');
   convert._Base64EncoderSink = class _Base64EncoderSink extends convert.ByteConversionSinkBase {
+    new() {
+      super.new();
+    }
     add(source) {
       this[_add$1](source, 0, source[dartx.length], false);
     }
@@ -29557,6 +29572,7 @@
     new(sink, urlSafe) {
       this[_sink$] = sink;
       this[_encoder] = new convert._BufferCachingBase64Encoder(urlSafe);
+      super.new();
     }
     [_add$1](source, start, end, isLast) {
       let buffer = this[_encoder].encode(source, start, end, isLast);
@@ -29581,6 +29597,7 @@
     new(sink, urlSafe) {
       this[_sink$] = sink;
       this[_encoder] = new convert._Base64Encoder(urlSafe);
+      super.new();
     }
     [_add$1](source, start, end, isLast) {
       let buffer = this[_encoder].encode(source, start, end, isLast);
@@ -29932,6 +29949,7 @@
   convert._ByteAdapterSink = class _ByteAdapterSink extends convert.ByteConversionSinkBase {
     new(sink) {
       this[_sink$] = sink;
+      super.new();
     }
     add(chunk) {
       this[_sink$].add(chunk);
@@ -29956,6 +29974,7 @@
       this[_buffer] = typed_data.Uint8List.new(convert._ByteCallbackSink._INITIAL_BUFFER_SIZE);
       this[_callback] = callback;
       this[_bufferIndex] = 0;
+      super.new();
     }
     add(chunk) {
       let freeCount = dart.notNull(this[_buffer][dartx.length]) - dart.notNull(this[_bufferIndex]);
@@ -31301,6 +31320,7 @@
   convert._Latin1DecoderSink = class _Latin1DecoderSink extends convert.ByteConversionSinkBase {
     new(sink) {
       this[_sink$] = sink;
+      super.new();
     }
     close() {
       this[_sink$].close();
@@ -78396,13 +78416,13 @@
       let val = 0;
       for (let measurement of dimensions) {
         if (augmentingMeasurement == html$._MARGIN) {
-          val = dart.notNull(val) + dart.notNull(dart.asInt(new html$.Dimension.css(styles[dartx.getPropertyValue](dart.str`${augmentingMeasurement}-${measurement}`)).value));
+          val = dart.notNull(val) + dart.notNull(new html$.Dimension.css(styles[dartx.getPropertyValue](dart.str`${augmentingMeasurement}-${measurement}`)).value);
         }
         if (augmentingMeasurement == html$._CONTENT) {
-          val = dart.notNull(val) - dart.notNull(dart.asInt(new html$.Dimension.css(styles[dartx.getPropertyValue](dart.str`${html$._PADDING}-${measurement}`)).value));
+          val = dart.notNull(val) - dart.notNull(new html$.Dimension.css(styles[dartx.getPropertyValue](dart.str`${html$._PADDING}-${measurement}`)).value);
         }
         if (augmentingMeasurement != html$._MARGIN) {
-          val = dart.notNull(val) - dart.notNull(dart.asInt(new html$.Dimension.css(styles[dartx.getPropertyValue](dart.str`border-${measurement}-width`)).value));
+          val = dart.notNull(val) - dart.notNull(new html$.Dimension.css(styles[dartx.getPropertyValue](dart.str`border-${measurement}-width`)).value);
         }
       }
       return val;
diff --git a/pkg/dev_compiler/lib/js/es6/dart_sdk.js b/pkg/dev_compiler/lib/js/es6/dart_sdk.js
index 5a1b9f8..c99499b 100644
--- a/pkg/dev_compiler/lib/js/es6/dart_sdk.js
+++ b/pkg/dev_compiler/lib/js/es6/dart_sdk.js
@@ -4264,12 +4264,20 @@
 });
 _interceptors.JSMutableArray = JSMutableArray();
 _interceptors.JSFixedArray$ = dart.generic(E => {
-  class JSFixedArray extends _interceptors.JSMutableArray$(E) {}
+  class JSFixedArray extends _interceptors.JSMutableArray$(E) {
+    new() {
+      super.new();
+    }
+  }
   return JSFixedArray;
 });
 _interceptors.JSFixedArray = JSFixedArray();
 _interceptors.JSExtendableArray$ = dart.generic(E => {
-  class JSExtendableArray extends _interceptors.JSMutableArray$(E) {}
+  class JSExtendableArray extends _interceptors.JSMutableArray$(E) {
+    new() {
+      super.new();
+    }
+  }
   return JSExtendableArray;
 });
 _interceptors.JSExtendableArray = JSExtendableArray();
@@ -17066,6 +17074,7 @@
   class _ControllerStream extends async._StreamImpl$(T) {
     new(controller) {
       this[_controller] = controller;
+      super.new();
     }
     [_createSubscription](onData, onError, onDone, cancelOnError) {
       return this[_controller][_subscribe](onData, onError, onDone, cancelOnError);
@@ -20109,6 +20118,7 @@
     new(pending) {
       this[_pending] = pending;
       this[_isUsed] = false;
+      super.new();
     }
     [_createSubscription](onData, onError, onDone, cancelOnError) {
       if (dart.test(this[_isUsed])) dart.throw(new core.StateError("Stream has already been listened to."));
@@ -25575,7 +25585,7 @@
         count++;
         if (count > MAX_COUNT) {
           while (dart.notNull(length) > LENGTH_LIMIT - ELLIPSIS_SIZE - OVERHEAD && count > HEAD_COUNT) {
-            length = dart.notNull(length) - dart.notNull(core.int._check(dart.dsend(dart.dload(parts[dartx.removeLast](), 'length'), '+', OVERHEAD)));
+            length = dart.notNull(length) - dart.notNull(core.num._check(dart.dsend(dart.dload(parts[dartx.removeLast](), 'length'), '+', OVERHEAD)));
             count--;
           }
           parts[dartx.add]("...");
@@ -25593,7 +25603,7 @@
     length = dart.notNull(length) + (ELLIPSIS_SIZE + OVERHEAD);
   }
   while (dart.notNull(length) > LENGTH_LIMIT && dart.notNull(parts[dartx.length]) > HEAD_COUNT) {
-    length = dart.notNull(length) - dart.notNull(core.int._check(dart.dsend(dart.dload(parts[dartx.removeLast](), 'length'), '+', OVERHEAD)));
+    length = dart.notNull(length) - dart.notNull(core.num._check(dart.dsend(dart.dload(parts[dartx.removeLast](), 'length'), '+', OVERHEAD)));
     if (elision == null) {
       elision = "...";
       length = dart.notNull(length) + (ELLIPSIS_SIZE + OVERHEAD);
@@ -29211,6 +29221,7 @@
 convert._ErrorHandlingAsciiDecoderSink = class _ErrorHandlingAsciiDecoderSink extends convert.ByteConversionSinkBase {
   new(utf8Sink) {
     this[_utf8Sink] = utf8Sink;
+    super.new();
   }
   close() {
     this[_utf8Sink].close();
@@ -29245,6 +29256,7 @@
 convert._SimpleAsciiDecoderSink = class _SimpleAsciiDecoderSink extends convert.ByteConversionSinkBase {
   new(sink) {
     this[_sink] = sink;
+    super.new();
   }
   close() {
     this[_sink].close();
@@ -29533,6 +29545,9 @@
 });
 const _add = Symbol('_add');
 convert._Base64EncoderSink = class _Base64EncoderSink extends convert.ByteConversionSinkBase {
+  new() {
+    super.new();
+  }
   add(source) {
     this[_add](source, 0, source[dartx.length], false);
   }
@@ -29555,6 +29570,7 @@
   new(sink, urlSafe) {
     this[_sink] = sink;
     this[_encoder] = new convert._BufferCachingBase64Encoder(urlSafe);
+    super.new();
   }
   [_add](source, start, end, isLast) {
     let buffer = this[_encoder].encode(source, start, end, isLast);
@@ -29579,6 +29595,7 @@
   new(sink, urlSafe) {
     this[_sink] = sink;
     this[_encoder] = new convert._Base64Encoder(urlSafe);
+    super.new();
   }
   [_add](source, start, end, isLast) {
     let buffer = this[_encoder].encode(source, start, end, isLast);
@@ -29930,6 +29947,7 @@
 convert._ByteAdapterSink = class _ByteAdapterSink extends convert.ByteConversionSinkBase {
   new(sink) {
     this[_sink] = sink;
+    super.new();
   }
   add(chunk) {
     this[_sink].add(chunk);
@@ -29954,6 +29972,7 @@
     this[_buffer] = typed_data.Uint8List.new(convert._ByteCallbackSink._INITIAL_BUFFER_SIZE);
     this[_callback] = callback;
     this[_bufferIndex] = 0;
+    super.new();
   }
   add(chunk) {
     let freeCount = dart.notNull(this[_buffer][dartx.length]) - dart.notNull(this[_bufferIndex]);
@@ -31299,6 +31318,7 @@
 convert._Latin1DecoderSink = class _Latin1DecoderSink extends convert.ByteConversionSinkBase {
   new(sink) {
     this[_sink] = sink;
+    super.new();
   }
   close() {
     this[_sink].close();
@@ -78394,13 +78414,13 @@
     let val = 0;
     for (let measurement of dimensions) {
       if (augmentingMeasurement == html._MARGIN) {
-        val = dart.notNull(val) + dart.notNull(dart.asInt(new html.Dimension.css(styles[dartx.getPropertyValue](dart.str`${augmentingMeasurement}-${measurement}`)).value));
+        val = dart.notNull(val) + dart.notNull(new html.Dimension.css(styles[dartx.getPropertyValue](dart.str`${augmentingMeasurement}-${measurement}`)).value);
       }
       if (augmentingMeasurement == html._CONTENT) {
-        val = dart.notNull(val) - dart.notNull(dart.asInt(new html.Dimension.css(styles[dartx.getPropertyValue](dart.str`${html._PADDING}-${measurement}`)).value));
+        val = dart.notNull(val) - dart.notNull(new html.Dimension.css(styles[dartx.getPropertyValue](dart.str`${html._PADDING}-${measurement}`)).value);
       }
       if (augmentingMeasurement != html._MARGIN) {
-        val = dart.notNull(val) - dart.notNull(dart.asInt(new html.Dimension.css(styles[dartx.getPropertyValue](dart.str`border-${measurement}-width`)).value));
+        val = dart.notNull(val) - dart.notNull(new html.Dimension.css(styles[dartx.getPropertyValue](dart.str`border-${measurement}-width`)).value);
       }
     }
     return val;
diff --git a/pkg/dev_compiler/lib/js/legacy/dart_sdk.js b/pkg/dev_compiler/lib/js/legacy/dart_sdk.js
index 1292685..4c981ff 100644
--- a/pkg/dev_compiler/lib/js/legacy/dart_sdk.js
+++ b/pkg/dev_compiler/lib/js/legacy/dart_sdk.js
@@ -4267,12 +4267,20 @@
   });
   _interceptors.JSMutableArray = JSMutableArray();
   _interceptors.JSFixedArray$ = dart.generic(E => {
-    class JSFixedArray extends _interceptors.JSMutableArray$(E) {}
+    class JSFixedArray extends _interceptors.JSMutableArray$(E) {
+      new() {
+        super.new();
+      }
+    }
     return JSFixedArray;
   });
   _interceptors.JSFixedArray = JSFixedArray();
   _interceptors.JSExtendableArray$ = dart.generic(E => {
-    class JSExtendableArray extends _interceptors.JSMutableArray$(E) {}
+    class JSExtendableArray extends _interceptors.JSMutableArray$(E) {
+      new() {
+        super.new();
+      }
+    }
     return JSExtendableArray;
   });
   _interceptors.JSExtendableArray = JSExtendableArray();
@@ -17069,6 +17077,7 @@
     class _ControllerStream extends async._StreamImpl$(T) {
       new(controller) {
         this[_controller$] = controller;
+        super.new();
       }
       [_createSubscription](onData, onError, onDone, cancelOnError) {
         return this[_controller$][_subscribe](onData, onError, onDone, cancelOnError);
@@ -20112,6 +20121,7 @@
       new(pending) {
         this[_pending] = pending;
         this[_isUsed] = false;
+        super.new();
       }
       [_createSubscription](onData, onError, onDone, cancelOnError) {
         if (dart.test(this[_isUsed])) dart.throw(new core.StateError("Stream has already been listened to."));
@@ -25578,7 +25588,7 @@
           count++;
           if (count > MAX_COUNT) {
             while (dart.notNull(length) > LENGTH_LIMIT - ELLIPSIS_SIZE - OVERHEAD && count > HEAD_COUNT) {
-              length = dart.notNull(length) - dart.notNull(core.int._check(dart.dsend(dart.dload(parts[dartx.removeLast](), 'length'), '+', OVERHEAD)));
+              length = dart.notNull(length) - dart.notNull(core.num._check(dart.dsend(dart.dload(parts[dartx.removeLast](), 'length'), '+', OVERHEAD)));
               count--;
             }
             parts[dartx.add]("...");
@@ -25596,7 +25606,7 @@
       length = dart.notNull(length) + (ELLIPSIS_SIZE + OVERHEAD);
     }
     while (dart.notNull(length) > LENGTH_LIMIT && dart.notNull(parts[dartx.length]) > HEAD_COUNT) {
-      length = dart.notNull(length) - dart.notNull(core.int._check(dart.dsend(dart.dload(parts[dartx.removeLast](), 'length'), '+', OVERHEAD)));
+      length = dart.notNull(length) - dart.notNull(core.num._check(dart.dsend(dart.dload(parts[dartx.removeLast](), 'length'), '+', OVERHEAD)));
       if (elision == null) {
         elision = "...";
         length = dart.notNull(length) + (ELLIPSIS_SIZE + OVERHEAD);
@@ -29214,6 +29224,7 @@
   convert._ErrorHandlingAsciiDecoderSink = class _ErrorHandlingAsciiDecoderSink extends convert.ByteConversionSinkBase {
     new(utf8Sink) {
       this[_utf8Sink] = utf8Sink;
+      super.new();
     }
     close() {
       this[_utf8Sink].close();
@@ -29248,6 +29259,7 @@
   convert._SimpleAsciiDecoderSink = class _SimpleAsciiDecoderSink extends convert.ByteConversionSinkBase {
     new(sink) {
       this[_sink$] = sink;
+      super.new();
     }
     close() {
       this[_sink$].close();
@@ -29536,6 +29548,9 @@
   });
   const _add$1 = Symbol('_add');
   convert._Base64EncoderSink = class _Base64EncoderSink extends convert.ByteConversionSinkBase {
+    new() {
+      super.new();
+    }
     add(source) {
       this[_add$1](source, 0, source[dartx.length], false);
     }
@@ -29558,6 +29573,7 @@
     new(sink, urlSafe) {
       this[_sink$] = sink;
       this[_encoder] = new convert._BufferCachingBase64Encoder(urlSafe);
+      super.new();
     }
     [_add$1](source, start, end, isLast) {
       let buffer = this[_encoder].encode(source, start, end, isLast);
@@ -29582,6 +29598,7 @@
     new(sink, urlSafe) {
       this[_sink$] = sink;
       this[_encoder] = new convert._Base64Encoder(urlSafe);
+      super.new();
     }
     [_add$1](source, start, end, isLast) {
       let buffer = this[_encoder].encode(source, start, end, isLast);
@@ -29933,6 +29950,7 @@
   convert._ByteAdapterSink = class _ByteAdapterSink extends convert.ByteConversionSinkBase {
     new(sink) {
       this[_sink$] = sink;
+      super.new();
     }
     add(chunk) {
       this[_sink$].add(chunk);
@@ -29957,6 +29975,7 @@
       this[_buffer] = typed_data.Uint8List.new(convert._ByteCallbackSink._INITIAL_BUFFER_SIZE);
       this[_callback] = callback;
       this[_bufferIndex] = 0;
+      super.new();
     }
     add(chunk) {
       let freeCount = dart.notNull(this[_buffer][dartx.length]) - dart.notNull(this[_bufferIndex]);
@@ -31302,6 +31321,7 @@
   convert._Latin1DecoderSink = class _Latin1DecoderSink extends convert.ByteConversionSinkBase {
     new(sink) {
       this[_sink$] = sink;
+      super.new();
     }
     close() {
       this[_sink$].close();
@@ -78397,13 +78417,13 @@
       let val = 0;
       for (let measurement of dimensions) {
         if (augmentingMeasurement == html$._MARGIN) {
-          val = dart.notNull(val) + dart.notNull(dart.asInt(new html$.Dimension.css(styles[dartx.getPropertyValue](dart.str`${augmentingMeasurement}-${measurement}`)).value));
+          val = dart.notNull(val) + dart.notNull(new html$.Dimension.css(styles[dartx.getPropertyValue](dart.str`${augmentingMeasurement}-${measurement}`)).value);
         }
         if (augmentingMeasurement == html$._CONTENT) {
-          val = dart.notNull(val) - dart.notNull(dart.asInt(new html$.Dimension.css(styles[dartx.getPropertyValue](dart.str`${html$._PADDING}-${measurement}`)).value));
+          val = dart.notNull(val) - dart.notNull(new html$.Dimension.css(styles[dartx.getPropertyValue](dart.str`${html$._PADDING}-${measurement}`)).value);
         }
         if (augmentingMeasurement != html$._MARGIN) {
-          val = dart.notNull(val) - dart.notNull(dart.asInt(new html$.Dimension.css(styles[dartx.getPropertyValue](dart.str`border-${measurement}-width`)).value));
+          val = dart.notNull(val) - dart.notNull(new html$.Dimension.css(styles[dartx.getPropertyValue](dart.str`border-${measurement}-width`)).value);
         }
       }
       return val;
diff --git a/pkg/dev_compiler/lib/src/analyzer/context.dart b/pkg/dev_compiler/lib/src/analyzer/context.dart
index 734731b..3545bca 100644
--- a/pkg/dev_compiler/lib/src/analyzer/context.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/context.dart
@@ -13,11 +13,11 @@
 import 'package:analyzer/src/context/context.dart' show AnalysisContextImpl;
 import 'package:analyzer/src/dart/sdk/sdk.dart' show FolderBasedDartSdk;
 import 'package:analyzer/src/generated/engine.dart'
-    show AnalysisContext, AnalysisEngine, AnalysisOptionsImpl;
+    show AnalysisEngine, AnalysisOptionsImpl;
 import 'package:analyzer/src/generated/source.dart'
     show DartUriResolver, SourceFactory, UriResolver;
 import 'package:analyzer/src/summary/package_bundle_reader.dart'
-    show InSummaryUriResolver, InputPackagesResultProvider, SummaryDataStore;
+    show InSummaryUriResolver, SummaryDataStore;
 import 'package:analyzer/src/summary/summary_sdk.dart' show SummaryBasedDartSdk;
 import 'package:cli_util/cli_util.dart' show getSdkDir;
 import 'package:path/path.dart' as path;
@@ -98,39 +98,6 @@
   }
 }
 
-/// Creates an [AnalysisContext] with dev_compiler type rules and inference,
-/// using [createSourceFactory] to set up its [SourceFactory].
-AnalysisContext createAnalysisContextWithSources(AnalyzerOptions options,
-    {DartUriResolver sdkResolver,
-    List<UriResolver> fileResolvers,
-    ResourceProvider resourceProvider}) {
-  AnalysisEngine.instance.processRequiredPlugins();
-
-  sdkResolver ??=
-      createSdkPathResolver(options.dartSdkSummaryPath, options.dartSdkPath);
-
-  // Read the summaries.
-  SummaryDataStore summaryData;
-  if (options.summaryPaths.isNotEmpty) {
-    summaryData = new SummaryDataStore(options.summaryPaths);
-  }
-
-  var srcFactory = _createSourceFactory(options,
-      sdkResolver: sdkResolver,
-      fileResolvers: fileResolvers,
-      summaryData: summaryData,
-      resourceProvider: resourceProvider);
-
-  var context = createAnalysisContext();
-  context.sourceFactory = srcFactory;
-  if (summaryData != null) {
-    context.typeProvider = sdkResolver.dartSdk.context.typeProvider;
-    context.resultProvider =
-        new InputPackagesResultProvider(context, summaryData);
-  }
-  return context;
-}
-
 /// Creates an analysis context that contains our restricted typing rules.
 AnalysisContextImpl createAnalysisContext() {
   var res = AnalysisEngine.instance.createAnalysisContext();
@@ -147,7 +114,7 @@
 ///
 /// If supplied, [fileResolvers] will override the default `file:` and
 /// `package:` URI resolvers.
-SourceFactory _createSourceFactory(AnalyzerOptions options,
+SourceFactory createSourceFactory(AnalyzerOptions options,
     {DartUriResolver sdkResolver,
     List<UriResolver> fileResolvers,
     SummaryDataStore summaryData,
diff --git a/pkg/dev_compiler/lib/src/compiler/code_generator.dart b/pkg/dev_compiler/lib/src/compiler/code_generator.dart
index dd31245..1b306a7 100644
--- a/pkg/dev_compiler/lib/src/compiler/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/compiler/code_generator.dart
@@ -1,4 +1,5 @@
 // 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.
 
@@ -14,15 +15,22 @@
 import 'package:analyzer/src/dart/element/element.dart'
     show LocalVariableElementImpl;
 import 'package:analyzer/src/dart/element/type.dart' show DynamicTypeImpl;
+import 'package:analyzer/src/dart/sdk/sdk.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
 import 'package:analyzer/src/generated/resolver.dart'
     show TypeProvider, NamespaceBuilder;
 import 'package:analyzer/src/generated/type_system.dart'
     show StrongTypeSystemImpl;
+import 'package:analyzer/src/summary/idl.dart' show UnlinkedUnit;
+import 'package:analyzer/src/summary/link.dart' as summary_link;
+import 'package:analyzer/src/summary/package_bundle_reader.dart';
+import 'package:analyzer/src/summary/summarize_ast.dart'
+    show serializeAstUnlinked;
 import 'package:analyzer/src/summary/summarize_elements.dart'
     show PackageBundleAssembler;
+import 'package:analyzer/src/summary/summary_sdk.dart';
 import 'package:analyzer/src/task/strong/ast_properties.dart'
-    show isDynamicInvoke, setIsDynamicInvoke;
+    show isDynamicInvoke, setIsDynamicInvoke, getImplicitAssignmentCast;
 import 'package:path/path.dart' show separator;
 
 import '../closure/closure_annotator.dart' show ClosureAnnotator;
@@ -47,6 +55,8 @@
 class CodeGenerator extends GeneralizingAstVisitor
     with ClosureAnnotator, JsTypeRefCodegen, NullableTypeInference {
   final AnalysisContext context;
+  final SummaryDataStore summaryData;
+
   final CompilerOptions options;
   final rules = new StrongTypeSystemImpl();
 
@@ -138,7 +148,8 @@
   /// Whether we are currently generating code for the body of a `JS()` call.
   bool _isInForeignJS = false;
 
-  CodeGenerator(AnalysisContext c, this.options, this._extensionTypes)
+  CodeGenerator(
+      AnalysisContext c, this.summaryData, this.options, this._extensionTypes)
       : context = c,
         types = c.typeProvider,
         _asyncStreamIterator =
@@ -175,14 +186,37 @@
     return new JSModuleFile(unit.name, errors, options, module, dartApiSummary);
   }
 
-  List<int> _summarizeModule(List<CompilationUnit> compilationUnits) {
+  List<int> _summarizeModule(List<CompilationUnit> units) {
     if (!options.summarizeApi) return null;
 
+    if (!units.any((u) => u.element.librarySource.isInSystemLibrary)) {
+      var sdk = context.sourceFactory.dartSdk;
+      summaryData.addBundle(
+          null,
+          sdk is SummaryBasedDartSdk
+              ? sdk.bundle
+              : (sdk as FolderBasedDartSdk).getSummarySdkBundle(true));
+    }
+
     var assembler = new PackageBundleAssembler();
-    compilationUnits
-        .map((u) => u.element.library)
-        .toSet()
-        .forEach(assembler.serializeLibraryElement);
+    assembler.recordDependencies(summaryData);
+
+    var uriToUnit = new Map<String, UnlinkedUnit>.fromIterable(units,
+        key: (u) => u.element.source.uri.toString(), value: (unit) {
+      var unlinked = serializeAstUnlinked(unit);
+      assembler.addUnlinkedUnit(unit.element.source, unlinked);
+      return unlinked;
+    });
+
+    summary_link
+        .link(
+            uriToUnit.keys.toSet(),
+            (uri) => summaryData.linkedMap[uri],
+            (uri) => summaryData.unlinkedMap[uri] ?? uriToUnit[uri],
+            context.declaredVariables.get,
+            true)
+        .forEach(assembler.addLinkedLibrary);
+
     return assembler.assemble().toBuffer();
   }
 
@@ -526,19 +560,13 @@
     var type = _emitType(to,
         nameType: options.nameTypeTests || options.hoistTypeTests,
         hoistType: options.hoistTypeTests);
-    if (isReifiedCoercion(node)) {
+    if (CoercionReifier.isImplicitCast(node)) {
       return js.call('#._check(#)', [type, jsFrom]);
     } else {
       return js.call('#.as(#)', [type, jsFrom]);
     }
   }
 
-  bool isReifiedCoercion(AstNode node) {
-    // TODO(sra): Find a better way to recognize reified coercion, since we
-    // can't set the isSynthetic attribute.
-    return (node is AsExpression) && (node.asOperator.offset == 0);
-  }
-
   @override
   visitIsExpression(IsExpression node) {
     // Generate `is` as `dart.is` or `typeof` depending on the RHS type.
@@ -1856,8 +1884,6 @@
       ClassDeclaration node,
       List<FieldDeclaration> fields,
       Map<FieldElement, JS.TemporaryId> virtualFields) {
-    assert(_hasUnnamedConstructor(node.element) == fields.isNotEmpty);
-
     // If we don't have a method body, skip this.
     var superCall = _superConstructorCall(node.element);
     if (fields.isEmpty && superCall == null) return null;
@@ -1897,8 +1923,8 @@
 
       var fun = new JS.Fun(
           params,
-          js.statement(
-              '{ return $newKeyword #(#); }', [_visit(redirect), params]),
+          js.statement('{ return $newKeyword #(#); }',
+              [_visit(redirect) as JS.Node, params]),
           returnType: returnType);
       return annotate(
           new JS.Method(name, fun, isStatic: true), node, node.element);
@@ -2031,7 +2057,7 @@
       return null;
     }
 
-    if (superCtor.name == '' && !_shouldCallUnnamedSuperCtor(element)) {
+    if (superCtor.name == '' && !_hasUnnamedSuperConstructor(element)) {
       return null;
     }
 
@@ -2040,7 +2066,7 @@
     return annotate(js.statement('super.#(#);', [name, args]), node);
   }
 
-  bool _shouldCallUnnamedSuperCtor(ClassElement e) {
+  bool _hasUnnamedSuperConstructor(ClassElement e) {
     var supertype = e.supertype;
     if (supertype == null) return false;
     if (_hasUnnamedConstructor(supertype.element)) return true;
@@ -2053,7 +2079,8 @@
   bool _hasUnnamedConstructor(ClassElement e) {
     if (e.type.isObject) return false;
     if (!e.unnamedConstructor.isSynthetic) return true;
-    return e.fields.any((f) => !f.isStatic && !f.isSynthetic);
+    if (e.fields.any((f) => !f.isStatic && !f.isSynthetic)) return true;
+    return _hasUnnamedSuperConstructor(e);
   }
 
   /// Initialize fields. They follow the sequence:
@@ -2981,9 +3008,12 @@
     // (for example, x is IndexExpression) we evaluate those once.
     var vars = <JS.MetaLetVariable, JS.Expression>{};
     var lhs = _bindLeftHandSide(vars, left, context: context);
-    var inc = AstBuilder.binaryExpression(lhs, op, right);
-    inc.staticElement = element;
-    inc.staticType = getStaticType(left);
+    Expression inc = AstBuilder.binaryExpression(lhs, op, right)
+      ..staticElement = element
+      ..staticType = getStaticType(lhs);
+
+    var castTo = getImplicitAssignmentCast(left);
+    if (castTo != null) inc = CoercionReifier.castExpression(inc, castTo);
     return new JS.MetaLet(vars, [_emitSet(lhs, inc)]);
   }
 
@@ -4511,7 +4541,8 @@
       }
     }
     if (tail.isEmpty) return _visit(node);
-    return js.call('dart.nullSafe(#, #)', [_visit(node), tail.reversed]);
+    return js.call(
+        'dart.nullSafe(#, #)', [_visit(node) as JS.Expression, tail.reversed]);
   }
 
   static Token _getOperator(Expression node) {
@@ -4664,8 +4695,8 @@
       // dynamic dispatch
       var dynamicHelper = const {'[]': 'dindex', '[]=': 'dsetindex'}[name];
       if (dynamicHelper != null) {
-        return js.call(
-            'dart.$dynamicHelper(#, #)', [_visit(target), _visitList(args)]);
+        return js.call('dart.$dynamicHelper(#, #)',
+            [_visit(target) as JS.Expression, _visitList(args)]);
       } else {
         return js.call('dart.dsend(#, #, #)',
             [_visit(target), memberName, _visitList(args)]);
@@ -5019,7 +5050,7 @@
     // TODO(jmesserly): we can likely make these faster.
     JS.Expression emitMap() {
       var entries = node.entries;
-      var mapArguments = null;
+      Object mapArguments = null;
       var type = node.staticType as InterfaceType;
       var typeArgs = type.typeArguments;
       var reifyTypeArgs = typeArgs.any((t) => !t.isDynamic);
@@ -5141,10 +5172,9 @@
       if (op == '&&') return shortCircuit('# && #');
       if (op == '||') return shortCircuit('# || #');
     }
-    if (isReifiedCoercion(node)) {
-      AsExpression asNode = node;
-      assert(asNode.staticType == types.boolType);
-      return js.call('dart.test(#)', _visit(asNode.expression));
+    if (node is AsExpression && CoercionReifier.isImplicitCast(node)) {
+      assert(node.staticType == types.boolType);
+      return js.call('dart.test(#)', _visit(node.expression));
     }
     JS.Expression result = _visit(node);
     if (isNullable(node)) result = js.call('dart.test(#)', result);
@@ -5425,7 +5455,8 @@
         uri.path.substring(libraryRoot.length).replaceAll('/', separator);
   } else {
     // We don't have a unique name.
-    throw 'Invalid library root. $libraryRoot does not contain ${uri.toFilePath()}';
+    throw 'Invalid library root. $libraryRoot does not contain ${uri
+        .toFilePath()}';
   }
   return pathToJSIdentifier(qualifiedPath);
 }
@@ -5446,10 +5477,12 @@
 /// everywhere in the tree where they are treated as the same variable.
 class TemporaryVariableElement extends LocalVariableElementImpl {
   final JS.Expression jsVariable;
+
   TemporaryVariableElement.forNode(Identifier name, this.jsVariable)
       : super.forNode(name);
 
   int get hashCode => identityHashCode(this);
+
   bool operator ==(Object other) => identical(this, other);
 }
 
diff --git a/pkg/dev_compiler/lib/src/compiler/compiler.dart b/pkg/dev_compiler/lib/src/compiler/compiler.dart
index bc1ae50..e789bca 100644
--- a/pkg/dev_compiler/lib/src/compiler/compiler.dart
+++ b/pkg/dev_compiler/lib/src/compiler/compiler.dart
@@ -9,12 +9,13 @@
 import 'package:analyzer/analyzer.dart'
     show AnalysisError, CompilationUnit, ErrorSeverity;
 import 'package:analyzer/file_system/file_system.dart' show ResourceProvider;
-import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
+import 'package:analyzer/src/generated/engine.dart'
+    show AnalysisContext, AnalysisEngine;
 import 'package:analyzer/src/generated/source.dart' show DartUriResolver;
 import 'package:analyzer/src/generated/source_io.dart'
     show Source, SourceKind, UriResolver;
 import 'package:analyzer/src/summary/package_bundle_reader.dart'
-    show InSummarySource;
+    show InSummarySource, InputPackagesResultProvider, SummaryDataStore;
 import 'package:args/args.dart' show ArgParser, ArgResults;
 import 'package:args/src/usage_exception.dart' show UsageException;
 import 'package:func/func.dart' show Func1;
@@ -22,7 +23,11 @@
 import 'package:source_maps/source_maps.dart';
 
 import '../analyzer/context.dart'
-    show AnalyzerOptions, createAnalysisContextWithSources;
+    show
+        AnalyzerOptions,
+        createAnalysisContext,
+        createSdkPathResolver,
+        createSourceFactory;
 import '../js_ast/js_ast.dart' as JS;
 import 'code_generator.dart' show CodeGenerator;
 import 'error_helpers.dart' show errorSeverity, formatError, sortErrors;
@@ -50,9 +55,10 @@
 /// about them.
 class ModuleCompiler {
   final AnalysisContext context;
+  final SummaryDataStore summaryData;
   final ExtensionTypeSet _extensionTypes;
 
-  ModuleCompiler.withContext(AnalysisContext context)
+  ModuleCompiler.withContext(AnalysisContext context, this.summaryData)
       : context = context,
         _extensionTypes = new ExtensionTypeSet(context) {
     if (!context.analysisOptions.strongMode) {
@@ -63,14 +69,33 @@
     }
   }
 
-  ModuleCompiler(AnalyzerOptions analyzerOptions,
+  factory ModuleCompiler(AnalyzerOptions options,
       {DartUriResolver sdkResolver,
       ResourceProvider resourceProvider,
-      List<UriResolver> fileResolvers})
-      : this.withContext(createAnalysisContextWithSources(analyzerOptions,
-            sdkResolver: sdkResolver,
-            fileResolvers: fileResolvers,
-            resourceProvider: resourceProvider));
+      List<UriResolver> fileResolvers}) {
+    AnalysisEngine.instance.processRequiredPlugins();
+
+    sdkResolver ??=
+        createSdkPathResolver(options.dartSdkSummaryPath, options.dartSdkPath);
+
+    // Read the summaries.
+    var summaryData =
+        new SummaryDataStore(options.summaryPaths, recordDependencyInfo: true);
+
+    var srcFactory = createSourceFactory(options,
+        sdkResolver: sdkResolver,
+        fileResolvers: fileResolvers,
+        summaryData: summaryData,
+        resourceProvider: resourceProvider);
+
+    var context = createAnalysisContext();
+    context.sourceFactory = srcFactory;
+    context.typeProvider = sdkResolver.dartSdk.context.typeProvider;
+    context.resultProvider =
+        new InputPackagesResultProvider(context, summaryData);
+
+    return new ModuleCompiler.withContext(context, summaryData);
+  }
 
   /// Compiles a single Dart build unit into a JavaScript module.
   ///
@@ -145,7 +170,8 @@
       return new JSModuleFile.invalid(unit.name, messages, options);
     }
 
-    var codeGenerator = new CodeGenerator(context, options, _extensionTypes);
+    var codeGenerator =
+        new CodeGenerator(context, summaryData, options, _extensionTypes);
     return codeGenerator.compile(unit, trees, messages);
   }
 }
@@ -479,6 +505,7 @@
     // Fall back to a relative path.
     return path.toUri(path.relative(path.fromUri(uri), from: dir)).toString();
   }
+
   for (int i = 0; i < list.length; i++) {
     list[i] = transformUri(list[i]);
   }
diff --git a/pkg/dev_compiler/lib/src/compiler/reify_coercions.dart b/pkg/dev_compiler/lib/src/compiler/reify_coercions.dart
index dd87fde..c0a9f72 100644
--- a/pkg/dev_compiler/lib/src/compiler/reify_coercions.dart
+++ b/pkg/dev_compiler/lib/src/compiler/reify_coercions.dart
@@ -31,6 +31,22 @@
     return units.map(cr.visitCompilationUnit).toList(growable: false);
   }
 
+  /// Returns true if the `as` [node] was created by this class.
+  // TODO(sra): Find a better way to recognize reified coercion, since we
+  // can't set the isSynthetic attribute.
+  static bool isImplicitCast(AsExpression node) => node.asOperator.offset == 0;
+
+  /// Creates an implicit cast for expression [e] to [toType].
+  static Expression castExpression(Expression e, DartType toType) {
+    // We use an empty name in the AST, because the JS code generator only cares
+    // about the target type. It does not look at the AST name.
+    var typeName = new TypeName(AstBuilder.identifierFromString(''), null);
+    typeName.type = toType;
+    var cast = AstBuilder.asExpression(e, typeName);
+    cast.staticType = toType;
+    return cast;
+  }
+
   @override
   CompilationUnit visitCompilationUnit(CompilationUnit node) {
     if (ast_properties.hasImplicitCasts(node)) {
@@ -47,7 +63,7 @@
 
     var castType = ast_properties.getImplicitCast(node);
     if (castType != null) {
-      _replaceNode(node.parent, node, _castExpression(node, castType));
+      _replaceNode(node.parent, node, castExpression(node, castType));
     }
   }
 
@@ -79,7 +95,7 @@
       // Build the cast. We will place this cast in the body, so need to clone
       // the variable's AST node and clear out its static type (otherwise we
       // will optimize away the cast).
-      var cast = _castExpression(
+      var cast = castExpression(
           _clone(variable)..staticType = DynamicTypeImpl.instance, castType);
 
       var body = node.body;
@@ -102,16 +118,6 @@
     }
   }
 
-  Expression _castExpression(Expression e, DartType toType) {
-    // We use an empty name in the AST, because the JS code generator only cares
-    // about the target type. It does not look at the AST name.
-    var typeName = new TypeName(AstBuilder.identifierFromString(''), null);
-    typeName.type = toType;
-    var cast = AstBuilder.asExpression(e, typeName);
-    cast.staticType = toType;
-    return cast;
-  }
-
   /*=T*/ _clone/*<T extends AstNode>*/(/*=T*/ node) {
     var copy = node.accept(cloner) as dynamic/*=T*/;
     ResolutionCopier.copyResolutionData(node, copy);
diff --git a/pkg/dev_compiler/pubspec.lock b/pkg/dev_compiler/pubspec.lock
deleted file mode 100644
index 792de61..0000000
--- a/pkg/dev_compiler/pubspec.lock
+++ /dev/null
@@ -1,335 +0,0 @@
-# Generated by pub
-# See http://pub.dartlang.org/doc/glossary.html#lockfile
-packages:
-  analyzer:
-    description:
-      path: "../analyzer"
-      relative: true
-    source: path
-    version: "0.29.0-alpha.0"
-  archive:
-    description:
-      name: archive
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.0.25"
-  args:
-    description:
-      name: args
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.13.5"
-  async:
-    description:
-      name: async
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.11.1"
-  barback:
-    description:
-      name: barback
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.15.2+9"
-  bazel_worker:
-    description:
-      name: bazel_worker
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.1.1"
-  boolean_selector:
-    description:
-      name: boolean_selector
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.0.2"
-  browser:
-    description:
-      name: browser
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.10.0+2"
-  charcode:
-    description:
-      name: charcode
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.1.0"
-  cli_util:
-    description:
-      name: cli_util
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.0.1+2"
-  collection:
-    description:
-      name: collection
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.9.1"
-  convert:
-    description:
-      name: convert
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "2.0.1"
-  crypto:
-    description:
-      name: crypto
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "2.0.1"
-  csslib:
-    description:
-      name: csslib
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.13.2"
-  dart_style:
-    description:
-      name: dart_style
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.2.4"
-  fixnum:
-    description:
-      name: fixnum
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.10.5"
-  func:
-    description:
-      name: func
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.1.0"
-  glob:
-    description:
-      name: glob
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.1.3"
-  html:
-    description:
-      name: html
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.12.2+2"
-  http:
-    description:
-      name: http
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.11.3+9"
-  http_multi_server:
-    description:
-      name: http_multi_server
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "2.0.2"
-  http_parser:
-    description:
-      name: http_parser
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "3.0.2"
-  isolate:
-    description:
-      name: isolate
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.2.3"
-  js:
-    description:
-      name: js
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.6.1"
-  logging:
-    description:
-      name: logging
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.11.3+1"
-  matcher:
-    description:
-      name: matcher
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.12.0+2"
-  meta:
-    description:
-      path: "../meta"
-      relative: true
-    source: path
-    version: "1.0.3"
-  mime:
-    description:
-      name: mime
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.9.3"
-  package_config:
-    description:
-      name: package_config
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.0.0"
-  package_resolver:
-    description:
-      name: package_resolver
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.0.2"
-  path:
-    description:
-      name: path
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.3.9"
-  plugin:
-    description:
-      name: plugin
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.2.0"
-  pool:
-    description:
-      name: pool
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.2.4"
-  protobuf:
-    description:
-      name: protobuf
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.5.3"
-  pub_semver:
-    description:
-      name: pub_semver
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.3.0"
-  shelf:
-    description:
-      name: shelf
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.6.5+3"
-  shelf_packages_handler:
-    description:
-      name: shelf_packages_handler
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.0.0"
-  shelf_static:
-    description:
-      name: shelf_static
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.2.4"
-  shelf_web_socket:
-    description:
-      name: shelf_web_socket
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.2.1"
-  source_map_stack_trace:
-    description:
-      name: source_map_stack_trace
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.1.3"
-  source_maps:
-    description:
-      name: source_maps
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.10.1+1"
-  source_span:
-    description:
-      name: source_span
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.2.3"
-  stack_trace:
-    description:
-      name: stack_trace
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.6.6"
-  stream_channel:
-    description:
-      name: stream_channel
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.5.0"
-  string_scanner:
-    description:
-      name: string_scanner
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.0.0"
-  test:
-    description:
-      name: test
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.12.15+6"
-  typed_data:
-    description:
-      name: typed_data
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.1.3"
-  unittest:
-    description:
-      name: unittest
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.11.6+4"
-  utf:
-    description:
-      name: utf
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.9.0+3"
-  watcher:
-    description:
-      name: watcher
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.9.7+3"
-  web_socket_channel:
-    description:
-      name: web_socket_channel
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.0.4"
-  webdriver:
-    description:
-      name: webdriver
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.2.1"
-  when:
-    description:
-      name: when
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.2.0"
-  which:
-    description:
-      name: which
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.1.3"
-  yaml:
-    description:
-      name: yaml
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "2.1.10"
-sdks:
-  dart: ">=1.19.0-dev.0.0 <2.0.0"
diff --git a/pkg/dev_compiler/test/codegen/corelib/collection_test.dart b/pkg/dev_compiler/test/codegen/corelib/collection_test.dart
index 680e20a..1b56960 100644
--- a/pkg/dev_compiler/test/codegen/corelib/collection_test.dart
+++ b/pkg/dev_compiler/test/codegen/corelib/collection_test.dart
@@ -8,13 +8,13 @@
 import 'dart:collection' show Queue;
 
 class CollectionTest {
-  CollectionTest(Iterable iterable) {
+  CollectionTest(Iterable<int> iterable) {
     testFold(iterable);
   }
 
-  void testFold(Iterable iterable) {
-    Expect.equals(28, iterable.fold(0, (prev, element) => prev + element));
-    Expect.equals(3024, iterable.fold(1, (prev, element) => prev * element));
+  void testFold(Iterable<int> iterable) {
+    Expect.equals(28, iterable.fold/*<int>*/(0, (prev, element) => prev + element));
+    Expect.equals(3024, iterable.fold/*<int>*/(1, (prev, element) => prev * element));
   }
 }
 
@@ -25,7 +25,7 @@
   new CollectionTest(TEST_ELEMENTS);
 
   // Fixed size list.
-  var fixedList = new List(TEST_ELEMENTS.length);
+  var fixedList = new List<int>(TEST_ELEMENTS.length);
   for (int i = 0; i < TEST_ELEMENTS.length; i++) {
     fixedList[i] = TEST_ELEMENTS[i];
   }
diff --git a/pkg/dev_compiler/test/codegen/corelib/list_map_test.dart b/pkg/dev_compiler/test/codegen/corelib/list_map_test.dart
index 947f40a..a5f48a8 100644
--- a/pkg/dev_compiler/test/codegen/corelib/list_map_test.dart
+++ b/pkg/dev_compiler/test/codegen/corelib/list_map_test.dart
@@ -52,7 +52,7 @@
 
   void testList(List list) {
     var throws = const ThrowMarker();
-    List mappedList = new List(list.length);
+    var mappedList = new List<int>(list.length);
     for (int i = 0; i < list.length; i++) {
       mappedList[i] = rev(list[i]);
     }
@@ -78,7 +78,7 @@
       }
     }
 
-    void testOp(operation(Iterable mappedList), name) {
+    void testOp(operation(Iterable<int> mappedList), name) {
       var expect;
       try {
         expect = operation(mappedList);
@@ -115,7 +115,7 @@
     testOp((i) => i.every((n) => n < 5), "every<5");
     testOp((i) => i.every((n) => n < 10), "every<10");
     testOp((i) => i.reduce((a, b) => a + b), "reduce-sum");
-    testOp((i) => i.fold(0, (a, b) => a + b), "fold-sum");
+    testOp((i) => i.fold/*<int>*/(0, (a, b) => a + b), "fold-sum");
     testOp((i) => i.join("-"), "join-");
     testOp((i) => i.join(""), "join");
     testOp((i) => i.join(), "join-null");
diff --git a/pkg/dev_compiler/test/codegen/corelib/list_reversed_test.dart b/pkg/dev_compiler/test/codegen/corelib/list_reversed_test.dart
index ea1e780..05dba7a 100644
--- a/pkg/dev_compiler/test/codegen/corelib/list_reversed_test.dart
+++ b/pkg/dev_compiler/test/codegen/corelib/list_reversed_test.dart
@@ -16,12 +16,12 @@
 
 void testOperations() {
   // Comparison lists.
-  List l = const [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
-  List r = const [10, 9, 8, 7, 6, 5, 4, 3, 2, 1];
+  var l = const [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+  var r = const [10, 9, 8, 7, 6, 5, 4, 3, 2, 1];
   // A base list that starts out like l.
-  List base = l.toList();
+  var base = l.toList();
   // A lazy reverse of base.
-  Iterable reversed = base.reversed;
+  var reversed = base.reversed;
 
   Expect.listEquals(r, reversed.toList());
   Expect.listEquals(l, reversed.toList().reversed.toList());
@@ -49,7 +49,7 @@
       reversed.skip(2).toList().reversed.skip(2).toList().reversed.toList());
 
 
-  void testList(List list) {
+  void testList(List<int> list) {
     var throws = const ThrowMarker();
     void testEquals(v1, v2, path) {
       if (v1 is Iterable) {
@@ -71,12 +71,12 @@
       }
     }
 
-    void testOp(operation(Iterable reversedList), name) {
-      List reversedList = new List(list.length);
+    void testOp(operation(Iterable<int> reversedList), name) {
+      var reversedList = new List<int>(list.length);
       for (int i = 0; i < list.length; i++) {
         reversedList[i] = list[list.length - 1 - i];
       }
-      Iterable reversed = list.reversed;
+      var reversed = list.reversed;
       var expect;
       try {
         expect = operation(reversedList);
@@ -107,7 +107,7 @@
     testOp((i) => i.every((n) => n < 5), "every<5");
     testOp((i) => i.every((n) => n < 10), "every<10");
     testOp((i) => i.reduce((a, b) => a + b), "reduce-sum");
-    testOp((i) => i.fold(0, (a, b) => a + b), "fold-sum");
+    testOp((i) => i.fold/*<int>*/(0, (a, b) => a + b), "fold-sum");
     testOp((i) => i.join("-"), "join-");
     testOp((i) => i.join(""), "join");
     testOp((i) => i.join(), "join-null");
diff --git a/pkg/dev_compiler/test/codegen/language/implicit_super_constructor_test.dart b/pkg/dev_compiler/test/codegen/language/implicit_super_constructor_test.dart
new file mode 100644
index 0000000..2c31206
--- /dev/null
+++ b/pkg/dev_compiler/test/codegen/language/implicit_super_constructor_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2016, 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";
+
+abstract class A {
+  int _x = 42;
+}
+
+abstract class B extends A {}
+
+class C extends B {
+  C() {}
+}
+
+main() {
+  // Regression test for https://github.com/dart-lang/sdk/issues/27421
+  Expect.equals(new C()._x, 42);
+}
diff --git a/pkg/dev_compiler/test/codegen/language/map_literal5_test.dart b/pkg/dev_compiler/test/codegen/language/map_literal5_test.dart
index 365f218..0c2fa17 100644
--- a/pkg/dev_compiler/test/codegen/language/map_literal5_test.dart
+++ b/pkg/dev_compiler/test/codegen/language/map_literal5_test.dart
@@ -32,7 +32,7 @@
   }
 }
 
-create(bool b) {
+Map create(bool b) {
   return {
     b: 0,
     m(b): n(b),
@@ -40,5 +40,5 @@
   };
 }
 
-m(bool b) => b ? 2 : "bar";
-n(bool b) => b ? 3 : "baz";
\ No newline at end of file
+Object m(bool b) => b ? 2 : "bar";
+Object n(bool b) => b ? 3 : "baz";
\ No newline at end of file
diff --git a/pkg/dev_compiler/test/codegen/language/regress_21998_3_test.dart b/pkg/dev_compiler/test/codegen/language/regress_21998_3_test.dart
index 2eac880..92a4ae1 100644
--- a/pkg/dev_compiler/test/codegen/language/regress_21998_3_test.dart
+++ b/pkg/dev_compiler/test/codegen/language/regress_21998_3_test.dart
@@ -15,6 +15,6 @@
   max(a) => a;
 
   m() {
-    return max(Math.max(lib2_max(1, 2), lib1.max('a', 'b', 'cd').length));
+    return max(Math.max/*<num>*/(lib2_max(1, 2), lib1.max('a', 'b', 'cd').length));
   }
 }
\ No newline at end of file
diff --git a/pkg/dev_compiler/test/codegen/language/regress_21998_4_test.dart b/pkg/dev_compiler/test/codegen/language/regress_21998_4_test.dart
index 7afe1ac..5de6774 100644
--- a/pkg/dev_compiler/test/codegen/language/regress_21998_4_test.dart
+++ b/pkg/dev_compiler/test/codegen/language/regress_21998_4_test.dart
@@ -16,7 +16,7 @@
   max(a) => a;
 
   m() {
-    return max(Math.max(
+    return max(Math.max/*<num>*/(
                lib3_max(0, lib2_max(1, 2)), lib1.max('a', 'b', 'cd').length));
   }
 }
\ No newline at end of file
diff --git a/pkg/dev_compiler/test/codegen/language/regress_21998_lib2.dart b/pkg/dev_compiler/test/codegen/language/regress_21998_lib2.dart
index 8d1ac893..d92071d 100644
--- a/pkg/dev_compiler/test/codegen/language/regress_21998_lib2.dart
+++ b/pkg/dev_compiler/test/codegen/language/regress_21998_lib2.dart
@@ -6,4 +6,4 @@
 
 import 'dart:math';
 
-lib2_max(a, b) => max(a, b);
\ No newline at end of file
+lib2_max(a, b) => max/*<num>*/(a, b);
\ No newline at end of file
diff --git a/pkg/dev_compiler/test/codegen/language/regress_21998_lib3.dart b/pkg/dev_compiler/test/codegen/language/regress_21998_lib3.dart
index a18f2ff..5b8f488 100644
--- a/pkg/dev_compiler/test/codegen/language/regress_21998_lib3.dart
+++ b/pkg/dev_compiler/test/codegen/language/regress_21998_lib3.dart
@@ -6,4 +6,4 @@
 
 import 'dart:math' as math;
 
-lib3_max(a, b) => math.max(a, b);
\ No newline at end of file
+lib3_max(a, b) => math.max/*<num>*/(a, b);
\ No newline at end of file
diff --git a/pkg/dev_compiler/test/codegen/language/string_optimizations_test.dart b/pkg/dev_compiler/test/codegen/language/string_optimizations_test.dart
index 1374bb3..afaf7ea 100644
--- a/pkg/dev_compiler/test/codegen/language/string_optimizations_test.dart
+++ b/pkg/dev_compiler/test/codegen/language/string_optimizations_test.dart
@@ -21,7 +21,7 @@
 }
 
 main() {
-  var a = [foo(path: '42'), foo(), 42, bar(path: '54')];
+  var a = <Object>[foo(path: '42'), foo(), 42, bar(path: '54')];
   Expect.isTrue(a[1] is String);
   Expect.throws(() => bar().concat('54'), (e) => e is NoSuchMethodError);
 }
diff --git a/pkg/dev_compiler/test/not_yet_strong_tests.dart b/pkg/dev_compiler/test/not_yet_strong_tests.dart
index 8ae6e78..f0d4c34 100644
--- a/pkg/dev_compiler/test/not_yet_strong_tests.dart
+++ b/pkg/dev_compiler/test/not_yet_strong_tests.dart
@@ -1478,8 +1478,6 @@
   'language/regress_21793_test_01_multi',
   'language/regress_21912_test_01_multi',
   'language/regress_21912_test_02_multi',
-  'language/regress_21998_3_test',
-  'language/regress_21998_4_test',
   'language/regress_22438_test',
   'language/regress_22936_test_01_multi',
   'language/regress_23038_test_01_multi',
diff --git a/pkg/dev_compiler/tool/global_compile.dart b/pkg/dev_compiler/tool/global_compile.dart
index cded0c7..b604099 100644
--- a/pkg/dev_compiler/tool/global_compile.dart
+++ b/pkg/dev_compiler/tool/global_compile.dart
@@ -28,6 +28,8 @@
         defaultsTo: 'out.js')
     ..addFlag('unsafe-force-compile',
         help: 'Generate code with undefined behavior', negatable: false)
+    ..addFlag('emit-metadata',
+        help: 'Preserve annotations in generated code', negatable: false)
     ..addOption('package-root',
         help: 'Directory containing packages',
         abbr: 'p',
@@ -47,16 +49,22 @@
   var unsafe = options['unsafe-force-compile'] as bool;
   var log = options['log'] as bool;
   var tmp = options['tmp'] as String;
+  var metadata = options['emit-metadata'] as bool;
 
   // Build an invocation to dartdevc
   var dartPath = Platform.resolvedExecutable;
   var ddcPath = path.dirname(path.dirname(Platform.script.toFilePath()));
   var template = [
     '$ddcPath/bin/dartdevc.dart',
-    '--no-source-map', // Invalid as we're just concatenating files below
+    '--modules=legacy', // TODO(vsm): Change this to use common format.
+    '--single-out-file',
+    '--inline-source-map',
     '-p',
     packageRoot
   ];
+  if (metadata) {
+    template.add('--emit-metadata');
+  }
   if (unsafe) {
     template.add('--unsafe-force-compile');
   }
@@ -78,11 +86,12 @@
   // Prepend Dart runtime files to the output
   var out = new File(outfile);
   var dartLibrary =
-      new File(path.join(ddcPath, 'lib', 'runtime', 'dart_library.js'))
+      new File(path.join(ddcPath, 'lib', 'js', 'legacy', 'dart_library.js'))
           .readAsStringSync();
   out.writeAsStringSync(dartLibrary);
-  var dartSdk = new File(path.join(ddcPath, 'lib', 'runtime', 'dart_sdk.js'))
-      .readAsStringSync();
+  var dartSdk =
+      new File(path.join(ddcPath, 'lib', 'js', 'legacy', 'dart_sdk.js'))
+          .readAsStringSync();
   out.writeAsStringSync(dartSdk, mode: FileMode.APPEND);
 
   // Linearize module concatenation for deterministic output
diff --git a/pkg/pkg.status b/pkg/pkg.status
index a647224..db253b5 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -19,6 +19,9 @@
 
 dart_messages/test/dart_messages_test: Skip  # Requires a package root.
 
+[ $compiler == dart2analyzer ]
+dev_compiler/gen/*: SkipByDesign
+
 [ $compiler == none && ($runtime == drt || $runtime == dartium) ]
 mutation_observer: Skip # Issue 21149
 unittest/*: Skip # Issue 21949
diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn
index df10d3a..afc963ab 100644
--- a/runtime/BUILD.gn
+++ b/runtime/BUILD.gn
@@ -2,10 +2,6 @@
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
 
-# TODO(zra): These build arguments should likely be moved to a gni file that is
-# included in BUILD.gn files that care about the values of the flags. For now,
-# since the GN build only happens as part of a Mojo build there is no need for
-# the indirection.
 declare_args() {
   # Instead of using is_debug, we introduce a different flag for specifying a
   # Debug build of Dart so that clients can still use a Release build of Dart
@@ -20,6 +16,10 @@
   # CPU profiling features enabled.
   # 'release' - The VM is built to run with AOT compiled code with no developer
   # features enabled.
+  #
+  # These settings are only used for Flutter, at the moment. A standalone build
+  # of the Dart VM should leave this set to "develop", and should set
+  # 'is_debug', 'is_release', or 'is_product'.
   dart_runtime_mode = "develop"
 
   # Explicitly set the target architecture in case of precompilation. Leaving
@@ -36,8 +36,8 @@
   ]
 }
 
-# Controls PRODUCT #define.
-config("dart_product_config") {
+# Adds PRODUCT define if Flutter has specified "release" for dart_runtime_mode
+config("dart_maybe_product_config") {
   defines = []
 
   if ((dart_runtime_mode != "develop") &&
@@ -56,8 +56,9 @@
   }
 }
 
-# Controls DART_PRECOMPILED_RUNTIME #define.
-config("dart_precompiled_runtime_config") {
+# Adds the DART_PRECOMPILED_RUNTIME define if Flutter has specified "profile" or
+# "release" for dart_runtime_mode.
+config("dart_maybe_precompiled_runtime_config") {
   defines = []
 
   if ((dart_runtime_mode != "develop") &&
@@ -83,12 +84,22 @@
   }
 }
 
+config("dart_precompiled_runtime_config") {
+  defines = []
+  defines += ["DART_PRECOMPILED_RUNTIME"]
+}
+
 # Controls DART_PRECOMPILER #define.
 config("dart_precompiler_config") {
   defines = []
   defines += ["DART_PRECOMPILER"]
 }
 
+config("dart_no_snapshot_config") {
+  defines = []
+  defines += ["DART_NO_SNAPSHOT"]
+}
+
 config("dart_config") {
   defines = []
 
@@ -97,23 +108,39 @@
   }
 
   if (dart_target_arch != "") {
-    if (dart_target_arch == "arm") {
+    if ((dart_target_arch == "arm") ||
+        (dart_target_arch == "simarm")) {
       defines += [ "TARGET_ARCH_ARM" ]
       if (target_os == "mac" || target_os == "ios") {
         defines += [ "TARGET_ABI_IOS" ]
       } else {
         defines += [ "TARGET_ABI_EABI" ]
       }
-    } else if (dart_target_arch == "arm64") {
+    } else if ((dart_target_arch == "armv6") ||
+               (dart_target_arch == "simarmv6")) {
+      defines += [ "TARGET_ARCH_ARM" ]
+      defines += [ "TARGET_ARCH_ARM_6" ]
+      defines += [ "TARGET_ABI_EABI" ]
+    } else if ((dart_target_arch == "armv5te") ||
+               (dart_target_arch == "simarmv5te")) {
+      defines += [ "TARGET_ARCH_ARM" ]
+      defines += [ "TARGET_ARCH_ARM_5TE" ]
+      defines += [ "TARGET_ABI_EABI" ]
+    } else if ((dart_target_arch == "arm64") ||
+               (dart_target_arch == "simarm64")) {
       defines += [ "TARGET_ARCH_ARM64" ]
-    } else if (dart_target_arch == "mips") {
+    } else if ((dart_target_arch == "mips") ||
+               (dart_target_arch == "simmips")) {
       defines += [ "TARGET_ARCH_MIPS" ]
     } else if (dart_target_arch == "x64") {
       defines += [ "TARGET_ARCH_X64" ]
     } else if (dart_target_arch == "ia32") {
       defines += [ "TARGET_ARCH_IA32" ]
-    } else if (dart_target_arch == "dbc") {
+    } else if ((dart_target_arch == "dbc") ||
+               (dart_target_arch == "simdbc") ||
+               (dart_target_arch == "simdbc64")) {
       defines += [ "TARGET_ARCH_DBC" ]
+      defines += [ "USING_SIMULATOR" ]
     } else  {
       print("Invalid |dart_target_arch|")
       assert(false)
@@ -159,31 +186,97 @@
   }
 }
 
-static_library("libdart") {
-  configs += [":dart_config",
-              ":dart_product_config",
-              ":dart_precompiled_runtime_config"]
-  deps = [
+template("libdart_library") {
+  extra_configs = []
+  if (defined(invoker.extra_configs)) {
+    extra_configs += invoker.extra_configs
+  }
+  extra_deps = []
+  if (defined(invoker.extra_deps)) {
+    extra_deps += invoker.extra_deps
+  }
+  static_library(target_name) {
+    configs += [
+      ":dart_config",
+      ":dart_maybe_product_config"
+    ] + extra_configs
+    deps = [
+      "vm:libdart_platform",
+      "third_party/double-conversion/src:libdouble_conversion",
+      ":generate_version_cc_file",
+    ] + extra_deps
+    include_dirs = [
+      ".",
+    ]
+    public_configs = [":dart_public_config"]
+    sources = [
+      "include/dart_api.h",
+      "include/dart_mirrors_api.h",
+      "include/dart_native_api.h",
+      "include/dart_tools_api.h",
+      "vm/dart_api_impl.cc",
+      "vm/debugger_api_impl.cc",
+      "vm/mirrors_api_impl.cc",
+      "vm/native_api_impl.cc",
+      "vm/version.h",
+      "$target_gen_dir/version.cc",
+    ]
+    defines = [
+      "DART_SHARED_LIB",
+    ]
+  }
+}
+
+libdart_library("libdart") {
+  extra_configs = [
+    ":dart_maybe_precompiled_runtime_config"
+  ]
+  extra_deps = [
     "vm:libdart_lib",
     "vm:libdart_vm",
-    "third_party/double-conversion/src:libdouble_conversion",
-    ":generate_version_cc_file",
   ]
-  include_dirs = [
-    ".",
+}
+
+libdart_library("libdart_precompiled_runtime") {
+  extra_configs = [
+    ":dart_precompiled_runtime_config"
   ]
-  public_configs = [":dart_public_config"]
-  sources = [
-    "include/dart_api.h",
-    "include/dart_mirrors_api.h",
-    "include/dart_native_api.h",
-    "include/dart_tools_api.h",
-    "vm/dart_api_impl.cc",
-    "vm/debugger_api_impl.cc",
-    "vm/mirrors_api_impl.cc",
-    "vm/native_api_impl.cc",
-    "vm/version.h",
-    "$target_gen_dir/version.cc",
+  extra_deps = [
+    "vm:libdart_lib_precompiled_runtime",
+    "vm:libdart_vm_precompiled_runtime",
+  ]
+}
+
+libdart_library("libdart_nosnapshot") {
+  extra_configs = [
+    ":dart_no_snapshot_config",
+    ":dart_maybe_precompiled_runtime_config"
+  ]
+  extra_deps = [
+    "vm:libdart_lib_nosnapshot",
+    "vm:libdart_vm_nosnapshot",
+  ]
+}
+
+libdart_library("libdart_nosnapshot_precompiled_runtime") {
+  extra_configs = [
+    ":dart_no_snapshot_config",
+    ":dart_precompiled_runtime_config"
+  ]
+  extra_deps = [
+    "vm:libdart_lib_nosnapshot_precompiled_runtime",
+    "vm:libdart_vm_nosnapshot_precompiled_runtime",
+  ]
+}
+
+libdart_library("libdart_nosnapshot_with_precompiler") {
+  extra_configs = [
+    ":dart_no_snapshot_config",
+    ":dart_precompiler_config",
+  ]
+  extra_deps = [
+    "vm:libdart_lib_nosnapshot_with_precompiler",
+    "vm:libdart_vm_nosnapshot_with_precompiler",
   ]
 }
 
@@ -211,8 +304,7 @@
 
 executable("libdart_dependency_helper") {
   configs += [":dart_config",
-              ":dart_product_config",
-              ":dart_precompiled_runtime_config"]
+              ":dart_maybe_product_config"]
   deps = [
     "vm:libdart_lib_nosnapshot",
     "vm:libdart_lib",
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index d03757b..549807b 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -2,6 +2,22 @@
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
 
+declare_args() {
+  # Whether to fall back to built-in root certificates when they cannot be
+  # verified at the operating system level.
+  dart_use_fallback_root_certificates = false
+
+  # The BUILD.gn file that we pull from chromium as part of zlib has a
+  # dependence on //base, which we don't pull in. In a standalone build of the
+  # VM, we set this to //runtime/bin/zlib where we have a BUILD.gn file without
+  # a dependence on //base.
+  dart_zlib_path = "//third_party/zlib"
+
+  # Whether to link the standalone VM against tcmalloc. The standalone build of
+  # the VM enables this only for Linux builds.
+  dart_use_tcmalloc = false
+}
+
 resources_sources_gypi =
     exec_script("../../tools/gypi_to_gn.py",
                 [rebase_path("vmservice/vmservice_sources.gypi")],
@@ -31,7 +47,6 @@
   ] + rebase_path(sources, root_build_dir)
 }
 
-
 template("gen_library_src_path") {
   assert(defined(invoker.sources), "Need sources in $target_name")
   assert(defined(invoker.output), "Need output in $target_name")
@@ -45,17 +60,20 @@
     outputs = [ invoker.output, ]
     name = invoker.name
     kind = invoker.kind
+    library_name = "dart:${name}"
+    if (defined(invoker.library_name)) {
+      library_name = invoker.library_name
+    }
     args = [
       "--output", rebase_path(invoker.output, root_build_dir),
       "--input_cc", rebase_path("builtin_in.cc", root_build_dir),
       "--include", "bin/builtin.h",
       "--var_name", "dart::bin::Builtin::${name}_${kind}_paths_",
-      "--library_name", "dart:${name}",] +
+      "--library_name", library_name,] +
       rebase_path(invoker.sources, root_build_dir)
   }
 }
 
-
 builtin_sources_gypi =
     exec_script("../../tools/gypi_to_gn.py",
                 [rebase_path("builtin_sources.gypi")],
@@ -69,7 +87,6 @@
   output = "$target_gen_dir/builtin_gen.cc"
 }
 
-
 sdk_io_sources_gypi =
     exec_script("../../tools/gypi_to_gn.py",
                 [rebase_path("../../sdk/lib/io/io_sources.gypi")],
@@ -98,14 +115,105 @@
   output = "$target_gen_dir/io_patch_gen.cc"
 }
 
+gen_library_src_path("generate_html_cc_file") {
+  name = "html"
+  kind = "source"
+  sources = ["../../sdk/lib/html/dartium/html_dartium.dart"]
+  output = "$target_gen_dir/html_gen.cc"
+}
+
+gen_library_src_path("generate_html_common_cc_file") {
+  name = "html_common"
+  kind = "source"
+  sources = [
+    "../../sdk/lib/html/html_common/html_common.dart",
+    "../../sdk/lib/html/html_common/css_class_set.dart",
+    "../../sdk/lib/html/html_common/device.dart",
+    "../../sdk/lib/html/html_common/filtered_element_list.dart",
+    "../../sdk/lib/html/html_common/lists.dart",
+    "../../sdk/lib/html/html_common/conversions.dart",
+    "../../sdk/lib/html/html_common/conversions_dartium.dart",
+  ]
+  output = "$target_gen_dir/html_common_gen.cc"
+}
+
+gen_library_src_path("generate_js_cc_file") {
+  name = "js"
+  kind = "source"
+  sources = ["../../sdk/lib/js/dartium/js_dartium.dart"]
+  output = "$target_gen_dir/js_gen.cc"
+}
+
+gen_library_src_path("generate_blink_cc_file") {
+  name = "_blink"
+  kind = "source"
+  sources = ["../../sdk/lib/_blink/dartium/_blink_dartium.dart"]
+  output = "$target_gen_dir/blink_gen.cc"
+}
+
+gen_library_src_path("generate_indexed_db_cc_file") {
+  name = "indexed_db"
+  kind = "source"
+  sources = ["../../sdk/lib/indexed_db/dartium/indexed_db_dartium.dart"]
+  output = "$target_gen_dir/indexed_db_gen.cc"
+}
+
+gen_library_src_path("generate_cached_patches_cc_file") {
+  name = "cached_patches"
+  library_name = "cached_patches.dart"
+  kind = "sources"
+  sources = ["../../sdk/lib/js/dartium/cached_patches.dart"]
+  output = "$target_gen_dir/cached_patches_gen.cc"
+}
+
+gen_library_src_path("generate_web_gl_cc_file") {
+  name = "web_gl"
+  kind = "source"
+  sources = ["../../sdk/lib/web_gl/dartium/web_gl_dartium.dart"]
+  output = "$target_gen_dir/web_gl_gen.cc"
+}
+
+gen_library_src_path("generate_metadata_cc_file") {
+  name = "metadata"
+  library_name = "metadata.dart"
+  kind = "source"
+  sources = ["../../sdk/lib/html/html_common/metadata.dart"]
+  output = "$target_gen_dir/metadata_gen.cc"
+}
+
+gen_library_src_path("generate_web_sql_cc_file") {
+  name = "web_sql"
+  kind = "source"
+  sources = ["../../sdk/lib/web_sql/dartium/web_sql_dartium.dart"]
+  output = "$target_gen_dir/web_sql_gen.cc"
+}
+
+gen_library_src_path("generate_svg_cc_file") {
+  name = "svg"
+  kind = "source"
+  sources = ["../../sdk/lib/svg/dartium/svg_dartium.dart"]
+  output = "$target_gen_dir/svg_gen.cc"
+}
+
+gen_library_src_path("generate_web_audio_cc_file") {
+  name = "web_audio"
+  kind = "source"
+  sources = ["../../sdk/lib/web_audio/dartium/web_audio_dartium.dart"]
+  output = "$target_gen_dir/web_audio_gen.cc"
+}
 
 config("libdart_builtin_config") {
   libs = [
     "dl",
   ]
+  if (is_android) {
+    libs += [
+      "android",
+      "log",
+    ]
+  }
 }
 
-
 builtin_impl_sources_gypi =
     exec_script("../../tools/gypi_to_gn.py",
                 [rebase_path("builtin_impl_sources.gypi")],
@@ -113,12 +221,24 @@
                 ["builtin_impl_sources.gypi"])
 
 static_library("libdart_builtin") {
-  configs += ["..:dart_config", "..:dart_product_config"]
+  configs += ["..:dart_config",
+              "..:dart_maybe_product_config"]
   public_configs = [":libdart_builtin_config"]
   deps = [
     ":generate_builtin_cc_file",
     ":generate_io_cc_file",
     ":generate_io_patch_cc_file",
+    ":generate_html_cc_file",
+    ":generate_html_common_cc_file",
+    ":generate_js_cc_file",
+    ":generate_blink_cc_file",
+    ":generate_indexed_db_cc_file",
+    ":generate_cached_patches_cc_file",
+    ":generate_web_gl_cc_file",
+    ":generate_metadata_cc_file",
+    ":generate_web_sql_cc_file",
+    ":generate_svg_cc_file",
+    ":generate_web_audio_cc_file",
   ]
   include_dirs = [
     "..",
@@ -133,74 +253,6 @@
   ] + builtin_impl_sources_gypi.sources
 }
 
-
-static_library("libdart_nosnapshot") {
-  configs += ["..:dart_config",
-              "..:dart_product_config",
-              "..:dart_precompiled_runtime_config"]
-  deps = [
-    "../vm:libdart_lib_nosnapshot",
-    "../vm:libdart_vm_nosnapshot",
-    "../vm:libdart_platform",
-    "../third_party/double-conversion/src:libdouble_conversion",
-    "..:generate_version_cc_file",
-  ]
-
-  sources = [
-    "../include/dart_api.h",
-    "../include/dart_mirrors_api.h",
-    "../include/dart_native_api.h",
-    "../include/dart_tools_api.h",
-    "../vm/dart_api_impl.cc",
-    "../vm/debugger_api_impl.cc",
-    "../vm/mirrors_api_impl.cc",
-    "../vm/native_api_impl.cc",
-    "$target_gen_dir/../version.cc",
-  ]
-
-  include_dirs = [
-    "..",
-  ]
-
-  defines = [
-    "DART_SHARED_LIB",
-  ]
-}
-
-
-static_library("libdart_nosnapshot_with_precompiler") {
-  configs += ["..:dart_config",
-              "..:dart_product_config",
-              "..:dart_precompiler_config"]
-  deps = [
-    "../vm:libdart_lib_nosnapshot_with_precompiler",
-    "../vm:libdart_vm_nosnapshot_with_precompiler",
-    "../vm:libdart_platform",
-    "../third_party/double-conversion/src:libdouble_conversion",
-    "..:generate_version_cc_file",
-  ]
-
-  sources = [
-    "../include/dart_api.h",
-    "../include/dart_mirrors_api.h",
-    "../include/dart_native_api.h",
-    "../include/dart_tools_api.h",
-    "../vm/dart_api_impl.cc",
-    "../vm/debugger_api_impl.cc",
-    "../vm/mirrors_api_impl.cc",
-    "../vm/native_api_impl.cc",
-    "$target_gen_dir/../version.cc",
-  ]
-
-  include_dirs = [
-    "..",
-  ]
-
-  defines = [
-    "DART_SHARED_LIB",
-  ]
-}
-
 io_impl_sources_gypi =
     exec_script("../../tools/gypi_to_gn.py",
                 [ rebase_path("io_impl_sources.gypi") ],
@@ -209,7 +261,7 @@
 
 executable("gen_snapshot") {
   configs += ["..:dart_config",
-              "..:dart_product_config",
+              "..:dart_maybe_product_config",
               "..:dart_precompiler_config"]
   deps = [
     ":gen_resources_cc",
@@ -218,7 +270,7 @@
     ":generate_io_cc_file",
     ":generate_io_patch_cc_file",
     ":libdart_builtin",
-    ":libdart_nosnapshot_with_precompiler",
+    "..:libdart_nosnapshot_with_precompiler",
   ]
 
   sources = [
@@ -254,11 +306,11 @@
 # (without secure sockets) suitable for linking with gen_snapshot.
 source_set("gen_snapshot_dart_io") {
   configs += ["..:dart_config",
-              "..:dart_product_config",
+              "..:dart_maybe_product_config",
               "..:dart_precompiler_config"]
 
   deps = [
-    "//third_party/zlib",
+    "$dart_zlib_path",
   ]
 
   custom_sources_filter = [
@@ -293,22 +345,16 @@
 
 source_set("libdart_embedder_noio") {
   configs += ["..:dart_config",
-              "..:dart_product_config",
-              "..:dart_precompiled_runtime_config"]
+              "..:dart_maybe_product_config"]
   deps = [
     "..:libdart",
-    "../vm:libdart_platform",
   ]
 }
 
-
-# A source set for the implementation of 'dart:io' library
-# (without secure sockets).
+# A source set for the implementation of 'dart:io' library.
 source_set("embedded_dart_io") {
   configs += ["..:dart_config",
-              "..:dart_product_config",
-              "..:dart_precompiled_runtime_config"]
-
+              "..:dart_maybe_product_config"]
   custom_sources_filter = [
     "*_test.cc",
     "*_test.h",
@@ -324,12 +370,15 @@
   }
   set_sources_assignment_filter(custom_sources_filter)
 
+  defines = []
   if (is_mac || is_ios) {
     libs = [
+      "CoreFoundation.framework",
+      "CoreServices.framework",
       "Security.framework",
     ]
   } else if (defined(is_fuchsia) && is_fuchsia) {
-    defines = [
+    defines += [
       "DART_IO_SECURE_SOCKET_DISABLED"
     ]
   } else {
@@ -352,8 +401,15 @@
     "log_win.cc",
     "log.h",
   ]
-  if (is_linux) {
-    sources += [ "../../third_party/root_certificates/root_certificates.cc"]
+
+  if (is_linux || is_win) {
+    if (dart_use_fallback_root_certificates) {
+      sources += [ "//third_party/root_certificates/root_certificates.cc"]
+    } else {
+      defines += [
+        "DART_IO_ROOT_CERTS_DISABLED",
+      ]
+    }
   }
 
   include_dirs = [
@@ -362,7 +418,6 @@
   ]
 }
 
-
 action("generate_snapshot_bin") {
   deps = [
     "../bin:gen_snapshot($host_toolchain)",
@@ -395,7 +450,6 @@
   ]
 }
 
-
 action("generate_snapshot_file") {
   deps = [
     ":generate_snapshot_bin",
@@ -426,7 +480,6 @@
   ]
 }
 
-
 source_set("dart_snapshot_cc") {
   sources = [
     "$root_gen_dir/dart_snapshot.cc",
@@ -437,114 +490,104 @@
   ]
 }
 
-if (defined(is_fuchsia) && is_fuchsia) {
-  copy("hello_fuchsia") {
-    sources = [ "../tests/vm/dart/hello_fuchsia_test.dart" ]
-    outputs = [ "$root_out_dir/hello_fuchsia.dart" ]
+template("dart_executable") {
+  extra_configs = []
+  if (defined(invoker.extra_configs)) {
+    extra_configs += invoker.extra_configs
   }
+  extra_deps = []
+  if (defined(invoker.extra_deps)) {
+    extra_deps += invoker.extra_deps
+  }
+  extra_defines = []
+  if (defined(invoker.extra_defines)) {
+    extra_defines = invoker.extra_defines
+  }
+  extra_sources = []
+  if (defined(invoker.extra_sources)) {
+    extra_sources += invoker.extra_sources
+  }
+  executable(target_name) {
+    configs += [
+      "..:dart_config",
+      "..:dart_maybe_product_config"
+    ] + extra_configs
 
-  executable("dart_no_observatory") {
-    configs += ["..:dart_config",
-                "..:dart_product_config",
-                "..:dart_precompiled_runtime_config",]
     deps = [
-      ":hello_fuchsia",
       ":gen_resources_cc",
       ":embedded_dart_io",
       ":libdart_builtin",
-      "../vm:libdart_platform",
-      "..:libdart",
-      ":dart_snapshot_cc",
-      "//third_party/zlib",
-    ]
+      "$dart_zlib_path",
+    ] + extra_deps
 
-    defines = [
-      "NO_OBSERVATORY",
-    ]
+    if (dart_use_tcmalloc) {
+      deps += [
+        "//third_party/tcmalloc",
+      ]
+    }
+
+    defines = extra_defines
 
     sources = [
       "main.cc",
-      "observatory_assets_empty.cc",
       "vmservice_impl.cc",
       "vmservice_impl.h",
       "$target_gen_dir/resources_gen.cc",
-    ]
+    ] + extra_sources
 
     include_dirs = [
       "..",
       "//third_party",
     ]
-  }
 
-  action("generate_snapshot_test_dat_file") {
-    snapshot_test_dat_file = "$root_gen_dir/snapshot_test.dat"
-    snapshot_test_in_dat_file = "../vm/snapshot_test_in.dat"
-    snapshot_test_dart_file = "../vm/snapshot_test.dart"
-    inputs = [
-      "../tools/create_string_literal.py",
-      snapshot_test_in_dat_file,
-      snapshot_test_dart_file,
-    ]
-
-    outputs = [
-      snapshot_test_dat_file,
-    ]
-
-    script = "../tools/create_string_literal.py"
-    args = [
-      "--output",
-      rebase_path(snapshot_test_dat_file),
-      "--input_cc",
-      rebase_path(snapshot_test_in_dat_file),
-      "--include",
-      "INTENTIONALLY_LEFT_BLANK",
-      "--var_name",
-      "INTENTIONALLY_LEFT_BLANK_TOO",
-      rebase_path(snapshot_test_dart_file),
+    ldflags = [
+      "-rdynamic",
     ]
   }
+}
 
-  executable("run_vm_tests") {
-    testonly = true
-    configs += ["..:dart_config",
-                "..:dart_product_config",
-                "..:dart_precompiled_runtime_config",]
-    deps = [
+if (!defined(is_fuchsia) || !is_fuchsia) {
+  dart_executable("dart") {
+    extra_deps = [
       "..:libdart",
-      ":libdart_builtin",
-      ":embedded_dart_io",
       ":dart_snapshot_cc",
-      ":generate_snapshot_test_dat_file",
-      "../vm:libdart_platform",
-      "//third_party/zlib",
+      "../observatory:standalone_observatory_archive",
     ]
-    include_dirs = [
-      "..",
-      "$target_gen_dir",
+  }
+
+  dart_executable("dart_precompiled_runtime") {
+    extra_configs = [
+      "..:dart_precompiled_runtime_config"
     ]
-    defines = [
-      "TESTING",
+    extra_deps = [
+      "..:libdart_precompiled_runtime",
+      ":dart_snapshot_cc",
+      "../observatory:standalone_observatory_archive",
     ]
+  }
+}
 
-    vm_tests_list = exec_script("../../tools/gypi_to_gn.py",
-                                  [rebase_path("../vm/vm_sources.gypi"),
-                                   "--keep_only=_test.cc",
-                                   "--keep_only=_test.h",],
-                                  "scope",
-                                  ["../vm/vm_sources.gypi"])
-    vm_tests = rebase_path(vm_tests_list.sources, ".", "../vm")
+dart_executable("dart_bootstrap") {
+  extra_configs = [
+    "..:dart_precompiler_config",
+    "..:dart_no_snapshot_config",
+  ]
+  extra_deps = [
+    "..:libdart",
+  ]
+  extra_defines = [
+    "NO_OBSERVATORY",
+  ]
+  extra_sources = [
+    "observatory_assets_empty.cc",
+    "snapshot_empty.cc",
+  ]
+}
 
-    builtin_impl_tests_list =
-        exec_script("../../tools/gypi_to_gn.py",
-                    [rebase_path("builtin_impl_sources.gypi"),
-                     "--keep_only=_test.cc",
-                     "--keep_only=_test.h",],
-                    "scope",
-                    ["builtin_impl_sources.gypi"])
-
-    sources = [
-      "run_vm_tests.cc",
-    ] + builtin_impl_tests_list.sources + vm_tests
+if (defined(is_fuchsia) && is_fuchsia) {
+  copy("hello_fuchsia") {
+    sources = [ "../tests/vm/dart/hello_fuchsia_test.dart" ]
+    outputs = [ "$root_out_dir/hello_fuchsia.dart" ]
   }
 
   executable("run_vm_tests_fuchsia") {
@@ -559,4 +602,144 @@
       "runtime",
     ]
   }
-}  # defined(is_fuchsia) && is_fuchsia
+}
+
+# This is only needed for the Fuchsia target build until the Observatory is
+# supported.
+dart_executable("dart_no_observatory") {
+  extra_deps = [
+    "..:libdart",
+    ":dart_snapshot_cc",
+  ]
+  if (defined(is_fuchsia) && is_fuchsia) {
+    extra_deps += [ ":hello_fuchsia" ]
+  }
+  extra_defines = [
+    "NO_OBSERVATORY",
+  ]
+  extra_sources = [
+    "observatory_assets_empty.cc",
+  ]
+}
+
+executable("process_test") {
+  sources = [
+    "process_test.cc",
+  ]
+}
+
+action("generate_snapshot_test_dat_file") {
+  snapshot_test_dat_file = "$root_gen_dir/snapshot_test.dat"
+  snapshot_test_in_dat_file = "../vm/snapshot_test_in.dat"
+  snapshot_test_dart_file = "../vm/snapshot_test.dart"
+  inputs = [
+    "../tools/create_string_literal.py",
+    snapshot_test_in_dat_file,
+    snapshot_test_dart_file,
+  ]
+
+  outputs = [
+    snapshot_test_dat_file,
+  ]
+
+  script = "../tools/create_string_literal.py"
+  args = [
+    "--output",
+    rebase_path(snapshot_test_dat_file),
+    "--input_cc",
+    rebase_path(snapshot_test_in_dat_file),
+    "--include",
+    "INTENTIONALLY_LEFT_BLANK",
+    "--var_name",
+    "INTENTIONALLY_LEFT_BLANK_TOO",
+    rebase_path(snapshot_test_dart_file),
+  ]
+}
+
+executable("run_vm_tests") {
+  configs += ["..:dart_config",
+              "..:dart_maybe_product_config"]
+  deps = [
+    "..:libdart",
+    ":libdart_builtin",
+    ":embedded_dart_io",
+    ":dart_snapshot_cc",
+    ":generate_snapshot_test_dat_file",
+    "$dart_zlib_path",
+  ]
+  include_dirs = [
+    "..",
+    "$target_gen_dir",
+  ]
+  defines = [
+    "TESTING",
+  ]
+
+  if (dart_use_tcmalloc) {
+    deps += [
+      "//third_party/tcmalloc",
+    ]
+  }
+
+  # The VM sources are already included in libdart, so we just want to add in
+  # the tests here.
+  vm_tests_list = exec_script("../../tools/gypi_to_gn.py",
+                                [rebase_path("../vm/vm_sources.gypi"),
+                                 "--keep_only=_test.cc",
+                                 "--keep_only=_test.h",],
+                                "scope",
+                                ["../vm/vm_sources.gypi"])
+  vm_tests = rebase_path(vm_tests_list.sources, ".", "../vm")
+
+  builtin_impl_tests_list =
+      exec_script("../../tools/gypi_to_gn.py",
+                  [rebase_path("builtin_impl_sources.gypi"),
+                   "--keep_only=_test.cc",
+                   "--keep_only=_test.h",],
+                  "scope",
+                  ["builtin_impl_sources.gypi"])
+
+  sources = [
+    "run_vm_tests.cc",
+  ] + builtin_impl_tests_list.sources + vm_tests
+
+  ldflags = [
+    "-rdynamic",
+  ]
+}
+
+if (!defined(is_fuchsia) || !is_fuchsia) {
+  shared_library("test_extension") {
+    deps = [
+      ":dart",
+    ]
+    sources = [
+      "test_extension.c",
+      "test_extension_dllmain_win.cc",
+    ]
+    include_dirs = [
+      "..",
+    ]
+    defines = [
+      # The only effect of DART_SHARED_LIB is to export the Dart API.
+      "DART_SHARED_LIB",
+    ]
+  }
+
+  shared_library("sample_extension") {
+    deps = [
+      ":dart",
+    ]
+    sources = [
+      "../../samples/sample_extension/sample_extension.cc",
+      "../../samples/sample_extension/sample_extension_dllmain_win.cc",
+    ]
+    include_dirs = [
+      "..",
+    ]
+    defines = [
+      # The only effect of DART_SHARED_LIB is to export the Dart API.
+      "DART_SHARED_LIB",
+    ]
+  }
+}
diff --git a/runtime/bin/bin.gypi b/runtime/bin/bin.gypi
index a31cb93..650f587 100644
--- a/runtime/bin/bin.gypi
+++ b/runtime/bin/bin.gypi
@@ -290,7 +290,7 @@
         '--output', '<(blink_cc_file)',
         '--input_cc', '<(builtin_in_cc_file)',
         '--include', 'bin/builtin.h',
-        '--var_name', 'dart::bin::Builtin::blink_source_paths_',
+        '--var_name', 'dart::bin::Builtin::_blink_source_paths_',
         '--library_name', 'dart:_blink',
         '<@(_sources)',
         ],
@@ -322,7 +322,7 @@
         '--output', '<(indexeddb_cc_file)',
         '--input_cc', '<(builtin_in_cc_file)',
         '--include', 'bin/builtin.h',
-        '--var_name', 'dart::bin::Builtin::indexeddb_source_paths_',
+        '--var_name', 'dart::bin::Builtin::indexed_db_source_paths_',
         '--library_name', 'dart:indexed_db',
         '<@(_sources)',
         ],
@@ -450,7 +450,7 @@
         '--output', '<(websql_cc_file)',
         '--input_cc', '<(builtin_in_cc_file)',
         '--include', 'bin/builtin.h',
-        '--var_name', 'dart::bin::Builtin::websql_source_paths_',
+        '--var_name', 'dart::bin::Builtin::web_sql_source_paths_',
         '--library_name', 'dart:web_sql',
         '<@(_sources)',
         ],
@@ -514,7 +514,7 @@
         '--output', '<(webaudio_cc_file)',
         '--input_cc', '<(builtin_in_cc_file)',
         '--include', 'bin/builtin.h',
-        '--var_name', 'dart::bin::Builtin::webaudio_source_paths_',
+        '--var_name', 'dart::bin::Builtin::web_audio_source_paths_',
         '--library_name', 'dart:web_audio',
         '<@(_sources)',
         ],
diff --git a/runtime/bin/builtin.cc b/runtime/bin/builtin.cc
index 2c303a1..b3215bb 100644
--- a/runtime/bin/builtin.cc
+++ b/runtime/bin/builtin.cc
@@ -25,14 +25,14 @@
   { "dart:html_common", html_common_source_paths_, NULL, NULL, true},
   { "dart:js", js_source_paths_, NULL, NULL, true},
   { "dart:js_util", js_util_source_paths_, NULL, NULL, true},
-  { "dart:_blink", blink_source_paths_, NULL, NULL, true },
-  { "dart:indexed_db", indexeddb_source_paths_, NULL, NULL, true },
+  { "dart:_blink", _blink_source_paths_, NULL, NULL, true },
+  { "dart:indexed_db", indexed_db_source_paths_, NULL, NULL, true },
   { "cached_patches.dart", cached_patches_source_paths_, NULL, NULL, true },
   { "dart:web_gl", web_gl_source_paths_, NULL, NULL, true },
   { "metadata.dart", metadata_source_paths_, NULL, NULL, true },
-  { "dart:web_sql", websql_source_paths_, NULL, NULL, true },
+  { "dart:web_sql", web_sql_source_paths_, NULL, NULL, true },
   { "dart:svg", svg_source_paths_, NULL, NULL, true },
-  { "dart:web_audio", webaudio_source_paths_, NULL, NULL, true },
+  { "dart:web_audio", web_audio_source_paths_, NULL, NULL, true },
 #endif  // defined(DART_NO_SNAPSHOT)
 
   // End marker.
diff --git a/runtime/bin/builtin.h b/runtime/bin/builtin.h
index d90223a..d7e1e4c 100644
--- a/runtime/bin/builtin.h
+++ b/runtime/bin/builtin.h
@@ -75,14 +75,14 @@
   static const char* html_common_source_paths_[];
   static const char* js_source_paths_[];
   static const char* js_util_source_paths_[];
-  static const char* blink_source_paths_[];
-  static const char* indexeddb_source_paths_[];
+  static const char* _blink_source_paths_[];
+  static const char* indexed_db_source_paths_[];
   static const char* cached_patches_source_paths_[];
   static const char* web_gl_source_paths_[];
   static const char* metadata_source_paths_[];
-  static const char* websql_source_paths_[];
+  static const char* web_sql_source_paths_[];
   static const char* svg_source_paths_[];
-  static const char* webaudio_source_paths_[];
+  static const char* web_audio_source_paths_[];
 
   static Dart_Port load_port_;
   static const int num_libs_;
diff --git a/runtime/bin/dart_product_entries.txt b/runtime/bin/dart_product_entries.txt
index 098d0a0..057c6db 100644
--- a/runtime/bin/dart_product_entries.txt
+++ b/runtime/bin/dart_product_entries.txt
@@ -3,5 +3,6 @@
 dart:_builtin,::,_getUriBaseClosure
 dart:_builtin,::,_setWorkingDirectory
 dart:_builtin,::,_setPackageRoot
+dart:_builtin,::,_setPackagesMap
 dart:_builtin,::,_loadPackagesMap
 dart:_builtin,::,_loadDataAsync
diff --git a/runtime/bin/eventhandler_fuchsia.cc b/runtime/bin/eventhandler_fuchsia.cc
index 69c2190..cdd4fad 100644
--- a/runtime/bin/eventhandler_fuchsia.cc
+++ b/runtime/bin/eventhandler_fuchsia.cc
@@ -20,9 +20,9 @@
 namespace bin {
 
 EventHandlerImplementation::EventHandlerImplementation() {
-  mx_status_t status = mx_message_pipe_create(interrupt_handles_, 0);
+  mx_status_t status = mx_msgpipe_create(interrupt_handles_, 0);
   if (status != NO_ERROR) {
-    FATAL1("mx_message_pipe_create failed: %s\n", mx_strstatus(status));
+    FATAL1("mx_msgpipe_create failed: %s\n", mx_strstatus(status));
   }
 }
 
@@ -48,9 +48,9 @@
   msg.data = data;
 
   mx_status_t status =
-    mx_message_write(interrupt_handles_[1], &msg, sizeof(msg), NULL, 0, 0);
+    mx_msgpipe_write(interrupt_handles_[1], &msg, sizeof(msg), NULL, 0, 0);
   if (status != NO_ERROR) {
-    FATAL1("mx_message_write failed: %s\n", mx_strstatus(status));
+    FATAL1("mx_msgpipe_write failed: %s\n", mx_strstatus(status));
   }
 }
 
@@ -60,7 +60,7 @@
   uint32_t bytes = kInterruptMessageSize;
   mx_status_t status;
   while (true) {
-    status = mx_message_read(
+    status = mx_msgpipe_read(
         interrupt_handles_[0], &msg, &bytes, NULL, NULL, 0);
     if (status != NO_ERROR) {
       break;
@@ -77,7 +77,7 @@
   // status == ERR_BAD_STATE when we try to read and there are no messages
   // available, so it is an error if we get here and status != ERR_BAD_STATE.
   if (status != ERR_BAD_STATE) {
-    FATAL1("mx_message_read failed: %s\n", mx_strstatus(status));
+    FATAL1("mx_msgpipe_read failed: %s\n", mx_strstatus(status));
   }
 }
 
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 277220e..8a80c7e 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -78,6 +78,7 @@
 // Global flag that is used to indicate that we want to compile all the
 // dart functions and not run anything.
 static bool compile_all = false;
+static bool parse_all = false;
 
 
 // Global flag that is used to indicate that we want to use blobs/mmap instead
@@ -324,6 +325,17 @@
 }
 
 
+static bool ProcessParseAllOption(const char* arg,
+                                  CommandLineOptions* vm_options) {
+  ASSERT(arg != NULL);
+  if (*arg != '\0') {
+    return false;
+  }
+  parse_all = true;
+  return true;
+}
+
+
 static bool ProcessUseBlobsOption(const char* arg,
                                   CommandLineOptions* vm_options) {
   ASSERT(arg != NULL);
@@ -547,6 +559,7 @@
 
   // VM specific options to the standalone dart program.
   { "--compile_all", ProcessCompileAllOption },
+  { "--parse_all", ProcessParseAllOption },
   { "--enable-vm-service", ProcessEnableVmServiceOption },
   { "--disable-service-origin-check", ProcessDisableServiceOriginCheckOption },
   { "--observe", ProcessObserveOption },
@@ -1515,6 +1528,15 @@
       CHECK_RESULT(result);
     }
 
+    if (parse_all) {
+      result = Dart_ParseAll();
+      CHECK_RESULT(result);
+      Dart_ExitScope();
+      // Shutdown the isolate.
+      Dart_ShutdownIsolate();
+      return false;
+    }
+
     if (is_noopt || (gen_snapshot_kind == kAppAOT)) {
       Dart_QualifiedFunctionName standalone_entry_points[] = {
         { "dart:_builtin", "::", "_getMainClosure" },
@@ -1523,6 +1545,7 @@
         { "dart:_builtin", "::", "_resolveInWorkingDirectory" },
         { "dart:_builtin", "::", "_setWorkingDirectory" },
         { "dart:_builtin", "::", "_setPackageRoot" },
+        { "dart:_builtin", "::", "_setPackagesMap" },
         { "dart:_builtin", "::", "_libraryFilePath" },
         { "dart:io", "::", "_makeUint8ListView" },
         { "dart:io", "::", "_makeDatagram" },
diff --git a/runtime/bin/socket_patch.dart b/runtime/bin/socket_patch.dart
index 0244e79..4850827 100644
--- a/runtime/bin/socket_patch.dart
+++ b/runtime/bin/socket_patch.dart
@@ -70,6 +70,12 @@
   static bool _listSupported() native "NetworkInterface_ListSupported";
 }
 
+void _throwOnBadPort(int port) {
+  if ((port == null) || (port < 0) || (port > 0xFFFF)) {
+    throw new ArgumentError("Invalid port $port");
+  }
+}
+
 class _InternetAddress implements InternetAddress {
   static const int _ADDRESS_LOOPBACK_IP_V4 = 0;
   static const int _ADDRESS_LOOPBACK_IP_V6 = 1;
@@ -387,6 +393,7 @@
   }
 
   static Future<_NativeSocket> connect(host, int port, sourceAddress) {
+    _throwOnBadPort(port);
     if (sourceAddress != null && sourceAddress is! _InternetAddress) {
       if (sourceAddress is String) {
         sourceAddress = new InternetAddress(sourceAddress);
@@ -488,6 +495,7 @@
                                     int backlog,
                                     bool v6Only,
                                     bool shared) {
+    _throwOnBadPort(port);
     return new Future.value(host)
         .then((host) {
           if (host is _InternetAddress) return host;
@@ -526,6 +534,7 @@
 
   static Future<_NativeSocket> bindDatagram(
       host, int port, bool reuseAddress) {
+    _throwOnBadPort(port);
     return new Future.value(host)
         .then((host) {
           if (host is _InternetAddress) return host;
@@ -676,6 +685,7 @@
 
   int send(List<int> buffer, int offset, int bytes,
            InternetAddress address, int port) {
+    _throwOnBadPort(port);
     if (isClosing || isClosed) return 0;
     _BufferAndStart bufferAndStart =
         _ensureFastAndSerializableByteData(
@@ -1116,8 +1126,7 @@
                                        int backlog,
                                        bool v6Only,
                                        bool shared) {
-    if (port < 0 || port > 0xFFFF)
-      throw new ArgumentError("Invalid port $port");
+    _throwOnBadPort(port);
     if (backlog < 0) throw new ArgumentError("Invalid backlog $backlog");
     return _NativeSocket.bind(address, port, backlog, v6Only, shared)
         .then((socket) => new _RawServerSocket(socket, v6Only));
@@ -1762,8 +1771,7 @@
 
   static Future<RawDatagramSocket> bind(
       host, int port, bool reuseAddress) {
-    if (port < 0 || port > 0xffff)
-      throw new ArgumentError("Invalid port $port");
+    _throwOnBadPort(port);
     return _NativeSocket.bindDatagram(host, port, reuseAddress)
         .then((socket) => new _RawDatagramSocket(socket));
   }
diff --git a/runtime/bin/zlib/BUILD.gn b/runtime/bin/zlib/BUILD.gn
new file mode 100644
index 0000000..ad78238
--- /dev/null
+++ b/runtime/bin/zlib/BUILD.gn
@@ -0,0 +1,56 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+config("zlib_config") {
+  include_dirs = [ "//third_party/zlib" ]
+}
+
+static_library("zlib") {
+  if (!is_win) {
+    # Don't stomp on "libzlib" on other platforms.
+    output_name = "chrome_zlib"
+  }
+
+  zlib_path = "//third_party/zlib"
+  sources = [
+    "$zlib_path/adler32.c",
+    "$zlib_path/compress.c",
+    "$zlib_path/crc32.c",
+    "$zlib_path/crc32.h",
+    "$zlib_path/deflate.c",
+    "$zlib_path/deflate.h",
+    "$zlib_path/gzclose.c",
+    "$zlib_path/gzguts.h",
+    "$zlib_path/gzlib.c",
+    "$zlib_path/gzread.c",
+    "$zlib_path/gzwrite.c",
+    "$zlib_path/infback.c",
+    "$zlib_path/inffast.c",
+    "$zlib_path/inffast.h",
+    "$zlib_path/inffixed.h",
+    "$zlib_path/inflate.c",
+    "$zlib_path/inflate.h",
+    "$zlib_path/inftrees.c",
+    "$zlib_path/inftrees.h",
+    "$zlib_path/mozzconf.h",
+    "$zlib_path/trees.c",
+    "$zlib_path/trees.h",
+    "$zlib_path/uncompr.c",
+    "$zlib_path/zconf.h",
+    "$zlib_path/zlib.h",
+    "$zlib_path/zutil.c",
+    "$zlib_path/zutil.h",
+  ]
+
+  configs -= [ "//build/config/compiler:chromium_code" ]
+  configs += [ "//build/config/compiler:no_chromium_code" ]
+
+  all_dependent_configs = [ ":zlib_config" ]
+
+  if (is_clang) {
+    cflags = [
+      "-Wno-shift-negative-value",
+    ]
+  }
+}
diff --git a/runtime/include/dart_native_api.h b/runtime/include/dart_native_api.h
index 7dce495..74237c1 100644
--- a/runtime/include/dart_native_api.h
+++ b/runtime/include/dart_native_api.h
@@ -170,4 +170,10 @@
  */
 DART_EXPORT Dart_Handle Dart_CompileAll();
 
+/**
+ * Parses all loaded functions in the current isolate..
+ *
+ */
+DART_EXPORT Dart_Handle Dart_ParseAll();
+
 #endif  /* INCLUDE_DART_NATIVE_API_H_ */  /* NOLINT */
diff --git a/runtime/observatory/.packages b/runtime/observatory/.packages
new file mode 100644
index 0000000..4730e62
--- /dev/null
+++ b/runtime/observatory/.packages
@@ -0,0 +1,43 @@
+# Generated by pub on 2016-09-23 00:19:32.016148.
+analyzer:../../third_party/observatory_pub_packages/packages/analyzer/lib/
+args:../../third_party/observatory_pub_packages/packages/args/lib/
+async:../../third_party/observatory_pub_packages/packages/async/lib/
+barback:../../third_party/observatory_pub_packages/packages/barback/lib/
+browser:../../third_party/observatory_pub_packages/packages/browser/lib/
+charcode:../../third_party/observatory_pub_packages/packages/charcode/lib/
+charted:../../third_party/observatory_pub_packages/packages/charted/lib/
+cli_util:../../third_party/observatory_pub_packages/packages/cli_util/lib/
+code_transformers:../../third_party/observatory_pub_packages/packages/code_transformers/lib/
+collection:../../third_party/observatory_pub_packages/packages/collection/lib/
+csslib:../../third_party/observatory_pub_packages/packages/csslib/lib/
+dart_style:../../third_party/observatory_pub_packages/packages/dart_style/lib/
+dart_to_js_script_rewriter:../../third_party/observatory_pub_packages/packages/dart_to_js_script_rewriter/lib/
+glob:../../third_party/observatory_pub_packages/packages/glob/lib/
+html:../../third_party/observatory_pub_packages/packages/html/lib/
+initialize:../../third_party/observatory_pub_packages/packages/initialize/lib/
+intl:../../third_party/observatory_pub_packages/packages/intl/lib/
+logging:../../third_party/observatory_pub_packages/packages/logging/lib/
+matcher:../../third_party/observatory_pub_packages/packages/matcher/lib/
+observe:../../third_party/observatory_pub_packages/packages/observe/lib/
+package_config:../../third_party/observatory_pub_packages/packages/package_config/lib/
+path:../../third_party/observatory_pub_packages/packages/path/lib/
+petitparser:../../third_party/observatory_pub_packages/packages/petitparser/lib/
+plugin:../../third_party/observatory_pub_packages/packages/plugin/lib/
+pool:../../third_party/observatory_pub_packages/packages/pool/lib/
+quiver:../../third_party/observatory_pub_packages/packages/quiver/lib/
+quiver_iterables:../../third_party/observatory_pub_packages/packages/quiver_iterables/lib/
+smoke:../../third_party/observatory_pub_packages/packages/smoke/lib/
+source_maps:../../third_party/observatory_pub_packages/packages/source_maps/lib/
+source_span:../../third_party/observatory_pub_packages/packages/source_span/lib/
+stack_trace:../../third_party/observatory_pub_packages/packages/stack_trace/lib/
+string_scanner:../../third_party/observatory_pub_packages/packages/string_scanner/lib/
+template_binding:../../third_party/observatory_pub_packages/packages/template_binding/lib/
+unittest:../../third_party/observatory_pub_packages/packages/unittest/lib/
+usage:../../third_party/observatory_pub_packages/packages/usage/lib/
+utf:../../third_party/observatory_pub_packages/packages/utf/lib/
+watcher:../../third_party/observatory_pub_packages/packages/watcher/lib/
+web_components:../../third_party/observatory_pub_packages/packages/web_components/lib/
+when:../../third_party/observatory_pub_packages/packages/when/lib/
+which:../../third_party/observatory_pub_packages/packages/which/lib/
+yaml:../../third_party/observatory_pub_packages/packages/yaml/lib/
+observatory:lib/
diff --git a/runtime/observatory/BUILD.gn b/runtime/observatory/BUILD.gn
index 3943253..a476414 100644
--- a/runtime/observatory/BUILD.gn
+++ b/runtime/observatory/BUILD.gn
@@ -41,23 +41,24 @@
     rebase_path("pubspec.yaml"),
   ]
 
+  current_dir = rebase_path(".", "//")
   args = [
     "--silent=True",
     "--pub-executable",
     dart_host_pub_exe,
     "--directory",
-    rebase_path("$root_gen_dir/observatory_copy/dart/runtime/observatory/"),
+    rebase_path("$root_gen_dir/observatory_copy/$current_dir/"),
     "--command",
     "rewrite",
     rebase_path("../observatory/pubspec.yaml"),
     rebase_path(
-        "$root_gen_dir/observatory_copy/dart/runtime/observatory/pubspec.yaml"),
+        "$root_gen_dir/observatory_copy/$current_dir/pubspec.yaml"),
     "../../third_party/",
     rebase_path("../../third_party/"),
   ]
 
   outputs = [
-    "$root_gen_dir/observatory_copy/dart/runtime/observatory/pubspec.yaml",
+    "$root_gen_dir/observatory_copy/$current_dir/pubspec.yaml",
   ]
 }
 
@@ -68,9 +69,10 @@
 
   script = "../../tools/observatory_tool.py"
 
+  current_dir = rebase_path(".", "//")
   inputs = [
     script,
-    "$root_gen_dir/observatory_copy/dart/runtime/observatory/pubspec.yaml",
+    "$root_gen_dir/observatory_copy/$current_dir/pubspec.yaml",
   ]
 
   args = [
@@ -78,23 +80,24 @@
     "--pub-executable",
     dart_host_pub_exe,
     "--stamp",
-    rebase_path("$root_gen_dir/observatory_copy/dart/runtime/observatory/packages.stamp"),
+    rebase_path("$root_gen_dir/observatory_copy/$current_dir/packages.stamp"),
     "--directory",
-    rebase_path("$root_gen_dir/observatory_copy/dart/runtime/observatory/"),
+    rebase_path("$root_gen_dir/observatory_copy/$current_dir/"),
     "--command",
     "get",
   ]
 
   outputs = [
-    "$root_gen_dir/observatory_copy/dart/runtime/observatory/packages.stamp",
+    "$root_gen_dir/observatory_copy/$current_dir/packages.stamp",
   ]
 }
 
 action("pub_build_observatory") {
+  current_dir = rebase_path(".", "//")
   sources =
       rebase_path(observatory_sources_gypi.sources,
                   "",
-                  "$root_gen_dir/observatory_copy/dart/runtime/observatory")
+                  "$root_gen_dir/observatory_copy/$current_dir")
 
   deps = [
     ":copy_observatory",
@@ -105,7 +108,7 @@
 
   inputs = [
     script,
-    "$root_gen_dir/observatory_copy/dart/runtime/observatory/packages.stamp",
+    "$root_gen_dir/observatory_copy/$current_dir/packages.stamp",
   ]
   inputs += sources
 
@@ -114,7 +117,7 @@
     "--pub-executable",
     dart_host_pub_exe,
     "--directory",
-    rebase_path("$root_gen_dir/observatory_copy/dart/runtime/observatory/"),
+    rebase_path("$root_gen_dir/observatory_copy/$current_dir/"),
     "--command",
     "build",
     rebase_path("$root_out_dir/observatory/build"),
@@ -152,41 +155,70 @@
   ]
 }
 
-action("archive_observatory") {
-  deps = [
-    ":deploy_observatory",
-  ]
+template("observatory_archive") {
+  assert(defined(invoker.inner_namespace),
+         "Need inner_namespace in $target_name")
+  assert(defined(invoker.outer_namespace),
+         "Need outer_namespace in $target_name")
+  action(target_name) {
+    deps = [
+      ":deploy_observatory",
+    ]
 
-  script = "../tools/create_archive.py"
+    script = "../tools/create_archive.py"
 
   inputs = [
     script,
     "$root_out_dir/observatory/deployed/web/main.dart.js",
   ]
 
-  args = [
-    "--output",
-    rebase_path("$root_gen_dir/observatory/observatory_archive.cc"),
-    "--tar_output",
-    rebase_path("$root_gen_dir/observatory/observatory_archive.tar"),
-    "--outer_namespace", "dart",
-    "--inner_namespace", "observatory",
-    "--name", "observatory_assets_archive",
-    "--client_root", rebase_path("$root_out_dir/observatory/deployed/web/"),
-  ]
+    inner_namespace = invoker.inner_namespace
+    outer_namespace = invoker.outer_namespace
+    output_name = target_name
+    args = [
+      "--output",
+      rebase_path("$root_gen_dir/observatory/${output_name}.cc"),
+      "--tar_output",
+      rebase_path("$root_gen_dir/observatory/${output_name}.tar"),
+      "--outer_namespace", outer_namespace,
+      "--inner_namespace", inner_namespace,
+      "--name", "observatory_assets_archive",
+      "--client_root", rebase_path("$root_out_dir/observatory/deployed/web/"),
+    ]
 
-  outputs = [
-    "$root_gen_dir/observatory/observatory_archive.cc",
-    "$root_gen_dir/observatory/observatory_archive.tar",
-  ]
+    outputs = [
+      "$root_gen_dir/observatory/${output_name}.cc",
+      "$root_gen_dir/observatory/${output_name}.tar",
+    ]
+  }
+}
+
+observatory_archive("embedded_archive_observatory") {
+  outer_namespace = "dart"
+  inner_namespace = "observatory"
 }
 
 source_set("embedded_observatory_archive") {
   deps = [
-    ":archive_observatory",
+    ":embedded_archive_observatory",
   ]
 
   sources = [
-    rebase_path("$root_gen_dir/observatory/observatory_archive.cc"),
+    rebase_path("$root_gen_dir/observatory/embedded_archive_observatory.cc"),
+  ]
+}
+
+observatory_archive("standalone_archive_observatory") {
+  outer_namespace = "dart"
+  inner_namespace = "bin"
+}
+
+source_set("standalone_observatory_archive") {
+  deps = [
+    ":standalone_archive_observatory",
+  ]
+
+  sources = [
+    rebase_path("$root_gen_dir/observatory/standalone_archive_observatory.cc"),
   ]
 }
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index 51ac8eb..85d9385 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -2256,7 +2256,8 @@
   final classes = <Class>[];
   final variables = <Field>[];
   final functions = <ServiceFunction>[];
-
+  bool _debuggable;
+  bool get debuggable => _debuggable;
   bool get immutable => false;
 
   bool isDart(String libraryName) {
@@ -2284,6 +2285,7 @@
       return;
     }
     _loaded = true;
+    _debuggable = map['debuggable'];
     dependencies.clear();
     dependencies.addAll(map["dependencies"].map(LibraryDependency._fromMap));
     scripts.clear();
diff --git a/runtime/observatory/observatory.gypi b/runtime/observatory/observatory.gypi
index ed241c5..be393ca 100644
--- a/runtime/observatory/observatory.gypi
+++ b/runtime/observatory/observatory.gypi
@@ -8,42 +8,10 @@
   },
   'targets': [
     {
-      'target_name': 'fetch_observatory_deps',
-      'type': 'none',
-      'dependencies': [
-        'dart_bootstrap#host',
-      ],
-      'toolsets': ['host'],
-      'actions': [
-        {
-          'action_name': 'get_obsevatory_dependencies',
-          'inputs': [
-            '../../tools/observatory_tool.py',
-            'pubspec.yaml',
-          ],
-          'outputs': [
-            '<(gen_source_dir)/observatory_packages.stamp'
-          ],
-          'action': [
-            'python',
-            '../tools/observatory_tool.py',
-            '--sdk=True',
-            '--stamp',
-            '<(gen_source_dir)/observatory_packages.stamp',
-            '--dart-executable',
-            '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)dart_bootstrap<(EXECUTABLE_SUFFIX)',
-            '--directory', 'observatory',
-            '--command', 'get',
-          ],
-        }
-      ],
-    },
-    {
       'target_name': 'build_observatory',
       'type': 'none',
       'dependencies': [
         'dart_bootstrap#host',
-        'fetch_observatory_deps#host',
       ],
       'toolsets': ['host'],
       'includes': [
@@ -54,7 +22,6 @@
           'action_name': 'pub_build_observatory',
           'inputs': [
             '../../tools/observatory_tool.py',
-            '<(gen_source_dir)/observatory_packages.stamp',
             '<@(_sources)',
           ],
           'outputs': [
diff --git a/runtime/observatory/tests/observatory_ui/observatory_ui.status b/runtime/observatory/tests/observatory_ui/observatory_ui.status
index f2ade5c..f683fd8 100644
--- a/runtime/observatory/tests/observatory_ui/observatory_ui.status
+++ b/runtime/observatory/tests/observatory_ui/observatory_ui.status
@@ -5,9 +5,6 @@
 [ $browser == false || $runtime == drt || $fast_startup]
 *: SkipByDesign
 
-[ $runtime == dartium || $runtime == chrome || $runtime == ff ]
-vm_connect/element_test: Skip # Times out. Issue 27397
-
 [ $runtime == dartium ]
 isolate/*: Skip
 allocation_profile: Skip
diff --git a/runtime/observatory/tests/service/issue_27238_test.dart b/runtime/observatory/tests/service/issue_27238_test.dart
new file mode 100644
index 0000000..052b107
--- /dev/null
+++ b/runtime/observatory/tests/service/issue_27238_test.dart
@@ -0,0 +1,46 @@
+// 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=--error_on_bad_type --error_on_bad_override  --verbose_debug
+
+import 'package:observatory/service_io.dart';
+import 'service_test_common.dart';
+import 'dart:async';
+import 'test_helper.dart';
+import 'dart:developer';
+
+const int LINE_A = 20;
+const int LINE_B = 23;
+const int LINE_C = 24;
+const int LINE_D = 26;
+const int LINE_E = 27;
+
+testMain() async {
+  debugger();
+  Future future1 = new Future.value();  // LINE_A.
+  Future future2 = new Future.value();
+
+  await future1;  // LINE_B.
+  await future2;  // LINE_C.
+
+  print('foo1'); // LINE_D.
+  print('foo2'); // LINE_E.
+}
+
+var tests = [
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  smartNext,
+  hasStoppedAtBreakpoint,
+  smartNext,
+  stoppedAtLine(LINE_B),
+  smartNext,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_C),
+  smartNext,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_D),
+  resumeIsolate,
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory/tests/service/issue_27287_test.dart b/runtime/observatory/tests/service/issue_27287_test.dart
new file mode 100644
index 0000000..58633b33
--- /dev/null
+++ b/runtime/observatory/tests/service/issue_27287_test.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2016, 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=--error_on_bad_type --error_on_bad_override  --verbose_debug
+
+import 'package:observatory/service_io.dart';
+import 'service_test_common.dart';
+import 'dart:async';
+import 'test_helper.dart';
+import 'dart:developer';
+
+const int LINE_A = 19;
+const int LINE_B = 20;
+
+var libVariable;
+
+testMain() {
+  debugger();
+  print("Before");  // LINE_A
+  libVariable = 0;  // LINE_B
+  print("and after");
+}
+
+var tests = [
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  stepOver,
+  // Check that debugger stops at assignment to top-level variable.
+  stoppedAtLine(LINE_B),
+  resumeIsolate,
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory/tests/service/service.status b/runtime/observatory/tests/service/service.status
index 1e49905..e3cc4de 100644
--- a/runtime/observatory/tests/service/service.status
+++ b/runtime/observatory/tests/service/service.status
@@ -7,6 +7,7 @@
 gc_test: Pass, RuntimeError # Issue 26490
 pause_on_start_and_exit_test: Pass, RuntimeError # Issue 26470
 pause_on_start_then_step_test: Pass, RuntimeError # Issue 26470
+debugger_location_test: Skip # Issue 27434
 
 [ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) ]
 evaluate_activation_test/instance: RuntimeError # http://dartbug.com/20047
diff --git a/runtime/observatory/tests/service/service_test_common.dart b/runtime/observatory/tests/service/service_test_common.dart
index 4b3dc36..935d426 100644
--- a/runtime/observatory/tests/service/service_test_common.dart
+++ b/runtime/observatory/tests/service/service_test_common.dart
@@ -28,6 +28,43 @@
   streamSubscriptions.remove(streamName);
 }
 
+Future smartNext(Isolate isolate) async {
+  print('smartNext');
+  if (isolate.status == M.IsolateStatus.paused) {
+    var event = isolate.pauseEvent;
+    if (event.atAsyncSuspension) {
+      return asyncNext(isolate);
+    } else {
+      return syncNext(isolate);
+    }
+  } else {
+    throw 'The program is already running';
+  }
+}
+
+Future asyncNext(Isolate isolate) async {
+  print('asyncNext');
+  if (isolate.status == M.IsolateStatus.paused) {
+    var event = isolate.pauseEvent;
+    if (!event.atAsyncSuspension) {
+      throw 'No async continuation at this location';
+    } else {
+      return isolate.stepOverAsyncSuspension();
+    }
+  } else {
+    throw 'The program is already running';
+  }
+}
+
+Future syncNext(Isolate isolate) async {
+  print('syncNext');
+  if (isolate.status == M.IsolateStatus.paused) {
+    return isolate.stepOver();
+  } else {
+    throw 'The program is already running';
+  }
+}
+
 Future asyncStepOver(Isolate isolate) async {
   final Completer pausedAtSyntheticBreakpoint = new Completer();
   StreamSubscription subscription;
@@ -191,13 +228,50 @@
     Script script = await top.location.script.load();
     int actualLine = script.tokenToLine(top.location.tokenPos);
     if (actualLine != line) {
-      var sb = new StringBuffer();
+      StringBuffer sb = new StringBuffer();
       sb.write("Expected to be at line $line but actually at line $actualLine");
       sb.write("\nFull stack trace:\n");
       for (Frame f in stack['frames']) {
         sb.write(" $f [${await f.location.getLine()}]\n");
       }
       throw sb.toString();
+    } else {
+      print('Program is stopped at line: $line');
+    }
+  };
+}
+
+
+IsolateTest stoppedInFunction(String functionName, {bool contains: false}) {
+  return (Isolate isolate) async {
+    print("Checking we are in function: $functionName");
+
+    ServiceMap stack = await isolate.getStack();
+    expect(stack.type, equals('Stack'));
+
+    List<Frame> frames = stack['frames'];
+    expect(frames.length, greaterThanOrEqualTo(1));
+
+    Frame topFrame = stack['frames'][0];
+    ServiceFunction function = await topFrame.function.load();
+    final bool matches =
+        contains ? function.name.contains(functionName) :
+                     function.name == functionName;
+    if (!matches) {
+      StringBuffer sb = new StringBuffer();
+      sb.write("Expected to be in function $functionName but "
+               "actually in function ${function.name}");
+      sb.write("\nFull stack trace:\n");
+      for (Frame f in stack['frames']) {
+        await f.function.load();
+        await (f.function.dartOwner as ServiceObject).load();
+        String name = f.function.name;
+        String ownerName = (f.function.dartOwner as ServiceObject).name;
+        sb.write(" $f [$name] [$ownerName]\n");
+      }
+      throw sb.toString();
+    } else {
+      print('Program is stopped in function: $functionName');
     }
   };
 }
@@ -253,6 +327,12 @@
   return hasStoppedAtBreakpoint(isolate);
 }
 
+Future<Isolate> stepOut(Isolate isolate) async {
+  await isolate.stepOut();
+  return hasStoppedAtBreakpoint(isolate);
+}
+
+
 Future<Class> getClassFromRootLib(Isolate isolate, String className) async {
   Library rootLib = await isolate.rootLibrary.load();
   for (var i = 0; i < rootLib.classes.length; i++) {
diff --git a/runtime/observatory/tests/service/set_library_debuggable_rpc_test.dart b/runtime/observatory/tests/service/set_library_debuggable_rpc_test.dart
index fe51ff7..0571376 100644
--- a/runtime/observatory/tests/service/set_library_debuggable_rpc_test.dart
+++ b/runtime/observatory/tests/service/set_library_debuggable_rpc_test.dart
@@ -57,6 +57,29 @@
     }
     expect(caughtException, isTrue);
   },
+
+  // illegal (dart:_*) library.
+  (Isolate isolate) async {
+    await isolate.load();
+    Library dartInternal = isolate.libraries.firstWhere(
+      (Library library) => library.uri == 'dart:_internal');
+    var params = {
+      'libraryId': dartInternal.id,
+      'isDebuggable': false,
+    };
+    bool caughtException;
+    try {
+      await isolate.invokeRpcNoUpgrade('setLibraryDebuggable', params);
+      expect(false, isTrue, reason:'Unreachable');
+    } on ServerRpcException catch(e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kInvalidParams));
+      expect(e.message,
+             "setLibraryDebuggable: "
+             "illegal 'libraryId' parameter: ${dartInternal.id}");
+    }
+    expect(caughtException, isTrue);
+  },
 ];
 
 main(args) async => runIsolateTests(args, tests);
diff --git a/runtime/observatory/tests/service/set_library_debuggable_test.dart b/runtime/observatory/tests/service/set_library_debuggable_test.dart
new file mode 100644
index 0000000..d76569c
--- /dev/null
+++ b/runtime/observatory/tests/service/set_library_debuggable_test.dart
@@ -0,0 +1,65 @@
+// Copyright (c) 2016, 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=--error_on_bad_type --error_on_bad_override
+
+library set_library_debuggable_test;
+
+import 'dart:developer';
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const LINE_A = 20;
+const LINE_B = 21;
+const LINE_C = 22;
+
+testMain() async {
+  debugger();
+  print('hi');   // LINE_A.
+  print('yep');  // LINE_B.
+  print('zoo');  // LINE_C.
+}
+
+var tests = [
+  (Isolate isolate) async {
+    await isolate.reload();
+    Library dartCore = isolate.libraries.firstWhere(
+      (Library library) => library.uri == 'dart:core');
+    await dartCore.load();
+    expect(dartCore.debuggable, equals(true));
+  },
+  stoppedInFunction('testMain', contains:true),
+  stoppedAtLine(LINE_A),
+  stepInto,
+  stoppedInFunction('print'),
+  stepOut,
+  stoppedInFunction('testMain', contains:true),
+  stoppedAtLine(LINE_B),
+  (Isolate isolate) async {
+    // Mark 'dart:core' as not debuggable.
+    await isolate.reload();
+    Library dartCore = isolate.libraries.firstWhere(
+      (Library library) => library.uri == 'dart:core');
+    await dartCore.load();
+    expect(dartCore.debuggable, equals(true));
+    var setDebugParams = {
+      'libraryId': dartCore.id,
+      'isDebuggable': false,
+    };
+    Map<String, dynamic> result =
+        await isolate.invokeRpcNoUpgrade('setLibraryDebuggable',
+                                         setDebugParams);
+    expect(result['type'], equals('Success'));
+    await dartCore.reload();
+    expect(dartCore.debuggable, equals(false));
+  },
+  stoppedInFunction('testMain', contains:true),
+  stoppedAtLine(LINE_B),
+  stepInto,
+  stoppedInFunction('testMain', contains:true),
+  stoppedAtLine(LINE_C),
+];
+
+main(args) async => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory/tests/service/step_over_await_test.dart b/runtime/observatory/tests/service/step_over_await_test.dart
index 5b5f4ed..1bbb3b7 100644
--- a/runtime/observatory/tests/service/step_over_await_test.dart
+++ b/runtime/observatory/tests/service/step_over_await_test.dart
@@ -13,164 +13,33 @@
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
 
-const int LINE_A = 25;
-const int LINE_B = 27;
-const int LINE_C = 29;
-const int LINE_D = 30;
+const int LINE_A = 22;
+const int LINE_B = 24;
 
-// This tests the low level synthetic breakpoint added / paused / removed
-// machinery triggered by the step OverAwait command.
-asyncWithoutAwait() async {
+// This tests the asyncStepOver command.
+asyncFunction() async {
   debugger();
   print('a');  // LINE_A
   await new Future.delayed(new Duration(seconds: 2));
   print('b');  // LINE_B
-  debugger();  // LINE_C
-  debugger();  // LINE_D
 }
 
 testMain() {
-  asyncWithoutAwait();
+  asyncFunction();
 }
 
-Breakpoint syntheticBreakpoint;
-
-Future<Isolate> testLowLevelAwaitOver(
-    Isolate isolate) {
-  assert(M.isAtAsyncSuspension(isolate.pauseEvent));
-
-  int state = 0;
-  bool firstResume = true;
-  handleBreakpointAdded(ServiceEvent event) {
-    expect(syntheticBreakpoint, isNull);
-    expect(state, 0);
-    if (!event.breakpoint.isSyntheticAsyncContinuation) {
-      // Not a synthetic async breakpoint.
-      return;
-    }
-    if (event.owner != isolate) {
-      // Wrong isolate.
-      return;
-    }
-    syntheticBreakpoint = event.breakpoint;
-    print('!!!! Synthetic async breakpoint added ${syntheticBreakpoint}');
-    state = 1;
-  }
-
-  handleResume(ServiceEvent event) {
-    if (firstResume) {
-      expect(state, 1);
-      if (event.owner != isolate) {
-        // Wrong isolate.
-        return;
-      }
-      print('!!!! Got first resume.');
-      state = 2;
-      firstResume = false;
-    } else {
-      expect(state, 3);
-      if (event.owner != isolate) {
-        // Wrong isolate.
-        return;
-      }
-      print('!!!! Got second resume.');
-      state = 4;
-    }
-
-  }
-
-  handlePauseBreakpoint(ServiceEvent event) {
-    expect(syntheticBreakpoint, isNotNull);
-    expect(state, 2);
-    if (!event.breakpoint.isSyntheticAsyncContinuation) {
-      // Not a synthetic async breakpoint.
-      return;
-    }
-    if (event.owner != isolate) {
-      // Wrong isolate.
-      return;
-    }
-    expect(event.breakpoint, equals(syntheticBreakpoint));
-    print('!!!! Paused at synthetic async breakpoint ${syntheticBreakpoint}');
-    state = 3;
-  }
-
-  handleBreakpointRemoved(ServiceEvent event) {
-    expect(syntheticBreakpoint, isNotNull);
-    expect(state, 4);
-    if (!event.breakpoint.isSyntheticAsyncContinuation) {
-      // Not a synthetic async breakpoint.
-      return;
-    }
-    if (event.owner != isolate) {
-      // Wrong isolate.
-      return;
-    }
-    expect(event.breakpoint, equals(syntheticBreakpoint));
-    print('!!!! Synthetic async breakpoint removed ${syntheticBreakpoint}');
-    state = 5;
-    syntheticBreakpoint = null;
-  }
-
-  // Set up a listener to wait for debugger events.
-  Completer completer = new Completer();
-  isolate.vm.getEventStream(VM.kDebugStream).then((stream) {
-    var subscription;
-    subscription = stream.listen((ServiceEvent event) async {
-      if (event.kind == ServiceEvent.kBreakpointAdded) {
-        handleBreakpointAdded(event);
-        expect(state, 1);
-      } else if (event.kind == ServiceEvent.kResume) {
-        if (firstResume) {
-          handleResume(event);
-          expect(state, 2);
-        } else {
-          handleResume(event);
-          expect(state, 4);
-        }
-      } else if (event.kind == ServiceEvent.kPauseBreakpoint) {
-        handlePauseBreakpoint(event);
-        expect(state, 3);
-        // Check that we are paused after the await statement.
-        await (stoppedAtLine(LINE_B)(isolate));
-        // Resume the isolate so that we trigger the breakpoint removal.
-        print('!!!! Triggering synthetic breakpoint removal.');
-        isolate.resume();
-      } else if (event.kind == ServiceEvent.kBreakpointRemoved) {
-        handleBreakpointRemoved(event);
-        expect(state, 5);
-        subscription.cancel();
-        if (completer != null) {
-          // Reload to update isolate.pauseEvent.
-          completer.complete(isolate.reload());
-          completer = null;
-        }
-      }
-    });
-  });
-
-  isolate.stepOverAsyncSuspension();
-
-  return completer.future;  // Will complete when breakpoint added.
-}
-
-
 var tests = [
   hasStoppedAtBreakpoint,
   stoppedAtLine(LINE_A),
-  stepOver,
-  stepOver,
-  stepOver,
+  stepOver,  // At new Duration().
+  stepOver,  // At new Future.delayed().
+  stepOver,  // At async.
+  // Check that we are at the async statement
   (Isolate isolate) async {
     expect(M.isAtAsyncSuspension(isolate.pauseEvent), isTrue);
-    expect(syntheticBreakpoint, isNull);
   },
-  testLowLevelAwaitOver,
-  hasStoppedAtBreakpoint,
-  stoppedAtLine(LINE_C),
-  resumeIsolate,
-  hasStoppedAtBreakpoint,
-  stoppedAtLine(LINE_D),
+  asyncStepOver,
+  stoppedAtLine(LINE_B),
   resumeIsolate,
 ];
 
diff --git a/runtime/vm/BUILD.gn b/runtime/vm/BUILD.gn
index 5f0a1ba..225afdf 100644
--- a/runtime/vm/BUILD.gn
+++ b/runtime/vm/BUILD.gn
@@ -25,7 +25,8 @@
 
 
 static_library("libdart_platform") {
-  configs += ["..:dart_config", "..:dart_product_config"]
+  configs += ["..:dart_config",
+              "..:dart_maybe_product_config"]
   public_configs = [":libdart_vm_config"]
 
   platform_headers_gypi =
@@ -59,7 +60,20 @@
 
 static_library("libdart_vm") {
   configs += ["..:dart_config",
-              "..:dart_product_config",
+              "..:dart_maybe_product_config",
+              "..:dart_maybe_precompiled_runtime_config"]
+  public_configs = [":libdart_vm_config"]
+  set_sources_assignment_filter(["*_test.cc", "*_test.h"])
+  sources = vm_sources_list.sources
+  include_dirs = [
+    "..",
+  ]
+}
+
+
+static_library("libdart_vm_precompiled_runtime") {
+  configs += ["..:dart_config",
+              "..:dart_maybe_product_config",
               "..:dart_precompiled_runtime_config"]
   public_configs = [":libdart_vm_config"]
   set_sources_assignment_filter(["*_test.cc", "*_test.h"])
@@ -72,10 +86,24 @@
 
 static_library("libdart_vm_nosnapshot") {
   configs += ["..:dart_config",
-              "..:dart_product_config",
-              "..:dart_precompiled_runtime_config"]
+              "..:dart_maybe_product_config",
+              "..:dart_maybe_precompiled_runtime_config",
+              "..:dart_no_snapshot_config",]
   public_configs = [":libdart_vm_config"]
-  defines = [ "DART_NO_SNAPSHOT" ]
+  set_sources_assignment_filter(["*_test.cc", "*_test.h"])
+  sources = vm_sources_list.sources
+  include_dirs = [
+    "..",
+  ]
+}
+
+
+static_library("libdart_vm_nosnapshot_precompiled_runtime") {
+  configs += ["..:dart_config",
+              "..:dart_maybe_product_config",
+              "..:dart_precompiled_runtime_config",
+              "..:dart_no_snapshot_config",]
+  public_configs = [":libdart_vm_config"]
   set_sources_assignment_filter(["*_test.cc", "*_test.h"])
   sources = vm_sources_list.sources
   include_dirs = [
@@ -86,10 +114,10 @@
 
 static_library("libdart_vm_nosnapshot_with_precompiler") {
   configs += ["..:dart_config",
-              "..:dart_product_config",
-              "..:dart_precompiler_config"]
+              "..:dart_maybe_product_config",
+              "..:dart_precompiler_config",
+              "..:dart_no_snapshot_config",]
   public_configs = [":libdart_vm_config"]
-  defines = [ "DART_NO_SNAPSHOT" ]
   set_sources_assignment_filter(["*_test.cc", "*_test.h"])
   sources = vm_sources_list.sources
   include_dirs = [
@@ -190,7 +218,17 @@
 
   static_library("libdart_lib_nosnapshot") {
     configs += ["..:dart_config",
-                "..:dart_product_config",
+                "..:dart_maybe_product_config",
+                "..:dart_maybe_precompiled_runtime_config"]
+    deps = libdeps
+    sources = libsources + ["bootstrap.cc"] + liboutputs
+    include_dirs = [
+      "..",
+    ]
+  }
+  static_library("libdart_lib_nosnapshot_precompiled_runtime") {
+    configs += ["..:dart_config",
+                "..:dart_maybe_product_config",
                 "..:dart_precompiled_runtime_config"]
     deps = libdeps
     sources = libsources + ["bootstrap.cc"] + liboutputs
@@ -200,7 +238,7 @@
   }
   static_library("libdart_lib_nosnapshot_with_precompiler") {
     configs += ["..:dart_config",
-                "..:dart_product_config",
+                "..:dart_maybe_product_config",
                 "..:dart_precompiler_config" ]
     deps = libdeps
     sources = libsources + [ "bootstrap.cc"] + liboutputs
@@ -210,7 +248,16 @@
   }
   static_library("libdart_lib") {
     configs += ["..:dart_config",
-                "..:dart_product_config",
+                "..:dart_maybe_product_config",
+                "..:dart_maybe_precompiled_runtime_config"]
+    sources = libsources + [ "bootstrap_nocore.cc"]
+    include_dirs = [
+      "..",
+    ]
+  }
+  static_library("libdart_lib_precompiled_runtime") {
+    configs += ["..:dart_config",
+                "..:dart_maybe_product_config",
                 "..:dart_precompiled_runtime_config"]
     sources = libsources + [ "bootstrap_nocore.cc"]
     include_dirs = [
diff --git a/runtime/vm/allocation.cc b/runtime/vm/allocation.cc
index b5f0f6c..6353cc8 100644
--- a/runtime/vm/allocation.cc
+++ b/runtime/vm/allocation.cc
@@ -26,7 +26,7 @@
 
 
 void* ZoneAllocated::operator new(uword size, Zone* zone) {
-  ASSERT(zone == Thread::Current()->zone());
+  ASSERT(Thread::Current()->ZoneIsOwnedByThread(zone));
   return Allocate(size, zone);
 }
 
diff --git a/runtime/vm/assembler_x64.cc b/runtime/vm/assembler_x64.cc
index 48e2613..213b8cb 100644
--- a/runtime/vm/assembler_x64.cc
+++ b/runtime/vm/assembler_x64.cc
@@ -3767,7 +3767,7 @@
 
 static const char* cpu_reg_names[kNumberOfCpuRegisters] = {
   "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
-  "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
+  "r8", "r9", "r10", "r11", "r12", "r13", "thr", "pp"
 };
 
 
diff --git a/runtime/vm/ast_printer.cc b/runtime/vm/ast_printer.cc
index eb5dd3b..6b47267 100644
--- a/runtime/vm/ast_printer.cc
+++ b/runtime/vm/ast_printer.cc
@@ -14,45 +14,47 @@
 
 namespace dart {
 
-AstPrinter::AstPrinter() : indent_(0) { }
+AstPrinter::AstPrinter(bool log)
+    : indent_(0),
+      logger_(log ? Log::Current() : Log::NoOpLog()) { }
 
 
 AstPrinter::~AstPrinter() { }
 
 
 void AstPrinter::VisitGenericAstNode(AstNode* node) {
-  THR_Print("(%s ", node->Name());
+  logger_->Print("(%s ", node->Name());
   node->VisitChildren(this);
-  THR_Print(")");
+  logger_->Print(")");
 }
 
 
 void AstPrinter::VisitSequenceNode(SequenceNode* node) {
   indent_++;
   LocalScope* scope = node->scope();
-  THR_Print("(%s (scope \"%p\"", node->Name(), scope);
+  logger_->Print("(%s (scope \"%p\"", node->Name(), scope);
   if (scope != NULL) {
-    THR_Print(" (%s-%s) loop %d",
+    logger_->Print(" (%s-%s) loop %d",
               scope->begin_token_pos().ToCString(),
               scope->end_token_pos().ToCString(),
               scope->loop_level());
     if (scope->HasContextLevel()) {
-      THR_Print(" context %d captures %d",
+      logger_->Print(" context %d captures %d",
                 scope->context_level(),
                 scope->num_context_variables());
     } else {
       ASSERT(scope->num_context_variables() == 0);
     }
   }
-  THR_Print(")");
+  logger_->Print(")");
   for (int i = 0; i < node->length(); ++i) {
-    THR_Print("\n");
+    logger_->Print("\n");
     for (intptr_t p = 0; p < indent_; p++) {
-      THR_Print("  ");
+      logger_->Print("  ");
     }
     node->NodeAt(i)->Visit(this);
   }
-  THR_Print(")");
+  logger_->Print(")");
   indent_--;
 }
 
@@ -83,29 +85,31 @@
       kind = "";
       UNREACHABLE();
   }
-  THR_Print("(%s %s", node->Name(), kind);
+  logger_->Print("(%s %s", node->Name(), kind);
   node->VisitChildren(this);
-  THR_Print(")");
+  logger_->Print(")");
 }
 
 
 void AstPrinter::VisitGenericLocalNode(AstNode* node,
                                        const LocalVariable& var) {
-  THR_Print("(%s %s%s \"%s\"",
+  logger_->Print("(%s %s%s \"%s\"",
             node->Name(),
             var.is_final() ? "final " : "",
             String::Handle(var.type().Name()).ToCString(),
             var.name().ToCString());
   if (var.HasIndex()) {
     if (var.is_captured()) {
-      THR_Print(" (context %d %d)", var.owner()->context_level(), var.index());
+      logger_->Print(" (context %d %d)",
+                     var.owner()->context_level(),
+                     var.index());
     } else {
-      THR_Print(" (stack %d)", var.index());
+      logger_->Print(" (stack %d)", var.index());
     }
   }
-  THR_Print(" ");
+  logger_->Print(" ");
   node->VisitChildren(this);
-  THR_Print(")");
+  logger_->Print(")");
 }
 
 
@@ -120,14 +124,14 @@
 
 
 void AstPrinter::VisitGenericFieldNode(AstNode* node, const Field& field) {
-  THR_Print("(%s %s%s \"%s\" ",
+  logger_->Print("(%s %s%s \"%s\" ",
             node->Name(),
             field.is_final() ? "final " : "",
             String::Handle(AbstractType::Handle(field.type()).Name()).
                 ToCString(),
             String::Handle(field.name()).ToCString());
   node->VisitChildren(this);
-  THR_Print(")");
+  logger_->Print(")");
 }
 
 
@@ -168,13 +172,13 @@
 
 void AstPrinter::VisitLiteralNode(LiteralNode* node) {
   const Instance& literal = node->literal();
-  THR_Print("(%s \"%s\")", node->Name(), literal.ToCString());
+  logger_->Print("(%s \"%s\")", node->Name(), literal.ToCString());
 }
 
 
 void AstPrinter::VisitTypeNode(TypeNode* node) {
   const AbstractType& type = node->type();
-  THR_Print("(%s \"%s\")",
+  logger_->Print("(%s \"%s\")",
             node->Name(),
             String::Handle(type.Name()).ToCString());
 }
@@ -183,24 +187,24 @@
 void AstPrinter::VisitAssignableNode(AssignableNode* node) {
   const AbstractType& type = node->type();
   const String& dst_name = node->dst_name();
-  THR_Print("(%s (type \"%s\") (of \"%s\") ",
+  logger_->Print("(%s (type \"%s\") (of \"%s\") ",
             node->Name(),
             String::Handle(type.Name()).ToCString(),
             dst_name.ToCString());
   node->VisitChildren(this);
-  THR_Print(")");
+  logger_->Print(")");
 }
 
 
 void AstPrinter::VisitAwaitNode(AwaitNode* node) {
-  THR_Print("(*****%s***** (scope \"%p\") ", node->Name(), node->scope());
+  logger_->Print("(*****%s***** (scope \"%p\") ", node->Name(), node->scope());
   node->VisitChildren(this);
-  THR_Print(")");
+  logger_->Print(")");
 }
 
 
 void AstPrinter::VisitAwaitMarkerNode(AwaitMarkerNode* node) {
-  THR_Print("(%s (async_scope \"%p\" await_scope \"%p\"))",
+  logger_->Print("(%s (async_scope \"%p\" await_scope \"%p\"))",
             node->Name(),
             node->async_scope(),
             node->await_scope());
@@ -208,30 +212,30 @@
 
 
 void AstPrinter::VisitPrimaryNode(PrimaryNode* node) {
-  THR_Print("(*****%s***** \"%s\")",
+  logger_->Print("(*****%s***** \"%s\")",
             node->Name(),
             node->primary().ToCString());
 }
 
 
 void AstPrinter::VisitComparisonNode(ComparisonNode* node) {
-  THR_Print("(%s %s ", node->Name(), node->TokenName());
+  logger_->Print("(%s %s ", node->Name(), node->TokenName());
   node->VisitChildren(this);
-  THR_Print(")");
+  logger_->Print(")");
 }
 
 
 void AstPrinter::VisitBinaryOpNode(BinaryOpNode* node) {
-  THR_Print("(%s %s ", node->Name(), node->TokenName());
+  logger_->Print("(%s %s ", node->Name(), node->TokenName());
   node->VisitChildren(this);
-  THR_Print(")");
+  logger_->Print(")");
 }
 
 
 void AstPrinter::VisitUnaryOpNode(UnaryOpNode* node) {
-  THR_Print("(%s %s ", node->Name(), node->TokenName());
+  logger_->Print("(%s %s ", node->Name(), node->TokenName());
   node->VisitChildren(this);
-  THR_Print(")");
+  logger_->Print(")");
 }
 
 
@@ -246,16 +250,16 @@
 
 
 void AstPrinter::VisitCaseNode(CaseNode* node) {
-  THR_Print("(%s (", node->Name());
+  logger_->Print("(%s (", node->Name());
   for (int i = 0; i < node->case_expressions()->length(); i++) {
     node->case_expressions()->NodeAt(i)->Visit(this);
   }
   if (node->contains_default()) {
-    THR_Print(" default");
+    logger_->Print(" default");
   }
-  THR_Print(")");
+  logger_->Print(")");
   node->statements()->Visit(this);
-  THR_Print(")");
+  logger_->Print(")");
 }
 
 
@@ -272,17 +276,17 @@
 void AstPrinter::VisitForNode(ForNode* node) {
   // Complicated because the condition is optional and so we clearly want to
   // indicate the subparts.
-  THR_Print("(%s (init ", node->Name());
+  logger_->Print("(%s (init ", node->Name());
   node->initializer()->Visit(this);
   if (node->condition() != NULL) {
-    THR_Print(") (cond ");
+    logger_->Print(") (cond ");
     node->condition()->Visit(this);
   }
-  THR_Print(") (update ");
+  logger_->Print(") (update ");
   node->increment()->Visit(this);
-  THR_Print(") ");
+  logger_->Print(") ");
   node->body()->Visit(this);
-  THR_Print(")");
+  logger_->Print(")");
 }
 
 
@@ -292,7 +296,7 @@
 
 
 void AstPrinter::VisitJumpNode(JumpNode* node) {
-  THR_Print("(%s %s %s (scope \"%p\"))",
+  logger_->Print("(%s %s %s (scope \"%p\"))",
             node->Name(),
             node->TokenName(),
             node->label()->name().ToCString(),
@@ -301,25 +305,25 @@
 
 
 void AstPrinter::VisitInstanceCallNode(InstanceCallNode* node) {
-  THR_Print("(%s \"%s\" ",
+  logger_->Print("(%s \"%s\" ",
             node->Name(),
             node->function_name().ToCString());
   node->VisitChildren(this);
-  THR_Print(")");
+  logger_->Print(")");
 }
 
 
 void AstPrinter::VisitStaticCallNode(StaticCallNode* node) {
   const char* function_fullname = node->function().ToFullyQualifiedCString();
-  THR_Print("(%s \"%s\" ", node->Name(), function_fullname);
+  logger_->Print("(%s \"%s\" ", node->Name(), function_fullname);
   node->VisitChildren(this);
-  THR_Print(")");
+  logger_->Print(")");
 }
 
 
 void AstPrinter::VisitClosureNode(ClosureNode* node) {
   const char* function_fullname = node->function().ToFullyQualifiedCString();
-  THR_Print("(%s \"%s\")", node->Name(), function_fullname);
+  logger_->Print("(%s \"%s\")", node->Name(), function_fullname);
 }
 
 
@@ -331,28 +335,28 @@
 void AstPrinter::VisitConstructorCallNode(ConstructorCallNode* node) {
   const char* kind = node->constructor().IsFactory() ? "factory " : "";
   const char* constructor_name = node->constructor().ToFullyQualifiedCString();
-  THR_Print("(%s %s \"%s\" ", node->Name(), kind, constructor_name);
+  logger_->Print("(%s %s \"%s\" ", node->Name(), kind, constructor_name);
   node->VisitChildren(this);
-  THR_Print(")");
+  logger_->Print(")");
 }
 
 
 void AstPrinter::VisitInstanceGetterNode(InstanceGetterNode* node) {
-  THR_Print("(%s \"%s\" ", node->Name(), node->field_name().ToCString());
+  logger_->Print("(%s \"%s\" ", node->Name(), node->field_name().ToCString());
   node->VisitChildren(this);
-  THR_Print(")");
+  logger_->Print(")");
 }
 
 
 void AstPrinter::VisitInstanceSetterNode(InstanceSetterNode* node) {
-  THR_Print("(%s \"%s\" ", node->Name(), node->field_name().ToCString());
+  logger_->Print("(%s \"%s\" ", node->Name(), node->field_name().ToCString());
   node->VisitChildren(this);
-  THR_Print(")");
+  logger_->Print(")");
 }
 
 
 void AstPrinter::VisitInitStaticFieldNode(InitStaticFieldNode* node) {
-  THR_Print("(%s \"%s\")",
+  logger_->Print("(%s \"%s\")",
             node->Name(),
             String::Handle(node->field().name()).ToCString());
 }
@@ -360,7 +364,7 @@
 
 void AstPrinter::VisitStaticGetterNode(StaticGetterNode* node) {
   String& class_name = String::Handle(node->cls().Name());
-  THR_Print("(%s \"%s.%s\")",
+  logger_->Print("(%s \"%s.%s\")",
             node->Name(),
             class_name.ToCString(),
             node->field_name().ToCString());
@@ -369,31 +373,31 @@
 
 void AstPrinter::VisitStaticSetterNode(StaticSetterNode* node) {
   String& class_name = String::Handle(node->cls().Name());
-  THR_Print("(%s \"%s.%s\" ",
+  logger_->Print("(%s \"%s.%s\" ",
             node->Name(),
             class_name.ToCString(),
             node->field_name().ToCString());
   node->VisitChildren(this);
-  THR_Print(")");
+  logger_->Print(")");
 }
 
 
 void AstPrinter::VisitLoadIndexedNode(LoadIndexedNode* node) {
-  THR_Print("(%s%s ", node->Name(), node->IsSuperLoad() ? " super" : "");
+  logger_->Print("(%s%s ", node->Name(), node->IsSuperLoad() ? " super" : "");
   node->VisitChildren(this);
-  THR_Print(")");
+  logger_->Print(")");
 }
 
 
 void AstPrinter::VisitStoreIndexedNode(StoreIndexedNode* node) {
-  THR_Print("(%s%s ", node->Name(), node->IsSuperStore() ? " super" : "");
+  logger_->Print("(%s%s ", node->Name(), node->IsSuperStore() ? " super" : "");
   node->VisitChildren(this);
-  THR_Print(")");
+  logger_->Print(")");
 }
 
 
 void AstPrinter::VisitNativeBodyNode(NativeBodyNode* node) {
-  THR_Print("(%s \"%s\" (%" Pd " args))",
+  logger_->Print("(%s \"%s\" (%" Pd " args))",
             node->Name(),
             node->native_c_function_name().ToCString(),
             NativeArguments::ParameterCountForResolution(node->function()));
@@ -406,15 +410,15 @@
 
 
 void AstPrinter::VisitTryCatchNode(TryCatchNode* node) {
-  THR_Print("(%s ", node->Name());
+  logger_->Print("(%s ", node->Name());
   node->try_block()->Visit(this);
   node->catch_block()->Visit(this);
   if (node->finally_block() != NULL) {
-    THR_Print("(finally ");
+    logger_->Print("(finally ");
     node->finally_block()->Visit(this);
-    THR_Print(")");
+    logger_->Print(")");
   }
-  THR_Print(")");
+  logger_->Print(")");
 }
 
 
@@ -424,7 +428,7 @@
 
 
 void AstPrinter::VisitStopNode(StopNode* node) {
-  THR_Print("(%s %s)", node->Name(), node->message());
+  logger_->Print("(%s %s)", node->Name(), node->message());
 }
 
 
@@ -437,13 +441,13 @@
   ASSERT(node != NULL);
   AstPrinter ast_printer;
   node->Visit(&ast_printer);
-  THR_Print("\n");
+  logger_->Print("\n");
 }
 
 
-static void IndentN(int count) {
+void AstPrinter::IndentN(int count) {
   for (int i = 0; i < count; i++) {
-    THR_Print(" ");
+    logger_->Print(" ");
   }
 }
 
@@ -454,22 +458,22 @@
   ASSERT(scope != NULL);
   ASSERT(var != NULL);
   IndentN(indent);
-  THR_Print("(%s%s '%s'",
+  logger_->Print("(%s%s '%s'",
             var->is_final() ? "final " : "",
             String::Handle(var->type().Name()).ToCString(),
             var->name().ToCString());
   if (var->owner() != scope) {
-    THR_Print(" alias");
+    logger_->Print(" alias");
   }
   if (var->HasIndex()) {
-    THR_Print(" @%d", var->index());
+    logger_->Print(" @%d", var->index());
     if (var->is_captured()) {
-      THR_Print(" ctx %d", var->owner()->context_level());
+      logger_->Print(" ctx %d", var->owner()->context_level());
     }
   } else if (var->owner()->function_level() != 0) {
-    THR_Print(" lev %d", var->owner()->function_level());
+    logger_->Print(" lev %d", var->owner()->function_level());
   }
-  THR_Print(" valid %s-%s)\n",
+  logger_->Print(" valid %s-%s)\n",
             var->token_pos().ToCString(),
             scope->end_token_pos().ToCString());
 }
@@ -486,16 +490,16 @@
   const LocalScope* child = scope->child();
   while (child != NULL) {
     IndentN(indent);
-    THR_Print("{scope %p ", child);
+    logger_->Print("{scope %p ", child);
     if (child->HasContextLevel()) {
-      THR_Print("ctx %d numctxvar %d ",
+      logger_->Print("ctx %d numctxvar %d ",
                 child->context_level(),
                 child->num_context_variables());
     }
-    THR_Print("llev %d\n", child->loop_level());
+    logger_->Print("llev %d\n", child->loop_level());
     PrintLocalScope(child, 0, indent + kScopeIndent);
     IndentN(indent);
-    THR_Print("}\n");
+    logger_->Print("}\n");
     child = child->sibling();
   }
 }
@@ -509,13 +513,13 @@
   const LocalScope* scope = node_sequence->scope();
   ASSERT(scope != NULL);
   const char* function_name = function.ToFullyQualifiedCString();
-  THR_Print("Scope for function '%s'\n{scope %p ", function_name, scope);
+  logger_->Print("Scope for function '%s'\n{scope %p ", function_name, scope);
   if (scope->HasContextLevel()) {
-    THR_Print("ctx %d numctxvar %d ",
+    logger_->Print("ctx %d numctxvar %d ",
               scope->context_level(),
               scope->num_context_variables());
   }
-  THR_Print("llev %d\n", scope->loop_level());
+  logger_->Print("llev %d\n", scope->loop_level());
   const int num_fixed_params = function.num_fixed_parameters();
   const int num_params = num_fixed_params + function.NumOptionalParameters();
   // Parameters must be listed first and must all appear in the top scope.
@@ -526,7 +530,7 @@
     LocalVariable* param = scope->VariableAt(pos);
     ASSERT(param->owner() == scope);  // No aliases should precede parameters.
     IndentN(indent);
-    THR_Print("(param %s%s '%s'",
+    logger_->Print("(param %s%s '%s'",
               param->is_final() ? "final " : "",
               String::Handle(param->type().Name()).ToCString(),
               param->name().ToCString());
@@ -534,22 +538,22 @@
     if (pos >= num_fixed_params && pos < num_params) {
       const Instance& default_parameter_value =
           parsed_function.DefaultParameterValueAt(pos - num_fixed_params);
-      THR_Print(" =%s", default_parameter_value.ToCString());
+      logger_->Print(" =%s", default_parameter_value.ToCString());
     }
     if (param->HasIndex()) {
-      THR_Print(" @%d", param->index());
+      logger_->Print(" @%d", param->index());
       if (param->is_captured()) {
-        THR_Print(" ctx %d", param->owner()->context_level());
+        logger_->Print(" ctx %d", param->owner()->context_level());
       }
     }
-    THR_Print(" valid %s-%s)\n",
+    logger_->Print(" valid %s-%s)\n",
               param->token_pos().ToCString(),
               scope->end_token_pos().ToCString());
     pos++;
   }
   // Visit remaining non-parameter variables and children scopes.
   PrintLocalScope(scope, pos, indent);
-  THR_Print("}\n");
+  logger_->Print("}\n");
 }
 
 
@@ -557,12 +561,11 @@
   HANDLESCOPE(parsed_function.thread());
   SequenceNode* node_sequence = parsed_function.node_sequence();
   ASSERT(node_sequence != NULL);
-  AstPrinter ast_printer;
   const char* function_name =
       parsed_function.function().ToFullyQualifiedCString();
-  THR_Print("Ast for function '%s' {\n", function_name);
-  node_sequence->Visit(&ast_printer);
-  THR_Print("}\n");
+  logger_->Print("Ast for function '%s' {\n", function_name);
+  node_sequence->Visit(this);
+  logger_->Print("}\n");
 }
 
 }  // namespace dart
diff --git a/runtime/vm/ast_printer.h b/runtime/vm/ast_printer.h
index 7c43ef6..b5ee0bd 100644
--- a/runtime/vm/ast_printer.h
+++ b/runtime/vm/ast_printer.h
@@ -12,12 +12,16 @@
 
 // Forward declaration.
 class ParsedFunction;
+class Log;
 
 class AstPrinter : public AstNodeVisitor {
  public:
-  static void PrintNode(AstNode* node);
-  static void PrintFunctionScope(const ParsedFunction& parsed_function);
-  static void PrintFunctionNodes(const ParsedFunction& parsed_function);
+  explicit AstPrinter(bool log = true);
+  ~AstPrinter();
+
+  void PrintNode(AstNode* node);
+  void PrintFunctionScope(const ParsedFunction& parsed_function);
+  void PrintFunctionNodes(const ParsedFunction& parsed_function);
 
 #define DECLARE_VISITOR_FUNCTION(BaseName)                                     \
   virtual void Visit##BaseName##Node(BaseName##Node* node);
@@ -26,23 +30,22 @@
 #undef DECLARE_VISITOR_FUNCTION
 
  private:
-  AstPrinter();
-  ~AstPrinter();
-
   static const int kScopeIndent = 2;
 
-  static void PrintLocalScopeVariable(const LocalScope* scope,
-                                      LocalVariable* var,
-                                      int indent = 0);
-  static void PrintLocalScope(const LocalScope* scope,
-                              int variable_index,
-                              int indent = 0);
+  void IndentN(int count);
+  void PrintLocalScopeVariable(const LocalScope* scope,
+                               LocalVariable* var,
+                               int indent = 0);
+  void PrintLocalScope(const LocalScope* scope,
+                       int variable_index,
+                       int indent = 0);
 
   void VisitGenericAstNode(AstNode* node);
   void VisitGenericLocalNode(AstNode* node, const LocalVariable& local);
   void VisitGenericFieldNode(AstNode* node, const Field& field);
 
   intptr_t indent_;
+  Log* logger_;
 
   DISALLOW_COPY_AND_ASSIGN(AstPrinter);
 };
diff --git a/runtime/vm/ast_printer_test.cc b/runtime/vm/ast_printer_test.cc
index 5b774e8..888fdda 100644
--- a/runtime/vm/ast_printer_test.cc
+++ b/runtime/vm/ast_printer_test.cc
@@ -21,21 +21,22 @@
                         String::ZoneHandle(Symbols::New(thread, "wurscht")),
                         Type::ZoneHandle(Type::DynamicType()));
   v->set_index(5);
+  AstPrinter ast_printer;
   LoadLocalNode* ll = new LoadLocalNode(kPos, v);
   ReturnNode* r = new ReturnNode(kPos, ll);
-  AstPrinter::PrintNode(r);
+  ast_printer.PrintNode(r);
 
   AstNode* l = new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(3)));
   ReturnNode* rl = new ReturnNode(kPos, l);
-  AstPrinter::PrintNode(rl);
+  ast_printer.PrintNode(rl);
 
-  AstPrinter::PrintNode(new ReturnNode(kPos));
+  ast_printer.PrintNode(new ReturnNode(kPos));
 
-  AstPrinter::PrintNode(new BinaryOpNode(kPos,
-                          Token::kADD,
-                          new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(3))),
-                          new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(5)))));
-  AstPrinter::PrintNode(new UnaryOpNode(kPos, Token::kNEGATE, ll));
+  ast_printer.PrintNode(new BinaryOpNode(kPos,
+                        Token::kADD,
+                        new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(3))),
+                        new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(5)))));
+  ast_printer.PrintNode(new UnaryOpNode(kPos, Token::kNEGATE, ll));
 }
 
 #endif  // !PRODUCT
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 629f3b0..7fce179 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -2089,6 +2089,86 @@
 
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
+class UnlinkedCallSerializationCluster : public SerializationCluster {
+ public:
+  UnlinkedCallSerializationCluster() { }
+  virtual ~UnlinkedCallSerializationCluster() { }
+
+  void Trace(Serializer* s, RawObject* object) {
+    RawUnlinkedCall* unlinked = UnlinkedCall::RawCast(object);
+    objects_.Add(unlinked);
+
+    RawObject** from = unlinked->from();
+    RawObject** to = unlinked->to();
+    for (RawObject** p = from; p <= to; p++) {
+      s->Push(*p);
+    }
+  }
+
+  void WriteAlloc(Serializer* s) {
+    s->WriteCid(kUnlinkedCallCid);
+    intptr_t count = objects_.length();
+    s->Write<int32_t>(count);
+    for (intptr_t i = 0; i < count; i++) {
+      RawUnlinkedCall* unlinked = objects_[i];
+      s->AssignRef(unlinked);
+    }
+  }
+
+  void WriteFill(Serializer* s) {
+    intptr_t count = objects_.length();
+    for (intptr_t i = 0; i < count; i++) {
+      RawUnlinkedCall* unlinked = objects_[i];
+      RawObject** from = unlinked->from();
+      RawObject** to = unlinked->to();
+      for (RawObject** p = from; p <= to; p++) {
+        s->WriteRef(*p);
+      }
+    }
+  }
+
+ private:
+  GrowableArray<RawUnlinkedCall*> objects_;
+};
+#endif  // !DART_PRECOMPILED_RUNTIME
+
+
+class UnlinkedCallDeserializationCluster : public DeserializationCluster {
+ public:
+  UnlinkedCallDeserializationCluster() { }
+  virtual ~UnlinkedCallDeserializationCluster() { }
+
+  void ReadAlloc(Deserializer* d) {
+    start_index_ = d->next_index();
+    PageSpace* old_space = d->heap()->old_space();
+    intptr_t count = d->Read<int32_t>();
+    for (intptr_t i = 0; i < count; i++) {
+      d->AssignRef(AllocateUninitialized(old_space,
+                                         UnlinkedCall::InstanceSize()));
+    }
+    stop_index_ = d->next_index();
+  }
+
+  void ReadFill(Deserializer* d) {
+    bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      RawUnlinkedCall* unlinked =
+          reinterpret_cast<RawUnlinkedCall*>(d->Ref(id));
+      Deserializer::InitializeHeader(unlinked, kUnlinkedCallCid,
+                                     UnlinkedCall::InstanceSize(),
+                                     is_vm_object);
+      RawObject** from = unlinked->from();
+      RawObject** to = unlinked->to();
+      for (RawObject** p = from; p <= to; p++) {
+        *p = d->ReadRef();
+      }
+    }
+  }
+};
+
+
+#if !defined(DART_PRECOMPILED_RUNTIME)
 class ICDataSerializationCluster : public SerializationCluster {
  public:
   ICDataSerializationCluster() { }
@@ -4271,6 +4351,7 @@
       return new (Z) ExceptionHandlersSerializationCluster();
     case kContextCid: return new (Z) ContextSerializationCluster();
     case kContextScopeCid: return new (Z) ContextScopeSerializationCluster();
+    case kUnlinkedCallCid: return new (Z) UnlinkedCallSerializationCluster();
     case kICDataCid: return new (Z) ICDataSerializationCluster();
     case kMegamorphicCacheCid:
       return new (Z) MegamorphicCacheSerializationCluster();
@@ -4436,7 +4517,7 @@
   }
 
   ClassTable* table = isolate()->class_table();
-  for (intptr_t cid = kClassCid; cid <= kUnwindErrorCid; cid++) {
+  for (intptr_t cid = kClassCid; cid < kInstanceCid; cid++) {
     // Error has no class object.
     if (cid != kErrorCid) {
       ASSERT(table->HasValidClassAt(cid));
@@ -4593,6 +4674,7 @@
       return new (Z) ExceptionHandlersDeserializationCluster();
     case kContextCid: return new (Z) ContextDeserializationCluster();
     case kContextScopeCid: return new (Z) ContextScopeDeserializationCluster();
+    case kUnlinkedCallCid: return new (Z) UnlinkedCallDeserializationCluster();
     case kICDataCid: return new (Z) ICDataDeserializationCluster();
     case kMegamorphicCacheCid:
       return new (Z) MegamorphicCacheDeserializationCluster();
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index 51e70e8..ee94ebf 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -1106,16 +1106,21 @@
   }
 
   if (old_target.raw() == target_function.raw()) {
-    intptr_t lower, upper;
+    intptr_t lower, upper, unchecked_lower, unchecked_upper;
     if (receiver.GetClassId() < cache.lower_limit()) {
       lower = receiver.GetClassId();
+      unchecked_lower = receiver.GetClassId();
       upper = cache.upper_limit();
+      unchecked_upper = cache.lower_limit() - 1;
     } else {
       lower = cache.lower_limit();
+      unchecked_lower = cache.upper_limit() + 1;
       upper = receiver.GetClassId();
+      unchecked_upper = receiver.GetClassId();
     }
 
-    if (IsSingleTarget(isolate, zone, lower, upper, target_function, name)) {
+    if (IsSingleTarget(isolate, zone, unchecked_lower, unchecked_upper,
+                       target_function, name)) {
       cache.set_lower_limit(lower);
       cache.set_upper_limit(upper);
       // Return the ICData. The single target stub will jump to continue in the
@@ -1141,6 +1146,81 @@
 }
 
 
+DEFINE_RUNTIME_ENTRY(UnlinkedCall, 2) {
+#if defined(TARGET_ARCH_DBC)
+  // DBC does not use switchable calls.
+  UNREACHABLE();
+#else
+  const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0));
+  const UnlinkedCall& unlinked =
+      UnlinkedCall::CheckedHandle(zone, arguments.ArgAt(1));
+
+  DartFrameIterator iterator;
+  StackFrame* caller_frame = iterator.NextFrame();
+  ASSERT(caller_frame->IsDartFrame());
+  const Code& caller_code =
+      Code::Handle(zone, caller_frame->LookupDartCode());
+  const Function& caller_function =
+      Function::Handle(zone, caller_frame->LookupDartFunction());
+
+  const String& name = String::Handle(zone, unlinked.target_name());
+  const Array& descriptor = Array::Handle(zone, unlinked.args_descriptor());
+  const ICData& ic_data =
+      ICData::Handle(zone, ICData::New(caller_function,
+                                       name,
+                                       descriptor,
+                                       Thread::kNoDeoptId,
+                                       1, /* args_tested */
+                                       false /* static_call */));
+
+  Class& cls = Class::Handle(zone, receiver.clazz());
+  ArgumentsDescriptor args_desc(descriptor);
+  Function& target_function = Function::Handle(zone,
+      Resolver::ResolveDynamicForReceiverClass(cls,
+                                               name,
+                                               args_desc));
+  if (target_function.IsNull()) {
+    target_function = InlineCacheMissHelper(receiver, descriptor, name);
+  }
+  if (target_function.IsNull()) {
+    ASSERT(!FLAG_lazy_dispatchers);
+  } else {
+    ic_data.AddReceiverCheck(receiver.GetClassId(), target_function);
+  }
+
+  if (!target_function.IsNull() &&
+      !target_function.HasOptionalParameters()) {
+    // Patch to monomorphic call.
+    ASSERT(target_function.HasCode());
+    const Code& target_code =
+        Code::Handle(zone, target_function.CurrentCode());
+    const Smi& expected_cid =
+        Smi::Handle(zone, Smi::New(receiver.GetClassId()));
+    CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code,
+                                       expected_cid, target_code);
+
+    // Return the ICData. The miss stub will jump to continue in the IC call
+    // stub.
+    arguments.SetReturn(ic_data);
+    return;
+  }
+
+  // Patch to call through stub.
+  const Code& stub =
+      Code::Handle(zone, StubCode::ICCallThroughCode_entry()->code());
+  ASSERT(!Isolate::Current()->compilation_allowed());
+  CodePatcher::PatchSwitchableCallAt(caller_frame->pc(),
+                                     caller_code,
+                                     ic_data,
+                                     stub);
+
+  // Return the ICData. The miss stub will jump to continue in the IC lookup
+  // stub.
+  arguments.SetReturn(ic_data);
+#endif  // !DBC
+}
+
+
 // Handle a miss of a megamorphic cache.
 //   Arg0: Receiver.
 //   Returns: the ICData used to continue with a polymorphic call.
@@ -1949,11 +2029,23 @@
   {
     WritableInstructionsScope writable(instrs.PayloadStart(), instrs.size());
     CodePatcher::InsertDeoptimizationCallAt(pc, lazy_deopt_jump);
-  }
-  if (FLAG_trace_patching) {
-    const String& name = String::Handle(function.name());
-    OS::PrintErr("InsertDeoptimizationCallAt: %" Px " to %" Px " for %s\n", pc,
-                 lazy_deopt_jump, name.ToCString());
+    if (FLAG_trace_patching) {
+      const String& name = String::Handle(function.name());
+      OS::PrintErr(
+          "InsertDeoptimizationCallAt: 0x%" Px " to 0x%" Px " for %s\n",
+          pc, lazy_deopt_jump, name.ToCString());
+    }
+    const ExceptionHandlers& handlers =
+        ExceptionHandlers::Handle(zone, optimized_code.exception_handlers());
+    RawExceptionHandlers::HandlerInfo info;
+    for (intptr_t i = 0; i < handlers.num_entries(); ++i) {
+      handlers.GetHandlerInfo(i, &info);
+      const uword patch_pc = instrs.PayloadStart() + info.handler_pc_offset;
+      CodePatcher::InsertDeoptimizationCallAt(patch_pc, lazy_deopt_jump);
+      if (FLAG_trace_patching) {
+        OS::PrintErr("  at handler 0x%" Px "\n", patch_pc);
+      }
+    }
   }
   // Mark code as dead (do not GC its embedded objects).
   optimized_code.set_is_alive(false);
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index 93898ad..25fad98 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -1316,9 +1316,12 @@
         // We got an error during compilation.
         error = thread->sticky_error();
         thread->clear_sticky_error();
-        // The non-optimizing compiler should not bail out.
-        ASSERT(error.IsLanguageError() &&
-               LanguageError::Cast(error).kind() != Report::kBailout);
+        // The non-optimizing compiler can get an unhandled exception
+        // due to OOM or Stack overflow errors, it should not however
+        // bail out.
+        ASSERT(error.IsUnhandledException() ||
+               (error.IsLanguageError() &&
+                LanguageError::Cast(error).kind() != Report::kBailout));
         return error.raw();
       }
     }
@@ -1339,11 +1342,13 @@
 
     if (FLAG_disassemble && FlowGraphPrinter::ShouldPrint(function)) {
       SafepointOperationScope safepoint_scope(thread);
+      NoHeapGrowthControlScope no_growth_control;
       Disassembler::DisassembleCode(function, optimized);
     } else if (FLAG_disassemble_optimized &&
                optimized &&
                FlowGraphPrinter::ShouldPrint(function)) {
       SafepointOperationScope safepoint_scope(thread);
+      NoHeapGrowthControlScope no_growth_control;
       Disassembler::DisassembleCode(function, true);
     }
 
@@ -1374,6 +1379,65 @@
 }
 
 
+static RawError* ParseFunctionHelper(CompilationPipeline* pipeline,
+                                     const Function& function,
+                                     bool optimized,
+                                     intptr_t osr_id) {
+  ASSERT(!FLAG_precompiled_mode);
+  ASSERT(!optimized || function.was_compiled());
+  LongJumpScope jump;
+  if (setjmp(*jump.Set()) == 0) {
+    Thread* const thread = Thread::Current();
+    StackZone stack_zone(thread);
+    Zone* const zone = stack_zone.GetZone();
+    const bool trace_compiler =
+        FLAG_trace_compiler ||
+        (FLAG_trace_optimizing_compiler && optimized);
+
+    if (trace_compiler) {
+      const intptr_t token_size = function.end_token_pos().Pos() -
+                                  function.token_pos().Pos();
+      THR_Print("Parsing %s%sfunction %s: '%s' @ token %s, size %" Pd "\n",
+                (osr_id == Compiler::kNoOSRDeoptId ? "" : "osr "),
+                (optimized ? "optimized " : ""),
+                (Compiler::IsBackgroundCompilation() ? "(background)" : ""),
+                function.ToFullyQualifiedCString(),
+                function.token_pos().ToCString(),
+                token_size);
+    }
+    ParsedFunction* parsed_function = new(zone) ParsedFunction(
+        thread, Function::ZoneHandle(zone, function.raw()));
+    pipeline->ParseFunction(parsed_function);
+    // For now we just walk thru the AST nodes and in DEBUG mode we print
+    // them otherwise just skip through them, this will be need to be
+    // wired to generate the IR format.
+#if !defined(PRODUCT)
+#if defined(DEBUG)
+    AstPrinter ast_printer(true);
+#else
+    AstPrinter ast_printer(false);
+#endif  // defined(DEBUG).
+    ast_printer.PrintFunctionNodes(*parsed_function);
+#endif  // !defined(PRODUCT).
+    return Error::null();
+  } else {
+    Thread* const thread = Thread::Current();
+    StackZone stack_zone(thread);
+    Error& error = Error::Handle();
+    // We got an error during compilation or it is a bailout from background
+    // compilation (e.g., during parsing with EnsureIsFinalized).
+    error = thread->sticky_error();
+    thread->clear_sticky_error();
+    // Unoptimized compilation or precompilation may encounter compile-time
+    // errors, but regular optimized compilation should not.
+    ASSERT(!optimized);
+    return error.raw();
+  }
+  UNREACHABLE();
+  return Error::null();
+}
+
+
 RawError* Compiler::CompileFunction(Thread* thread,
                                     const Function& function) {
 #ifdef DART_PRECOMPILER
@@ -1404,6 +1468,31 @@
 }
 
 
+RawError* Compiler::ParseFunction(Thread* thread,
+                                  const Function& function) {
+  Isolate* isolate = thread->isolate();
+NOT_IN_PRODUCT(
+  VMTagScope tagScope(thread, VMTag::kCompileUnoptimizedTagId);
+  TIMELINE_FUNCTION_COMPILATION_DURATION(thread, "ParseFunction", function);
+)  // !PRODUCT
+
+  if (!isolate->compilation_allowed()) {
+    FATAL3("Precompilation missed function %s (%s, %s)\n",
+           function.ToLibNamePrefixedQualifiedCString(),
+           function.token_pos().ToCString(),
+           Function::KindToCString(function.kind()));
+  }
+
+  CompilationPipeline* pipeline =
+      CompilationPipeline::New(thread->zone(), function);
+
+  return ParseFunctionHelper(pipeline,
+                             function,
+                             /* optimized = */ false,
+                             kNoOSRDeoptId);
+}
+
+
 RawError* Compiler::EnsureUnoptimizedCode(Thread* thread,
                                           const Function& function) {
   if (function.unoptimized_code() != Object::null()) {
@@ -1555,6 +1644,40 @@
 }
 
 
+RawError* Compiler::ParseAllFunctions(const Class& cls) {
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
+  Error& error = Error::Handle(zone);
+  Array& functions = Array::Handle(zone, cls.functions());
+  Function& func = Function::Handle(zone);
+  // Class dynamic lives in the vm isolate. Its array fields cannot be set to
+  // an empty array.
+  if (functions.IsNull()) {
+    ASSERT(cls.IsDynamicClass());
+    return error.raw();
+  }
+  // Compile all the regular functions.
+  for (int i = 0; i < functions.Length(); i++) {
+    func ^= functions.At(i);
+    ASSERT(!func.IsNull());
+    if (!func.is_abstract() && !func.IsRedirectingFactory()) {
+      if ((cls.is_mixin_app_alias() || cls.IsMixinApplication()) &&
+          func.HasOptionalParameters()) {
+        // Skipping optional parameters in mixin application.
+        continue;
+      }
+      error = ParseFunction(thread, func);
+      if (!error.IsNull()) {
+        return error.raw();
+      }
+      func.ClearICDataArray();
+      func.ClearCode();
+    }
+  }
+  return error.raw();
+}
+
+
 RawObject* Compiler::EvaluateStaticInitializer(const Field& field) {
 #ifdef DART_PRECOMPILER
   if (FLAG_precompiled_mode) {
@@ -1633,7 +1756,8 @@
     if (FLAG_trace_compiler) {
       THR_Print("compiling expression: ");
       if (FLAG_support_ast_printer) {
-        AstPrinter::PrintNode(fragment);
+        AstPrinter ast_printer;
+        ast_printer.PrintNode(fragment);
       }
     }
 
@@ -2091,6 +2215,13 @@
 }
 
 
+RawError* Compiler::ParseFunction(Thread* thread,
+                                  const Function& function) {
+  UNREACHABLE();
+  return Error::null();
+}
+
+
 RawError* Compiler::EnsureUnoptimizedCode(Thread* thread,
                                           const Function& function) {
   UNREACHABLE();
@@ -2124,6 +2255,12 @@
 }
 
 
+RawError* Compiler::ParseAllFunctions(const Class& cls) {
+  UNREACHABLE();
+  return Error::null();
+}
+
+
 RawObject* Compiler::EvaluateStaticInitializer(const Field& field) {
   ASSERT(field.HasPrecompiledInitializer());
   const Function& initializer =
diff --git a/runtime/vm/compiler.h b/runtime/vm/compiler.h
index 1e8e3fc..4ec478f 100644
--- a/runtime/vm/compiler.h
+++ b/runtime/vm/compiler.h
@@ -100,6 +100,7 @@
   //
   // Returns Error::null() if there is no compilation error.
   static RawError* CompileFunction(Thread* thread, const Function& function);
+  static RawError* ParseFunction(Thread* thread, const Function& function);
 
   // Generates unoptimized code if not present, current code is unchanged.
   static RawError* EnsureUnoptimizedCode(Thread* thread,
@@ -143,6 +144,7 @@
   //
   // Returns Error::null() if there is no compilation error.
   static RawError* CompileAllFunctions(const Class& cls);
+  static RawError* ParseAllFunctions(const Class& cls);
 
   // Notify the compiler that background (optimized) compilation has failed
   // because the mutator thread changed the state (e.g., deoptimization,
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index d5d7998..c1a2f36 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -50,7 +50,7 @@
 
 namespace dart {
 
-// Facilitate quick access to the current zone once we have the curren thread.
+// Facilitate quick access to the current zone once we have the current thread.
 #define Z (T->zone())
 
 
@@ -1486,7 +1486,8 @@
 
 
 DART_EXPORT bool Dart_HasStickyError() {
-  Isolate* isolate = Isolate::Current();
+  Thread* T = Thread::Current();
+  Isolate* isolate = T->isolate();
   CHECK_ISOLATE(isolate);
   NoSafepointScope no_safepoint_scope;
   return isolate->sticky_error() != Error::null();
@@ -1494,12 +1495,13 @@
 
 
 DART_EXPORT Dart_Handle Dart_GetStickyError() {
-  Isolate* I = Isolate::Current();
+  Thread* T = Thread::Current();
+  Isolate* I = T->isolate();
   CHECK_ISOLATE(I);
   NoSafepointScope no_safepoint_scope;
-  if (I->sticky_error() != Object::null()) {
+  if (I->sticky_error() != Error::null()) {
     Dart_Handle error =
-        Api::NewHandle(Thread::Current(), I->sticky_error());
+        Api::NewHandle(T, I->sticky_error());
     return error;
   }
   return Dart_Null();
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index a4afc16..51c6721 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -371,10 +371,16 @@
 Breakpoint* BreakpointLocation::AddPerClosure(Debugger* dbg,
                                               const Instance& closure,
                                               bool for_over_await) {
-  Breakpoint* bpt = breakpoints();
-  while (bpt != NULL) {
-    if (bpt->IsPerClosure() && bpt->closure() == closure.raw()) break;
-    bpt = bpt->next();
+  Breakpoint* bpt = NULL;
+  // Do not reuse existing breakpoints for stepping over await clauses.
+  // A second async step-over command will set a new breakpoint before
+  // the existing one gets deleted when first async step-over resumes.
+  if (!for_over_await) {
+    bpt = breakpoints();
+    while (bpt != NULL) {
+      if (bpt->IsPerClosure() && (bpt->closure() == closure.raw())) break;
+      bpt = bpt->next();
+    }
   }
   if (bpt == NULL) {
     bpt = new Breakpoint(dbg->nextId(), this);
@@ -2607,9 +2613,6 @@
   if (!func.is_debuggable()) {
     return false;
   }
-  if (ServiceIsolate::IsRunning()) {
-    return true;
-  }
   const Class& cls = Class::Handle(func.Owner());
   const Library& lib = Library::Handle(cls.library());
   return lib.IsDebuggable();
@@ -2678,7 +2681,7 @@
     // There is an "interesting frame" set. Only pause at appropriate
     // locations in this frame.
     if (IsCalleeFrameOf(stepping_fp_, frame->fp())) {
-      // We are i n a callee of the frame we're interested in.
+      // We are in a callee of the frame we're interested in.
       // Ignore this stepping break.
       return Error::null();
     } else if (IsCalleeFrameOf(frame->fp(), stepping_fp_)) {
@@ -2857,10 +2860,6 @@
     return;
   }
 
-  if (!NeedsDebugEvents()) {
-    OS::Print("Hit debugger!");
-  }
-
   DebuggerStackTrace* stack_trace = CollectStackTrace();
   ASSERT(stack_trace->Length() > 0);
   ASSERT(stack_trace_ == NULL);
diff --git a/runtime/vm/debugger_api_impl_test.cc b/runtime/vm/debugger_api_impl_test.cc
index 80311f1..a41d10b 100644
--- a/runtime/vm/debugger_api_impl_test.cc
+++ b/runtime/vm/debugger_api_impl_test.cc
@@ -38,6 +38,29 @@
 }
 
 
+static void DisableDebuggabilityOfDartColonLibraries() {
+  const char* dart_colon = "dart:";
+  const intptr_t dart_colon_length = strlen(dart_colon);
+  // Disable debuggability of all dart: libraries.
+  Dart_Handle library_ids = Dart_GetLibraryIds();
+  intptr_t library_ids_length;
+  Dart_ListLength(library_ids, &library_ids_length);
+  for (intptr_t i = 0; i < library_ids_length; i++) {
+    Dart_Handle library_id_handle = Dart_ListGetAt(library_ids, i);
+    int64_t library_id;
+    Dart_IntegerToInt64(library_id_handle, &library_id);
+    Dart_Handle library_url_handle = Dart_GetLibraryURL(library_id);
+    const char* library_url;
+    Dart_StringToCString(library_url_handle, &library_url);
+    if (strncmp(library_url, dart_colon, dart_colon_length) == 0) {
+      Dart_SetLibraryDebuggable(library_id, false);
+    } else {
+      Dart_SetLibraryDebuggable(library_id, true);
+    }
+  }
+}
+
+
 static Dart_Handle Invoke(const char* func_name) {
   ASSERT(script_lib != NULL);
   ASSERT(!Dart_IsError(script_lib));
@@ -741,6 +764,8 @@
   LoadScript(kScriptChars);
   Dart_SetPausedEventHandler(&TestStepIntoHandler);
 
+  DisableDebuggabilityOfDartColonLibraries();
+
   SetBreakpointAtEntry("", "main");
   breakpoint_hit = false;
   breakpoint_hit_counter = 0;
diff --git a/runtime/vm/disassembler_arm.cc b/runtime/vm/disassembler_arm.cc
index 67c0afb..6419c08 100644
--- a/runtime/vm/disassembler_arm.cc
+++ b/runtime/vm/disassembler_arm.cc
@@ -116,10 +116,10 @@
 static const char* reg_names[kNumberOfCpuRegisters] = {
 #if defined(TARGET_ABI_IOS)
   "r0", "r1", "r2", "r3", "r4", "pp", "r6", "fp",
-  "r8", "r9", "r10", "r11", "ip", "sp", "lr", "pc",
+  "r8", "r9", "thr", "r11", "ip", "sp", "lr", "pc",
 #elif defined(TARGET_ABI_EABI)
   "r0", "r1", "r2", "r3", "r4", "pp", "r6", "r7",
-  "r8", "r9", "r10", "fp", "ip", "sp", "lr", "pc",
+  "r8", "r9", "thr", "fp", "ip", "sp", "lr", "pc",
 #else
 #error Unknown ABI
 #endif
diff --git a/runtime/vm/disassembler_arm64.cc b/runtime/vm/disassembler_arm64.cc
index dd7d00c..6bbc3c7 100644
--- a/runtime/vm/disassembler_arm64.cc
+++ b/runtime/vm/disassembler_arm64.cc
@@ -92,7 +92,7 @@
   "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
   "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
   "ip0", "ip1", "r18", "sp",  "r20", "r21", "r22", "r23",
-  "r24", "r25", "r26", "pp",  "ctx", "fp",  "lr",  "r31",
+  "r24", "r25", "thr", "pp",  "ctx", "fp",  "lr",  "r31",
 };
 
 
diff --git a/runtime/vm/disassembler_mips.cc b/runtime/vm/disassembler_mips.cc
index 78831a7..49fbb33 100644
--- a/runtime/vm/disassembler_mips.cc
+++ b/runtime/vm/disassembler_mips.cc
@@ -79,10 +79,10 @@
 
 
 static const char* reg_names[kNumberOfCpuRegisters] = {
-  "r0" , "r1" , "r2" , "r3" , "r4" , "r5" , "r6" , "r7" ,
-  "r8" , "r9" , "r10", "r11", "r12", "r13", "r14", "r15",
-  "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
-  "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+  "zr", "at", "v0", "v1" , "a0", "a1", "a2", "a3",
+  "t0", "t1", "t2", "t3" , "t4", "t5", "t6", "t7",
+  "s0", "s1", "s2", "thr", "s4", "s5", "s6", "pp",
+  "t8", "t9", "k0", "k1" , "gp", "sp", "fp", "ra",
 };
 
 
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index edfad99..7c9d71d 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -330,7 +330,6 @@
                                           &handler_needs_stacktrace);
     if (handler_pc == 0) {
       // No Dart frame.
-      ASSERT(!thread->IsMutatorThread());
       ASSERT(incoming_exception.raw() ==
              isolate->object_store()->out_of_memory());
       const UnhandledException& error = UnhandledException::Handle(
diff --git a/runtime/vm/flow_graph.cc b/runtime/vm/flow_graph.cc
index 89ed20d..f513b30 100644
--- a/runtime/vm/flow_graph.cc
+++ b/runtime/vm/flow_graph.cc
@@ -2009,7 +2009,9 @@
        !block_it.Done();
        block_it.Advance()) {
     BlockEntryInstr* block = block_it.Current();
-    block->RemoveEnvironment();
+    if (!block->IsCatchBlockEntry()) {
+      block->RemoveEnvironment();
+    }
     for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
       Instruction* current = it.Current();
       if (!current->CanDeoptimize()) {
diff --git a/runtime/vm/flow_graph_allocator.cc b/runtime/vm/flow_graph_allocator.cc
index 558e6f7..7b62e37 100644
--- a/runtime/vm/flow_graph_allocator.cc
+++ b/runtime/vm/flow_graph_allocator.cc
@@ -616,6 +616,9 @@
       // TODO(vegorov) support try-catch/finally for DBC.
       flow_graph_.parsed_function().Bailout("FlowGraphAllocator", "Catch");
 #endif
+
+      ProcessEnvironmentUses(catch_entry, catch_entry);  // For lazy deopt
+
       for (intptr_t i = 0;
            i < catch_entry->initial_definitions()->length();
            i++) {
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index 7a01480..ffdf3de 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -3586,10 +3586,14 @@
   // call. Exception: don't do this when assigning to or from internal
   // variables, or for generated code that has no source position.
   if (FLAG_support_debugger) {
-    if ((node->value()->IsLiteralNode() ||
-        (node->value()->IsLoadLocalNode() &&
-            !node->value()->AsLoadLocalNode()->local().IsInternal()) ||
-        node->value()->IsClosureNode()) &&
+    AstNode* rhs = node->value();
+    if (rhs->IsAssignableNode()) {
+      rhs = rhs->AsAssignableNode()->expr();
+    }
+    if ((rhs->IsLiteralNode() ||
+         (rhs->IsLoadLocalNode() &&
+          !rhs->AsLoadLocalNode()->local().IsInternal()) ||
+         rhs->IsClosureNode()) &&
         !node->local().IsInternal() &&
         node->token_pos().IsDebugPause()) {
       AddInstruction(new(Z) DebugStepCheckInstr(
@@ -3704,6 +3708,23 @@
     StoreStaticFieldNode* node,
     bool result_is_needed,
     TokenPosition token_pos) {
+  if (FLAG_support_debugger) {
+    // If the right hand side is an expression that does not contain
+    // a safe point for the debugger to stop, add an explicit stub
+    // call.
+    AstNode* rhs = node->value();
+    if (rhs->IsAssignableNode()) {
+      rhs = rhs->AsAssignableNode()->expr();
+    }
+    if ((rhs->IsLiteralNode() ||
+         rhs->IsLoadLocalNode() ||
+         rhs->IsClosureNode()) &&
+         node->token_pos().IsDebugPause()) {
+      AddInstruction(new(Z) DebugStepCheckInstr(
+          node->token_pos(), RawPcDescriptors::kRuntimeCall));
+    }
+  }
+
   ValueGraphVisitor for_value(owner());
   node->value()->Visit(&for_value);
   Append(for_value);
@@ -4300,7 +4321,8 @@
                                   try_handler_index,
                                   catch_block->exception_var(),
                                   catch_block->stacktrace_var(),
-                                  catch_block->needs_stacktrace());
+                                  catch_block->needs_stacktrace(),
+                                  Thread::Current()->GetNextDeoptId());
   owner()->AddCatchEntry(catch_entry);
   AppendFragment(catch_entry, for_catch);
 
@@ -4346,7 +4368,8 @@
                                     catch_handler_index,
                                     catch_block->exception_var(),
                                     catch_block->stacktrace_var(),
-                                    catch_block->needs_stacktrace());
+                                    catch_block->needs_stacktrace(),
+                                    Thread::Current()->GetNextDeoptId());
     owner()->AddCatchEntry(finally_entry);
     AppendFragment(finally_entry, for_finally);
   }
@@ -4577,10 +4600,12 @@
                       FLAG_profile_vm);
   if (FLAG_support_ast_printer && FLAG_print_ast) {
     // Print the function ast before IL generation.
-    AstPrinter::PrintFunctionNodes(parsed_function());
+    AstPrinter ast_printer;
+    ast_printer.PrintFunctionNodes(parsed_function());
   }
   if (FLAG_support_ast_printer && FLAG_print_scopes) {
-    AstPrinter::PrintFunctionScope(parsed_function());
+    AstPrinter ast_printer;
+    ast_printer.PrintFunctionScope(parsed_function());
   }
   TargetEntryInstr* normal_entry =
       new(Z) TargetEntryInstr(AllocateBlockId(),
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index e668652..4e0d2c7 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -536,7 +536,10 @@
 
     entry->set_offset(assembler()->CodeSize());
     BeginCodeSourceRange();
+    ASSERT(pending_deoptimization_env_ == NULL);
+    pending_deoptimization_env_ = entry->env();
     entry->EmitNativeCode(this);
+    pending_deoptimization_env_ = NULL;
     EndCodeSourceRange(entry->token_pos());
     // Compile all successors until an exit, branch, or a block entry.
     for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
@@ -805,8 +808,7 @@
 }
 
 
-void FlowGraphCompiler::AddDeoptIndexAtCall(intptr_t deopt_id,
-                                            TokenPosition token_pos) {
+void FlowGraphCompiler::AddDeoptIndexAtCall(intptr_t deopt_id) {
   ASSERT(is_optimizing());
   ASSERT(!intrinsic_mode());
   CompilerDeoptInfo* info =
diff --git a/runtime/vm/flow_graph_compiler.h b/runtime/vm/flow_graph_compiler.h
index d6c74cb..31a627a 100644
--- a/runtime/vm/flow_graph_compiler.h
+++ b/runtime/vm/flow_graph_compiler.h
@@ -536,7 +536,7 @@
   uint16_t ToEmbeddableCid(intptr_t cid, Instruction* instruction);
 #endif  // defined(TARGET_ARCH_DBC)
 
-  void AddDeoptIndexAtCall(intptr_t deopt_id, TokenPosition token_pos);
+  void AddDeoptIndexAtCall(intptr_t deopt_id);
 
   void AddSlowPathCode(SlowPathCode* slow_path);
 
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index dadc66a..38db33b 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -1163,7 +1163,7 @@
   // deoptimization point in optimized code, after call.
   const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
   if (is_optimizing()) {
-    AddDeoptIndexAtCall(deopt_id_after, token_pos);
+    AddDeoptIndexAtCall(deopt_id_after);
   } else {
     // Add deoptimization continuation point after the call and before the
     // arguments are removed.
@@ -1191,7 +1191,7 @@
   // deoptimization point in optimized code, after call.
   const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
   if (is_optimizing()) {
-    AddDeoptIndexAtCall(deopt_id_after, token_pos);
+    AddDeoptIndexAtCall(deopt_id_after);
   } else {
     // Add deoptimization continuation point after the call and before the
     // arguments are removed.
@@ -1215,7 +1215,7 @@
     // deoptimization point in optimized code, after call.
     const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
     if (is_optimizing()) {
-      AddDeoptIndexAtCall(deopt_id_after, token_pos);
+      AddDeoptIndexAtCall(deopt_id_after);
     } else {
       // Add deoptimization continuation point after the call and before the
       // arguments are removed.
@@ -1354,7 +1354,7 @@
   } else if (is_optimizing()) {
     AddCurrentDescriptor(RawPcDescriptors::kOther,
                          Thread::kNoDeoptId, token_pos);
-    AddDeoptIndexAtCall(deopt_id_after, token_pos);
+    AddDeoptIndexAtCall(deopt_id_after);
   } else {
     AddCurrentDescriptor(RawPcDescriptors::kOther,
         Thread::kNoDeoptId, token_pos);
@@ -1389,7 +1389,7 @@
   RecordSafepoint(locs);
   const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
   if (is_optimizing()) {
-    AddDeoptIndexAtCall(deopt_id_after, token_pos);
+    AddDeoptIndexAtCall(deopt_id_after);
   } else {
     // Add deoptimization continuation point after the call and before the
     // arguments are removed.
diff --git a/runtime/vm/flow_graph_compiler_arm64.cc b/runtime/vm/flow_graph_compiler_arm64.cc
index 304dcb3..2634ae2b 100644
--- a/runtime/vm/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/flow_graph_compiler_arm64.cc
@@ -1157,7 +1157,7 @@
   // deoptimization point in optimized code, after call.
   const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
   if (is_optimizing()) {
-    AddDeoptIndexAtCall(deopt_id_after, token_pos);
+    AddDeoptIndexAtCall(deopt_id_after);
   } else {
     // Add deoptimization continuation point after the call and before the
     // arguments are removed.
@@ -1184,7 +1184,7 @@
   // deoptimization point in optimized code, after call.
   const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
   if (is_optimizing()) {
-    AddDeoptIndexAtCall(deopt_id_after, token_pos);
+    AddDeoptIndexAtCall(deopt_id_after);
   } else {
     // Add deoptimization continuation point after the call and before the
     // arguments are removed.
@@ -1207,7 +1207,7 @@
     // deoptimization point in optimized code, after call.
     const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
     if (is_optimizing()) {
-      AddDeoptIndexAtCall(deopt_id_after, token_pos);
+      AddDeoptIndexAtCall(deopt_id_after);
     } else {
       // Add deoptimization continuation point after the call and before the
       // arguments are removed.
@@ -1336,7 +1336,7 @@
   } else if (is_optimizing()) {
     AddCurrentDescriptor(RawPcDescriptors::kOther,
         Thread::kNoDeoptId, token_pos);
-    AddDeoptIndexAtCall(deopt_id_after, token_pos);
+    AddDeoptIndexAtCall(deopt_id_after);
   } else {
     AddCurrentDescriptor(RawPcDescriptors::kOther,
         Thread::kNoDeoptId, token_pos);
@@ -1370,7 +1370,7 @@
   RecordSafepoint(locs);
   const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
   if (is_optimizing()) {
-    AddDeoptIndexAtCall(deopt_id_after, token_pos);
+    AddDeoptIndexAtCall(deopt_id_after);
   } else {
     // Add deoptimization continuation point after the call and before the
     // arguments are removed.
diff --git a/runtime/vm/flow_graph_compiler_dbc.cc b/runtime/vm/flow_graph_compiler_dbc.cc
index fc1534d..69dd8ad 100644
--- a/runtime/vm/flow_graph_compiler_dbc.cc
+++ b/runtime/vm/flow_graph_compiler_dbc.cc
@@ -198,7 +198,7 @@
     // On all other architectures caller drops outgoing arguments itself
     // hence the difference.
     pending_deoptimization_env_->DropArguments(instr->ArgumentCount());
-    AddDeoptIndexAtCall(deopt_id_after, instr->token_pos());
+    AddDeoptIndexAtCall(deopt_id_after);
   } else {
     // Add deoptimization continuation point after the call and before the
     // arguments are removed.
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index 461785a..90ec1f2 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -1170,7 +1170,7 @@
   // deoptimization point in optimized code, after call.
   const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
   if (is_optimizing()) {
-    AddDeoptIndexAtCall(deopt_id_after, token_pos);
+    AddDeoptIndexAtCall(deopt_id_after);
   } else {
     // Add deoptimization continuation point after the call and before the
     // arguments are removed.
@@ -1192,7 +1192,7 @@
     // deoptimization point in optimized code, after call.
     const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
     if (is_optimizing()) {
-      AddDeoptIndexAtCall(deopt_id_after, token_pos);
+      AddDeoptIndexAtCall(deopt_id_after);
     } else {
       // Add deoptimization continuation point after the call and before the
       // arguments are removed.
@@ -1322,7 +1322,7 @@
   // Precompilation not implemented on ia32 platform.
   ASSERT(!FLAG_precompiled_mode);
   if (is_optimizing()) {
-    AddDeoptIndexAtCall(deopt_id_after, token_pos);
+    AddDeoptIndexAtCall(deopt_id_after);
   } else {
     // Add deoptimization continuation point after the call and before the
     // arguments are removed.
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index f27c80a..fb3eadb 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -1177,7 +1177,7 @@
   // deoptimization point in optimized code, after call.
   const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
   if (is_optimizing()) {
-    AddDeoptIndexAtCall(deopt_id_after, token_pos);
+    AddDeoptIndexAtCall(deopt_id_after);
   } else {
     // Add deoptimization continuation point after the call and before the
     // arguments are removed.
@@ -1206,7 +1206,7 @@
   // deoptimization point in optimized code, after call.
   const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
   if (is_optimizing()) {
-    AddDeoptIndexAtCall(deopt_id_after, token_pos);
+    AddDeoptIndexAtCall(deopt_id_after);
   } else {
     // Add deoptimization continuation point after the call and before the
     // arguments are removed.
@@ -1231,7 +1231,7 @@
     // deoptimization point in optimized code, after call.
     const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
     if (is_optimizing()) {
-      AddDeoptIndexAtCall(deopt_id_after, token_pos);
+      AddDeoptIndexAtCall(deopt_id_after);
     } else {
       // Add deoptimization continuation point after the call and before the
       // arguments are removed.
@@ -1360,7 +1360,7 @@
   } else if (is_optimizing()) {
     AddCurrentDescriptor(RawPcDescriptors::kOther,
         Thread::kNoDeoptId, token_pos);
-    AddDeoptIndexAtCall(deopt_id_after, token_pos);
+    AddDeoptIndexAtCall(deopt_id_after);
   } else {
     AddCurrentDescriptor(RawPcDescriptors::kOther,
         Thread::kNoDeoptId, token_pos);
@@ -1394,7 +1394,7 @@
   RecordSafepoint(locs);
   const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
   if (is_optimizing()) {
-    AddDeoptIndexAtCall(deopt_id_after, token_pos);
+    AddDeoptIndexAtCall(deopt_id_after);
   } else {
     // Add deoptimization continuation point after the call and before the
     // arguments are removed.
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index fb521bf..0c0444a 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -1172,7 +1172,7 @@
   // deoptimization point in optimized code, after call.
   const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
   if (is_optimizing()) {
-    AddDeoptIndexAtCall(deopt_id_after, token_pos);
+    AddDeoptIndexAtCall(deopt_id_after);
   } else {
     // Add deoptimization continuation point after the call and before the
     // arguments are removed.
@@ -1199,7 +1199,7 @@
   // deoptimization point in optimized code, after call.
   const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
   if (is_optimizing()) {
-    AddDeoptIndexAtCall(deopt_id_after, token_pos);
+    AddDeoptIndexAtCall(deopt_id_after);
   } else {
     // Add deoptimization continuation point after the call and before the
     // arguments are removed.
@@ -1222,7 +1222,7 @@
     // deoptimization point in optimized code, after call.
     const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
     if (is_optimizing()) {
-      AddDeoptIndexAtCall(deopt_id_after, token_pos);
+      AddDeoptIndexAtCall(deopt_id_after);
     } else {
       // Add deoptimization continuation point after the call and before the
       // arguments are removed.
@@ -1360,7 +1360,7 @@
   } else if (is_optimizing()) {
     AddCurrentDescriptor(RawPcDescriptors::kOther,
         Thread::kNoDeoptId, token_pos);
-    AddDeoptIndexAtCall(deopt_id_after, token_pos);
+    AddDeoptIndexAtCall(deopt_id_after);
   } else {
     AddCurrentDescriptor(RawPcDescriptors::kOther,
         Thread::kNoDeoptId, token_pos);
@@ -1394,7 +1394,7 @@
   RecordSafepoint(locs);
   const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
   if (is_optimizing()) {
-    AddDeoptIndexAtCall(deopt_id_after, token_pos);
+    AddDeoptIndexAtCall(deopt_id_after);
   } else {
     // Add deoptimization continuation point after the call and before the
     // arguments are removed.
diff --git a/runtime/vm/heap.cc b/runtime/vm/heap.cc
index fd22740..c3353d2 100644
--- a/runtime/vm/heap.cc
+++ b/runtime/vm/heap.cc
@@ -89,18 +89,18 @@
   // If we are in the process of running a sweep, wait for the sweeper to free
   // memory.
   Thread* thread = Thread::Current();
-  {
-    MonitorLocker ml(old_space_.tasks_lock());
-    addr = old_space_.TryAllocate(size, type);
-    while ((addr == 0) && (old_space_.tasks() > 0)) {
-      ml.WaitWithSafepointCheck(thread);
-      addr = old_space_.TryAllocate(size, type);
-    }
-  }
-  if (addr != 0) {
-    return addr;
-  }
   if (thread->CanCollectGarbage()) {
+    {
+      MonitorLocker ml(old_space_.tasks_lock());
+      addr = old_space_.TryAllocate(size, type);
+      while ((addr == 0) && (old_space_.tasks() > 0)) {
+        ml.WaitWithSafepointCheck(thread);
+        addr = old_space_.TryAllocate(size, type);
+      }
+    }
+    if (addr != 0) {
+      return addr;
+    }
     // All GC tasks finished without allocating successfully. Run a full GC.
     CollectAllGarbage();
     addr = old_space_.TryAllocate(size, type);
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index 3a5ab03..102f6b8 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -8,7 +8,6 @@
 #include "vm/allocation.h"
 #include "vm/ast.h"
 #include "vm/growable_array.h"
-#include "vm/handles_impl.h"
 #include "vm/locations.h"
 #include "vm/method_recognizer.h"
 #include "vm/object.h"
@@ -898,6 +897,7 @@
   friend class ComparisonInstr;
   friend class Scheduler;
   friend class BlockEntryInstr;
+  friend class CatchBlockEntryInstr;  // deopt_id_
 
   // Fetch deopt id without checking if this computation can deoptimize.
   intptr_t GetDeoptId() const {
@@ -1565,7 +1565,8 @@
                        intptr_t catch_try_index,
                        const LocalVariable& exception_var,
                        const LocalVariable& stacktrace_var,
-                       bool needs_stacktrace)
+                       bool needs_stacktrace,
+                       intptr_t deopt_id)
       : BlockEntryInstr(block_id, try_index),
         graph_entry_(graph_entry),
         predecessor_(NULL),
@@ -1573,7 +1574,9 @@
         catch_try_index_(catch_try_index),
         exception_var_(exception_var),
         stacktrace_var_(stacktrace_var),
-        needs_stacktrace_(needs_stacktrace) { }
+        needs_stacktrace_(needs_stacktrace) {
+    deopt_id_ = deopt_id;
+  }
 
   DECLARE_INSTRUCTION(CatchBlockEntry)
 
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index b4e27f0..9827a4d 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -13,6 +13,7 @@
 #include "vm/flow_graph.h"
 #include "vm/flow_graph_compiler.h"
 #include "vm/flow_graph_range_analysis.h"
+#include "vm/instructions.h"
 #include "vm/locations.h"
 #include "vm/object_store.h"
 #include "vm/parser.h"
@@ -232,7 +233,7 @@
   // deoptimization point in optimized code, after call.
   const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id());
   if (compiler->is_optimizing()) {
-    compiler->AddDeoptIndexAtCall(deopt_id_after, token_pos());
+    compiler->AddDeoptIndexAtCall(deopt_id_after);
   }
   // Add deoptimization continuation point after the call and before the
   // arguments are removed.
@@ -2836,16 +2837,30 @@
 
 
 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  // Ensure space for patching return sites for lazy deopt.
+  if (!FLAG_precompiled_mode && compiler->is_optimizing()) {
+    for (intptr_t i = 0;
+         i < CallPattern::DeoptCallPatternLengthInInstructions();
+         ++i) {
+      __ nop();
+    }
+  }
   __ Bind(compiler->GetJumpLabel(this));
   compiler->AddExceptionHandler(catch_try_index(),
                                 try_index(),
                                 compiler->assembler()->CodeSize(),
                                 catch_handler_types_,
                                 needs_stacktrace());
-  // Restore the pool pointer.
-  __ RestoreCodePointer();
-  __ LoadPoolPointer();
-
+  // On lazy deoptimization we patch the optimized code here to enter the
+  // deoptimization stub.
+  const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId());
+  if (compiler->is_optimizing()) {
+    compiler->AddDeoptIndexAtCall(deopt_id);
+  } else {
+    compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt,
+                                   deopt_id,
+                                   TokenPosition::kNoSource);
+  }
   if (HasParallelMove()) {
     compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
   }
diff --git a/runtime/vm/intermediate_language_arm64.cc b/runtime/vm/intermediate_language_arm64.cc
index b5f235f..af9f56d 100644
--- a/runtime/vm/intermediate_language_arm64.cc
+++ b/runtime/vm/intermediate_language_arm64.cc
@@ -12,6 +12,7 @@
 #include "vm/flow_graph.h"
 #include "vm/flow_graph_compiler.h"
 #include "vm/flow_graph_range_analysis.h"
+#include "vm/instructions.h"
 #include "vm/locations.h"
 #include "vm/object_store.h"
 #include "vm/parser.h"
@@ -229,7 +230,7 @@
   // deoptimization point in optimized code, after call.
   const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id());
   if (compiler->is_optimizing()) {
-    compiler->AddDeoptIndexAtCall(deopt_id_after, token_pos());
+    compiler->AddDeoptIndexAtCall(deopt_id_after);
   }
   // Add deoptimization continuation point after the call and before the
   // arguments are removed.
@@ -2553,17 +2554,30 @@
 
 
 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  // Ensure space for patching return sites for lazy deopt.
+  if (!FLAG_precompiled_mode && compiler->is_optimizing()) {
+    for (intptr_t i = 0;
+      i < CallPattern::kDeoptCallLengthInInstructions;
+      ++i) {
+      __ orr(R0, ZR, Operand(R0));  // nop
+    }
+  }
   __ Bind(compiler->GetJumpLabel(this));
   compiler->AddExceptionHandler(catch_try_index(),
                                 try_index(),
                                 compiler->assembler()->CodeSize(),
                                 catch_handler_types_,
                                 needs_stacktrace());
-
-  // Restore the pool pointer.
-  __ RestoreCodePointer();
-  __ LoadPoolPointer();
-
+  // On lazy deoptimization we patch the optimized code here to enter the
+  // deoptimization stub.
+  const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId());
+  if (compiler->is_optimizing()) {
+    compiler->AddDeoptIndexAtCall(deopt_id);
+  } else {
+    compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt,
+                                   deopt_id,
+                                   TokenPosition::kNoSource);
+  }
   if (HasParallelMove()) {
     compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
   }
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index 1595297..597fd43 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -12,6 +12,7 @@
 #include "vm/flow_graph.h"
 #include "vm/flow_graph_compiler.h"
 #include "vm/flow_graph_range_analysis.h"
+#include "vm/instructions.h"
 #include "vm/locations.h"
 #include "vm/object_store.h"
 #include "vm/parser.h"
@@ -2547,12 +2548,26 @@
 
 
 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  // Ensure space for patching return sites for lazy deopt.
+  if (!FLAG_precompiled_mode && compiler->is_optimizing()) {
+    __ nop(CallPattern::pattern_length_in_bytes());
+  }
   __ Bind(compiler->GetJumpLabel(this));
   compiler->AddExceptionHandler(catch_try_index(),
                                 try_index(),
                                 compiler->assembler()->CodeSize(),
                                 catch_handler_types_,
                                 needs_stacktrace());
+  // On lazy deoptimization we patch the optimized code here to enter the
+  // deoptimization stub.
+  const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId());
+  if (compiler->is_optimizing()) {
+    compiler->AddDeoptIndexAtCall(deopt_id);
+  } else {
+    compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt,
+                                   deopt_id,
+                                   TokenPosition::kNoSource);
+  }
   if (HasParallelMove()) {
     compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
   }
@@ -6784,7 +6799,7 @@
   // deoptimization point in optimized code, after call.
   const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id());
   if (compiler->is_optimizing()) {
-    compiler->AddDeoptIndexAtCall(deopt_id_after, token_pos());
+    compiler->AddDeoptIndexAtCall(deopt_id_after);
   }
   // Add deoptimization continuation point after the call and before the
   // arguments are removed.
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index f583fa1..6ec28cc 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -12,6 +12,7 @@
 #include "vm/flow_graph.h"
 #include "vm/flow_graph_compiler.h"
 #include "vm/flow_graph_range_analysis.h"
+#include "vm/instructions.h"
 #include "vm/locations.h"
 #include "vm/object_store.h"
 #include "vm/parser.h"
@@ -278,7 +279,7 @@
   // deoptimization point in optimized code, after call.
   const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id());
   if (compiler->is_optimizing()) {
-    compiler->AddDeoptIndexAtCall(deopt_id_after, token_pos());
+    compiler->AddDeoptIndexAtCall(deopt_id_after);
   }
   // Add deoptimization continuation point after the call and before the
   // arguments are removed.
@@ -2667,20 +2668,33 @@
 
 
 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  // Ensure space for patching return sites for lazy deopt.
+  if (!FLAG_precompiled_mode && compiler->is_optimizing()) {
+    for (intptr_t i = 0;
+      i < CallPattern::kDeoptCallLengthInInstructions;
+      ++i) {
+      __ nop();
+    }
+  }
   __ Bind(compiler->GetJumpLabel(this));
   compiler->AddExceptionHandler(catch_try_index(),
                                 try_index(),
                                 compiler->assembler()->CodeSize(),
                                 catch_handler_types_,
                                 needs_stacktrace());
-  // Restore pool pointer.
-  __ RestoreCodePointer();
-  __ LoadPoolPointer();
-
+  // On lazy deoptimization we patch the optimized code here to enter the
+  // deoptimization stub.
+  const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId());
+  if (compiler->is_optimizing()) {
+    compiler->AddDeoptIndexAtCall(deopt_id);
+  } else {
+    compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt,
+                                   deopt_id,
+                                   TokenPosition::kNoSource);
+  }
   if (HasParallelMove()) {
     compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
   }
-
   // Restore SP from FP as we are coming from a throw and the code for
   // popping arguments has not been run.
   const intptr_t fp_sp_dist =
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index b4eefbf..b8a57bb 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -12,6 +12,7 @@
 #include "vm/flow_graph.h"
 #include "vm/flow_graph_compiler.h"
 #include "vm/flow_graph_range_analysis.h"
+#include "vm/instructions.h"
 #include "vm/locations.h"
 #include "vm/object_store.h"
 #include "vm/parser.h"
@@ -2563,17 +2564,26 @@
 
 
 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  // Ensure space for patching return sites for lazy deopt.
+  if (!FLAG_precompiled_mode && compiler->is_optimizing()) {
+    __ nop(ShortCallPattern::pattern_length_in_bytes());
+  }
   __ Bind(compiler->GetJumpLabel(this));
   compiler->AddExceptionHandler(catch_try_index(),
                                 try_index(),
                                 compiler->assembler()->CodeSize(),
                                 catch_handler_types_,
                                 needs_stacktrace());
-
-  // Restore the pool pointer.
-  __ RestoreCodePointer();
-  __ LoadPoolPointer(PP);
-
+  // On lazy deoptimization we patch the optimized code here to enter the
+  // deoptimization stub.
+  const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId());
+  if (compiler->is_optimizing()) {
+    compiler->AddDeoptIndexAtCall(deopt_id);
+  } else {
+    compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt,
+                                   deopt_id,
+                                   TokenPosition::kNoSource);
+  }
   if (HasParallelMove()) {
     compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
   }
@@ -6507,7 +6517,7 @@
   // deoptimization point in optimized code, after call.
   const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id());
   if (compiler->is_optimizing()) {
-    compiler->AddDeoptIndexAtCall(deopt_id_after, token_pos());
+    compiler->AddDeoptIndexAtCall(deopt_id_after);
   }
   // Add deoptimization continuation point after the call and before the
   // arguments are removed.
diff --git a/runtime/vm/megamorphic_cache_table.cc b/runtime/vm/megamorphic_cache_table.cc
index 1fdd8e2..e3d34dd 100644
--- a/runtime/vm/megamorphic_cache_table.cc
+++ b/runtime/vm/megamorphic_cache_table.cc
@@ -5,7 +5,6 @@
 #include "vm/megamorphic_cache_table.h"
 
 #include <stdlib.h>
-#include "vm/handles_impl.h"
 #include "vm/object.h"
 #include "vm/object_store.h"
 #include "vm/stub_code.h"
diff --git a/runtime/vm/native_api_impl.cc b/runtime/vm/native_api_impl.cc
index 7abd52e..48d9289 100644
--- a/runtime/vm/native_api_impl.cc
+++ b/runtime/vm/native_api_impl.cc
@@ -129,4 +129,28 @@
   return result;
 }
 
+
+static void ParseAll(Thread* thread, Dart_Handle* result) {
+  ASSERT(thread != NULL);
+  const Error& error = Error::Handle(thread->zone(),
+                                     Library::ParseAll(thread));
+  if (error.IsNull()) {
+    *result = Api::Success();
+  } else {
+    *result = Api::NewHandle(thread, error.raw());
+  }
+}
+
+
+DART_EXPORT Dart_Handle Dart_ParseAll() {
+  DARTSCOPE(Thread::Current());
+  Dart_Handle result = Api::CheckAndFinalizePendingClasses(T);
+  if (::Dart_IsError(result)) {
+    return result;
+  }
+  CHECK_CALLBACK_STATE(T);
+  ParseAll(T, &result);
+  return result;
+}
+
 }  // namespace dart
diff --git a/runtime/vm/native_arguments.h b/runtime/vm/native_arguments.h
index 7035a50..77c67ed 100644
--- a/runtime/vm/native_arguments.h
+++ b/runtime/vm/native_arguments.h
@@ -8,7 +8,6 @@
 #include "platform/assert.h"
 #include "platform/memory_sanitizer.h"
 #include "vm/globals.h"
-#include "vm/handles_impl.h"
 #include "vm/simulator.h"
 #include "vm/stub_code.h"
 
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 2456ed6..a368c52 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -153,6 +153,7 @@
 RawClass* Object::context_scope_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::singletargetcache_class_ =
     reinterpret_cast<RawClass*>(RAW_NULL);
+RawClass* Object::unlinkedcall_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::icdata_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::megamorphic_cache_class_ =
     reinterpret_cast<RawClass*>(RAW_NULL);
@@ -656,6 +657,9 @@
   cls = Class::New<SingleTargetCache>();
   singletargetcache_class_ = cls.raw();
 
+  cls = Class::New<UnlinkedCall>();
+  unlinkedcall_class_ = cls.raw();
+
   cls = Class::New<ICData>();
   icdata_class_ = cls.raw();
 
@@ -998,6 +1002,7 @@
   SET_CLASS_NAME(context, Context);
   SET_CLASS_NAME(context_scope, ContextScope);
   SET_CLASS_NAME(singletargetcache, SingleTargetCache);
+  SET_CLASS_NAME(unlinkedcall, UnlinkedCall);
   SET_CLASS_NAME(icdata, ICData);
   SET_CLASS_NAME(megamorphic_cache, MegamorphicCache);
   SET_CLASS_NAME(subtypetestcache, SubtypeTestCache);
@@ -5977,13 +5982,13 @@
 
 
 bool Function::IsOptimizable() const {
+  if (FLAG_precompiled_mode) {
+    return true;
+  }
   if (is_native()) {
     // Native methods don't need to be optimized.
     return false;
   }
-  if (FLAG_precompiled_mode) {
-    return true;
-  }
   const intptr_t function_length = end_token_pos().Pos() - token_pos().Pos();
   if (is_optimizable() && (script() != Script::null()) &&
       (function_length < FLAG_huge_method_cutoff_in_tokens)) {
@@ -10478,6 +10483,9 @@
   ASSERT(thread->IsMutatorThread());
   // Force the url to have a hash code.
   url.Hash();
+  const bool dart_scheme = url.StartsWith(Symbols::DartScheme());
+  const bool dart_private_scheme =
+      dart_scheme && url.StartsWith(Symbols::DartSchemePrivate());
   const Library& result = Library::Handle(zone, Library::New());
   result.StorePointer(&result.raw_ptr()->name_, Symbols::Empty().raw());
   result.StorePointer(&result.raw_ptr()->url_, url.raw());
@@ -10501,8 +10509,8 @@
   result.set_native_entry_symbol_resolver(NULL);
   result.set_is_in_fullsnapshot(false);
   result.StoreNonPointer(&result.raw_ptr()->corelib_imported_, true);
-  result.set_debuggable(false);
-  result.set_is_dart_scheme(url.StartsWith(Symbols::DartScheme()));
+  result.set_debuggable(!dart_private_scheme);
+  result.set_is_dart_scheme(dart_scheme);
   result.StoreNonPointer(&result.raw_ptr()->load_state_,
                          RawLibrary::kAllocated);
   result.StoreNonPointer(&result.raw_ptr()->index_, -1);
@@ -11414,6 +11422,51 @@
 }
 
 
+RawError* Library::ParseAll(Thread* thread) {
+  Zone* zone = thread->zone();
+  Error& error = Error::Handle(zone);
+  Isolate* isolate = thread->isolate();
+  const GrowableObjectArray& libs = GrowableObjectArray::Handle(
+      isolate->object_store()->libraries());
+  Library& lib = Library::Handle(zone);
+  Class& cls = Class::Handle(zone);
+  for (int i = 0; i < libs.Length(); i++) {
+    lib ^= libs.At(i);
+    ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
+    while (it.HasNext()) {
+      cls = it.GetNextClass();
+      error = cls.EnsureIsFinalized(thread);
+      if (!error.IsNull()) {
+        return error.raw();
+      }
+      error = Compiler::ParseAllFunctions(cls);
+      if (!error.IsNull()) {
+        return error.raw();
+      }
+    }
+  }
+
+  // Inner functions get added to the closures array. As part of compilation
+  // more closures can be added to the end of the array. Compile all the
+  // closures until we have reached the end of the "worklist".
+  const GrowableObjectArray& closures = GrowableObjectArray::Handle(zone,
+      Isolate::Current()->object_store()->closure_functions());
+  Function& func = Function::Handle(zone);
+  for (int i = 0; i < closures.Length(); i++) {
+    func ^= closures.At(i);
+    if (!func.HasCode()) {
+      error = Compiler::ParseFunction(thread, func);
+      if (!error.IsNull()) {
+        return error.raw();
+      }
+      func.ClearICDataArray();
+      func.ClearCode();
+    }
+  }
+  return error.raw();
+}
+
+
 // Return Function::null() if function does not exist in libs.
 RawFunction* Library::GetFunction(const GrowableArray<Library*>& libs,
                                   const char* class_name,
@@ -12600,6 +12653,29 @@
 }
 
 
+void UnlinkedCall::set_target_name(const String& value) const {
+  StorePointer(&raw_ptr()->target_name_, value.raw());
+}
+
+
+void UnlinkedCall::set_args_descriptor(const Array& value) const {
+  StorePointer(&raw_ptr()->args_descriptor_, value.raw());
+}
+
+
+const char* UnlinkedCall::ToCString() const {
+  return "UnlinkedCall";
+}
+
+
+RawUnlinkedCall* UnlinkedCall::New() {
+  RawObject* raw = Object::Allocate(UnlinkedCall::kClassId,
+                                    UnlinkedCall::InstanceSize(),
+                                    Heap::kOld);
+  return reinterpret_cast<RawUnlinkedCall*>(raw);
+}
+
+
 void ICData::ResetSwitchable(Zone* zone) const {
   ASSERT(NumArgsTested() == 1);
   set_ic_data_array(Array::Handle(zone, CachedEmptyICDataArray(1)));
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index f0074a51f..fbc72e2 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -542,6 +542,7 @@
   static RawClass* singletargetcache_class() {
     return singletargetcache_class_;
   }
+  static RawClass* unlinkedcall_class() { return unlinkedcall_class_; }
   static RawClass* icdata_class() { return icdata_class_; }
   static RawClass* megamorphic_cache_class() {
     return megamorphic_cache_class_;
@@ -794,6 +795,7 @@
   static RawClass* context_class_;  // Class of the Context vm object.
   static RawClass* context_scope_class_;  // Class of ContextScope vm object.
   static RawClass* singletargetcache_class_;  // Class of SingleTargetCache.
+  static RawClass* unlinkedcall_class_;  // Class of UnlinkedCall.
   static RawClass* icdata_class_;  // Class of ICData.
   static RawClass* megamorphic_cache_class_;  // Class of MegamorphiCache.
   static RawClass* subtypetestcache_class_;  // Class of SubtypeTestCache.
@@ -1858,6 +1860,25 @@
 };
 
 
+class UnlinkedCall : public Object {
+ public:
+  RawString* target_name() const { return raw_ptr()->target_name_; }
+  void set_target_name(const String& target_name) const;
+  RawArray* args_descriptor() const { return raw_ptr()->args_descriptor_; }
+  void set_args_descriptor(const Array& args_descriptor) const;
+
+  static intptr_t InstanceSize() {
+    return RoundedAllocationSize(sizeof(RawUnlinkedCall));
+  }
+
+  static RawUnlinkedCall* New();
+
+ private:
+  FINAL_HEAP_OBJECT_IMPLEMENTATION(UnlinkedCall, Object);
+  friend class Class;
+};
+
+
 // Object holding information about an IC: test classes and their
 // corresponding targets. The owner of the ICData can be either the function
 // or the original ICData object. In case of background compilation we
@@ -3858,6 +3879,7 @@
 
   // Eagerly compile all classes and functions in the library.
   static RawError* CompileAll();
+  static RawError* ParseAll(Thread* thread);
 
 #if defined(DART_NO_SNAPSHOT)
   // Checks function fingerprints. Prints mismatches and aborts if
diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc
index dd15a1f..f3b06e0 100644
--- a/runtime/vm/object_reload.cc
+++ b/runtime/vm/object_reload.cc
@@ -392,6 +392,9 @@
         old_closure = old_func.ImplicitStaticClosure();
         new_func = new_func.ImplicitClosureFunction();
         new_closure = new_func.ImplicitStaticClosure();
+        if (old_closure.IsCanonical()) {
+          new_closure.SetCanonical();
+        }
         irc->AddBecomeMapping(old_closure, new_closure);
       }
     }
diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc
index fc95622..bb0bb26 100644
--- a/runtime/vm/object_service.cc
+++ b/runtime/vm/object_service.cc
@@ -754,6 +754,11 @@
 }
 
 
+void UnlinkedCall::PrintJSONImpl(JSONStream* stream, bool ref) const {
+  Object::PrintJSONImpl(stream, ref);
+}
+
+
 void ICData::PrintJSONImpl(JSONStream* stream, bool ref) const {
   JSONObject jsobj(stream);
   AddCommonObjectProperties(&jsobj, "Object", ref);
diff --git a/runtime/vm/pages.cc b/runtime/vm/pages.cc
index 80527f2..f2bbdf2 100644
--- a/runtime/vm/pages.cc
+++ b/runtime/vm/pages.cc
@@ -1153,39 +1153,70 @@
     SpaceUsage before, SpaceUsage after, int64_t start, int64_t end) {
   ASSERT(end >= start);
   history_.AddGarbageCollectionTime(start, end);
-  int gc_time_fraction = history_.GarbageCollectionTimeFraction();
+  const int gc_time_fraction = history_.GarbageCollectionTimeFraction();
   heap_->RecordData(PageSpace::kGCTimeFraction, gc_time_fraction);
 
   // Assume garbage increases linearly with allocation:
   // G = kA, and estimate k from the previous cycle.
-  intptr_t allocated_since_previous_gc =
+  const intptr_t allocated_since_previous_gc =
       before.used_in_words - last_usage_.used_in_words;
-  intptr_t garbage = before.used_in_words - after.used_in_words;
-  double k = garbage / static_cast<double>(allocated_since_previous_gc);
-  heap_->RecordData(PageSpace::kGarbageRatio, static_cast<int>(k * 100));
+  if (allocated_since_previous_gc > 0) {
+    const intptr_t garbage = before.used_in_words - after.used_in_words;
+    ASSERT(garbage >= 0);
+    const double k = garbage / static_cast<double>(allocated_since_previous_gc);
+    const int garbage_ratio = static_cast<int>(k * 100);
+    heap_->RecordData(PageSpace::kGarbageRatio, garbage_ratio);
 
-  // Define GC to be 'worthwhile' iff at least fraction t of heap is garbage.
-  double t = 1.0 - desired_utilization_;
-  // If we spend too much time in GC, strive for even more free space.
-  if (gc_time_fraction > garbage_collection_time_ratio_) {
-    t += (gc_time_fraction - garbage_collection_time_ratio_) / 100.0;
-  }
-
-  // Find minimum 'grow_heap_' such that after increasing capacity by
-  // 'grow_heap_' pages and filling them, we expect a GC to be worthwhile.
-  for (grow_heap_ = 0; grow_heap_ < heap_growth_max_; ++grow_heap_) {
-    intptr_t limit =
-        after.capacity_in_words + (grow_heap_ * PageSpace::kPageSizeInWords);
-    intptr_t allocated_before_next_gc = limit - after.used_in_words;
-    double estimated_garbage = k * allocated_before_next_gc;
-    if (t <= estimated_garbage / limit) {
-      break;
+    // Define GC to be 'worthwhile' iff at least fraction t of heap is garbage.
+    double t = 1.0 - desired_utilization_;
+    // If we spend too much time in GC, strive for even more free space.
+    if (gc_time_fraction > garbage_collection_time_ratio_) {
+      t += (gc_time_fraction - garbage_collection_time_ratio_) / 100.0;
     }
+
+    const intptr_t grow_ratio = (
+        static_cast<intptr_t>(after.capacity_in_words / desired_utilization_) -
+        after.capacity_in_words) / PageSpace::kPageSizeInWords;
+    if (garbage_ratio == 0) {
+      // No garbage in the previous cycle so it would be hard to compute a
+      // grow_heap_ size based on estimated garbage so we use growth ratio
+      // heuristics instead.
+      grow_heap_ = Utils::Maximum(static_cast<intptr_t>(heap_growth_max_),
+                                  grow_ratio);
+    } else {
+      // Find minimum 'grow_heap_' such that after increasing capacity by
+      // 'grow_heap_' pages and filling them, we expect a GC to be worthwhile.
+      intptr_t max = heap_growth_max_;
+      intptr_t min = 0;
+      intptr_t local_grow_heap = 0;
+      while (min < max) {
+        local_grow_heap = (max + min) / 2;
+        const intptr_t limit = after.capacity_in_words +
+            (grow_heap_ * PageSpace::kPageSizeInWords);
+        const intptr_t allocated_before_next_gc = limit - after.used_in_words;
+        const double estimated_garbage = k * allocated_before_next_gc;
+        if (t <= estimated_garbage / limit) {
+          max = local_grow_heap - 1;
+        } else {
+          min = local_grow_heap + 1;
+        }
+      }
+      grow_heap_ = local_grow_heap;
+      ASSERT(grow_heap_ >= 0);
+      // If we are going to grow by heap_grow_max_ then ensure that we
+      // will be growing the heap at least by the growth ratio heuristics.
+      if ((grow_heap_ == heap_growth_max_) && (grow_ratio > grow_heap_)) {
+        grow_heap_ = grow_ratio;
+      }
+    }
+  } else {
+    heap_->RecordData(PageSpace::kGarbageRatio, 100);
+    grow_heap_ = 0;
   }
   heap_->RecordData(PageSpace::kPageGrowth, grow_heap_);
 
   // Limit shrinkage: allow growth by at least half the pages freed by GC.
-  intptr_t freed_pages =
+  const intptr_t freed_pages =
       (before.capacity_in_words - after.capacity_in_words) /
       PageSpace::kPageSizeInWords;
   grow_heap_ = Utils::Maximum(grow_heap_, freed_pages / 2);
diff --git a/runtime/vm/pages.h b/runtime/vm/pages.h
index 640e771..06e3ab5 100644
--- a/runtime/vm/pages.h
+++ b/runtime/vm/pages.h
@@ -412,8 +412,13 @@
       // Unlimited.
       return true;
     }
-    ASSERT(CapacityInWords() <= max_capacity_in_words_);
-    return increase_in_words <= (max_capacity_in_words_ - CapacityInWords());
+    // TODO(issue 27413): Make the check against capacity and the bump
+    // of capacity atomic so that CapacityInWords does not exceed
+    // max_capacity_in_words_.
+    intptr_t free_capacity_in_words =
+        (max_capacity_in_words_ - CapacityInWords());
+    return ((free_capacity_in_words > 0) &&
+            (increase_in_words <= free_capacity_in_words));
   }
 
   FreeList freelist_[HeapPage::kNumPageTypes];
diff --git a/runtime/vm/parser_test.cc b/runtime/vm/parser_test.cc
index 319b13d..14fae8e 100644
--- a/runtime/vm/parser_test.cc
+++ b/runtime/vm/parser_test.cc
@@ -40,7 +40,8 @@
     EXPECT(parsed_function->node_sequence() != NULL);
     printf("Class %s function %s:\n", cname, fname);
     if (FLAG_support_ast_printer) {
-      AstPrinter::PrintFunctionNodes(*parsed_function);
+      AstPrinter ast_printer;
+      ast_printer.PrintFunctionNodes(*parsed_function);
     } else {
       OS::Print("AST printer not supported.");
     }
diff --git a/runtime/vm/precompiler.cc b/runtime/vm/precompiler.cc
index 2981e17d..d55a6f1 100644
--- a/runtime/vm/precompiler.cc
+++ b/runtime/vm/precompiler.cc
@@ -1197,7 +1197,8 @@
     Thread* const thread = Thread::Current();
     if (FLAG_support_ast_printer && FLAG_trace_compiler) {
       THR_Print("compiling expression: ");
-      AstPrinter::PrintNode(fragment);
+      AstPrinter ast_printer;
+      ast_printer.PrintNode(fragment);
     }
 
     // Create a dummy function object for the code generator.
@@ -2112,7 +2113,11 @@
         pool_(ObjectPool::Handle(zone)),
         entry_(Object::Handle(zone)),
         ic_(ICData::Handle(zone)),
-        target_code_(Code::Handle(zone)) {
+        target_name_(String::Handle(zone)),
+        args_descriptor_(Array::Handle(zone)),
+        unlinked_(UnlinkedCall::Handle(zone)),
+        target_code_(Code::Handle(zone)),
+        canonical_unlinked_calls_() {
     }
 
     void Visit(const Function& function) {
@@ -2130,21 +2135,45 @@
           // calls.
           ic_ ^= entry_.raw();
           ic_.ResetSwitchable(zone_);
+
+          unlinked_ = UnlinkedCall::New();
+          target_name_ = ic_.target_name();
+          unlinked_.set_target_name(target_name_);
+          args_descriptor_ = ic_.arguments_descriptor();
+          unlinked_.set_args_descriptor(args_descriptor_);
+          unlinked_ = DedupUnlinkedCall(unlinked_);
+          pool_.SetObjectAt(i, unlinked_);
         } else if (entry_.raw() ==
                    StubCode::ICCallThroughFunction_entry()->code()) {
-          target_code_ = StubCode::ICCallThroughCode_entry()->code();
+          target_code_ = StubCode::UnlinkedCall_entry()->code();
           pool_.SetObjectAt(i, target_code_);
         }
       }
     }
 
+    RawUnlinkedCall* DedupUnlinkedCall(const UnlinkedCall& unlinked) {
+      const UnlinkedCall* canonical_unlinked =
+          canonical_unlinked_calls_.LookupValue(&unlinked);
+      if (canonical_unlinked == NULL) {
+        canonical_unlinked_calls_.Insert(
+            &UnlinkedCall::ZoneHandle(zone_, unlinked.raw()));
+        return unlinked.raw();
+      } else {
+        return canonical_unlinked->raw();
+      }
+    }
+
    private:
     Zone* zone_;
     Code& code_;
     ObjectPool& pool_;
     Object& entry_;
     ICData& ic_;
+    String& target_name_;
+    Array& args_descriptor_;
+    UnlinkedCall& unlinked_;
     Code& target_code_;
+    UnlinkedCallSet canonical_unlinked_calls_;
   };
 
   ASSERT(!I->compilation_allowed());
diff --git a/runtime/vm/precompiler.h b/runtime/vm/precompiler.h
index 67c54e1..90b5f82 100644
--- a/runtime/vm/precompiler.h
+++ b/runtime/vm/precompiler.h
@@ -157,6 +157,30 @@
 typedef DirectChainedHashMap<InstructionsKeyValueTrait> InstructionsSet;
 
 
+class UnlinkedCallKeyValueTrait {
+ public:
+  // Typedefs needed for the DirectChainedHashMap template.
+  typedef const UnlinkedCall* Key;
+  typedef const UnlinkedCall* Value;
+  typedef const UnlinkedCall* Pair;
+
+  static Key KeyOf(Pair kv) { return kv; }
+
+  static Value ValueOf(Pair kv) { return kv; }
+
+  static inline intptr_t Hashcode(Key key) {
+    return String::Handle(key->target_name()).Hash();
+  }
+
+  static inline bool IsKeyEqual(Pair pair, Key key) {
+    return (pair->target_name() == key->target_name()) &&
+        (pair->args_descriptor() == key->args_descriptor());
+  }
+};
+
+typedef DirectChainedHashMap<UnlinkedCallKeyValueTrait> UnlinkedCallSet;
+
+
 class FunctionKeyValueTrait {
  public:
   // Typedefs needed for the DirectChainedHashMap template.
diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc
index d5ffcb9..1a80017 100644
--- a/runtime/vm/profiler_service.cc
+++ b/runtime/vm/profiler_service.cc
@@ -5,7 +5,6 @@
 #include "vm/profiler_service.h"
 
 #include "vm/growable_array.h"
-#include "vm/handles_impl.h"
 #include "vm/hash_map.h"
 #include "vm/log.h"
 #include "vm/native_symbol.h"
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index 991b2e0..d777f68 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -646,6 +646,13 @@
 }
 
 
+intptr_t RawUnlinkedCall::VisitUnlinkedCallPointers(
+    RawUnlinkedCall* raw_obj, ObjectPointerVisitor* visitor) {
+  visitor->VisitPointers(raw_obj->from(), raw_obj->to());
+  return UnlinkedCall::InstanceSize();
+}
+
+
 intptr_t RawICData::VisitICDataPointers(RawICData* raw_obj,
                                         ObjectPointerVisitor* visitor) {
   visitor->VisitPointers(raw_obj->from(), raw_obj->to());
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 9e40136..66b2d4c 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -40,6 +40,7 @@
   V(Context)                                                                   \
   V(ContextScope)                                                              \
   V(SingleTargetCache)                                                         \
+  V(UnlinkedCall)                                                              \
   V(ICData)                                                                    \
   V(MegamorphicCache)                                                          \
   V(SubtypeTestCache)                                                          \
@@ -1509,6 +1510,19 @@
 };
 
 
+class RawUnlinkedCall : public RawObject {
+  RAW_HEAP_OBJECT_IMPLEMENTATION(UnlinkedCall);
+  RawObject** from() {
+    return reinterpret_cast<RawObject**>(&ptr()->target_name_);
+  }
+  RawString* target_name_;
+  RawArray* args_descriptor_;
+  RawObject** to() {
+    return reinterpret_cast<RawObject**>(&ptr()->args_descriptor_);
+  }
+};
+
+
 class RawICData : public RawObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(ICData);
 
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 7829e95..f345a19 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -1543,6 +1543,24 @@
 }
 
 
+RawUnlinkedCall* UnlinkedCall::ReadFrom(SnapshotReader* reader,
+                                        intptr_t object_id,
+                                        intptr_t tags,
+                                        Snapshot::Kind kind,
+                                        bool as_reference) {
+  UNREACHABLE();
+  return UnlinkedCall::null();
+}
+
+
+void RawUnlinkedCall::WriteTo(SnapshotWriter* writer,
+                              intptr_t object_id,
+                              Snapshot::Kind kind,
+                              bool as_reference) {
+  UNREACHABLE();
+}
+
+
 RawICData* ICData::ReadFrom(SnapshotReader* reader,
                             intptr_t object_id,
                             intptr_t tags,
diff --git a/runtime/vm/runtime_entry_list.h b/runtime/vm/runtime_entry_list.h
index f816769..9564146 100644
--- a/runtime/vm/runtime_entry_list.h
+++ b/runtime/vm/runtime_entry_list.h
@@ -46,6 +46,7 @@
   V(CompileFunction)                                                           \
   V(MonomorphicMiss)                                                           \
   V(SingleTargetMiss)                                                          \
+  V(UnlinkedCall)                                                              \
 
 #define LEAF_RUNTIME_ENTRY_LIST(V)                                             \
   V(void, PrintStopMessage, const char*)                                       \
diff --git a/runtime/vm/scanner.cc b/runtime/vm/scanner.cc
index f7ae4ac..cd8abf5 100644
--- a/runtime/vm/scanner.cc
+++ b/runtime/vm/scanner.cc
@@ -484,9 +484,7 @@
       }
     }
   }
-  if (is_valid &&
-      ((Utf::IsOutOfRange(*code_point) ||
-        (Utf16::IsSurrogate(*code_point))))) {
+  if (is_valid && (Utf::IsOutOfRange(*code_point))) {
     ErrorMsg("invalid code point");
   }
 }
diff --git a/runtime/vm/scanner_test.cc b/runtime/vm/scanner_test.cc
index 3d8d70c..b6d4d23 100644
--- a/runtime/vm/scanner_test.cc
+++ b/runtime/vm/scanner_test.cc
@@ -192,62 +192,6 @@
 
 
 static void InvalidStringEscapes() {
-  const GrowableTokenStream& high_start_4 =
-      Scan("\"\\uD800\"");
-  EXPECT_EQ(2, high_start_4.length());
-  CheckKind(high_start_4, 0, Token::kERROR);
-  EXPECT(high_start_4[0].literal->Equals("invalid code point"));
-  CheckKind(high_start_4, 1, Token::kEOS);
-
-  const GrowableTokenStream& high_start_seq =
-      Scan("\"\\u{D800}\"");
-  EXPECT_EQ(2, high_start_seq.length());
-  CheckKind(high_start_seq, 0, Token::kERROR);
-  EXPECT(high_start_seq[0].literal->Equals("invalid code point"));
-  CheckKind(high_start_seq, 1, Token::kEOS);
-
-  const GrowableTokenStream& high_end_4 =
-      Scan("\"\\uDBFF\"");
-  EXPECT_EQ(2, high_end_4.length());
-  CheckKind(high_end_4, 0, Token::kERROR);
-  EXPECT(high_end_4[0].literal->Equals("invalid code point"));
-  CheckKind(high_end_4, 1, Token::kEOS);
-
-  const GrowableTokenStream& high_end_seq =
-      Scan("\"\\u{DBFF}\"");
-  EXPECT_EQ(2, high_end_seq.length());
-  CheckKind(high_end_seq, 0, Token::kERROR);
-  EXPECT(high_end_seq[0].literal->Equals("invalid code point"));
-  CheckKind(high_end_seq, 1, Token::kEOS);
-
-  const GrowableTokenStream& low_start_4 =
-      Scan("\"\\uDC00\"");
-  EXPECT_EQ(2, low_start_4.length());
-  CheckKind(low_start_4, 0, Token::kERROR);
-  EXPECT(low_start_4[0].literal->Equals("invalid code point"));
-  CheckKind(low_start_4, 1, Token::kEOS);
-
-  const GrowableTokenStream& low_start_seq =
-      Scan("\"\\u{DC00}\"");
-  EXPECT_EQ(2, low_start_seq.length());
-  CheckKind(low_start_seq, 0, Token::kERROR);
-  EXPECT(low_start_seq[0].literal->Equals("invalid code point"));
-  CheckKind(low_start_seq, 1, Token::kEOS);
-
-  const GrowableTokenStream& low_end_4 =
-      Scan("\"\\uDFFF\"");
-  EXPECT_EQ(2, low_end_4.length());
-  CheckKind(low_end_4, 0, Token::kERROR);
-  EXPECT(low_end_4[0].literal->Equals("invalid code point"));
-  CheckKind(low_end_4, 1, Token::kEOS);
-
-  const GrowableTokenStream& low_end_seq =
-      Scan("\"\\u{DFFF}\"");
-  EXPECT_EQ(2, low_end_seq.length());
-  CheckKind(low_end_seq, 0, Token::kERROR);
-  EXPECT(low_end_seq[0].literal->Equals("invalid code point"));
-  CheckKind(low_end_seq, 1, Token::kEOS);
-
   const GrowableTokenStream& out_of_range_low =
       Scan("\"\\u{110000}\"");
   EXPECT_EQ(2, out_of_range_low.length());
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index d35f0e1..efc5c24 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -241,6 +241,14 @@
 }
 
 
+static void PrintIllegalParamError(JSONStream* js,
+                                   const char* param) {
+  js->PrintError(kInvalidParams,
+                 "%s: illegal '%s' parameter: %s",
+                 js->method(), param, js->LookupParam(param));
+}
+
+
 static void PrintUnrecognizedMethodError(JSONStream* js) {
   js->PrintError(kMethodNotFound, NULL);
 }
@@ -3977,6 +3985,13 @@
       BoolParameter::Parse(js->LookupParam("isDebuggable"), false);
   if (obj.IsLibrary()) {
     const Library& lib = Library::Cast(obj);
+    if (lib.is_dart_scheme()) {
+      const String& url = String::Handle(lib.url());
+      if (url.StartsWith(Symbols::DartSchemePrivate())) {
+        PrintIllegalParamError(js, "libraryId");
+        return true;
+      }
+    }
     lib.set_debuggable(is_debuggable);
     PrintSuccess(js);
     return true;
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index 3077c8b6..9c3e3cf 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -3906,6 +3906,13 @@
   ASSERT(raw_exception != Object::null());
   set_register(kExceptionObjectReg, bit_cast<int32_t>(raw_exception));
   set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace));
+  // Restore pool pointer.
+  int32_t code = *reinterpret_cast<int32_t*>(
+      fp + kPcMarkerSlotFromFp * kWordSize);
+  int32_t pp = *reinterpret_cast<int32_t*>(
+      code + Code::object_pool_offset() - kHeapObjectTag);
+  set_register(CODE_REG, code);
+  set_register(PP, pp);
   buf->Longjmp();
 }
 
diff --git a/runtime/vm/simulator_arm64.cc b/runtime/vm/simulator_arm64.cc
index 610b857..0cfcb2a 100644
--- a/runtime/vm/simulator_arm64.cc
+++ b/runtime/vm/simulator_arm64.cc
@@ -3604,6 +3604,14 @@
   ASSERT(raw_exception != Object::null());
   set_register(NULL, kExceptionObjectReg, bit_cast<int64_t>(raw_exception));
   set_register(NULL, kStackTraceObjectReg, bit_cast<int64_t>(raw_stacktrace));
+  // Restore pool pointer.
+  int64_t code = *reinterpret_cast<int64_t*>(
+      fp + kPcMarkerSlotFromFp * kWordSize);
+  int64_t pp = *reinterpret_cast<int64_t*>(
+      code + Code::object_pool_offset() - kHeapObjectTag);
+  pp -= kHeapObjectTag;  // In the PP register, the pool pointer is untagged.
+  set_register(NULL, CODE_REG, code);
+  set_register(NULL, PP, pp);
   buf->Longjmp();
 }
 
diff --git a/runtime/vm/simulator_mips.cc b/runtime/vm/simulator_mips.cc
index eb03c49..f42b3fa 100644
--- a/runtime/vm/simulator_mips.cc
+++ b/runtime/vm/simulator_mips.cc
@@ -2530,6 +2530,13 @@
   ASSERT(raw_exception != Object::null());
   set_register(kExceptionObjectReg, bit_cast<int32_t>(raw_exception));
   set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace));
+  // Restore pool pointer.
+  int32_t code = *reinterpret_cast<int32_t*>(
+      fp + kPcMarkerSlotFromFp * kWordSize);
+  int32_t pp = *reinterpret_cast<int32_t*>(
+      code + Code::object_pool_offset() - kHeapObjectTag);
+  set_register(CODE_REG, code);
+  set_register(PP, pp);
   buf->Longjmp();
 }
 
diff --git a/runtime/vm/stub_code.h b/runtime/vm/stub_code.h
index e961342..c179cac 100644
--- a/runtime/vm/stub_code.h
+++ b/runtime/vm/stub_code.h
@@ -37,6 +37,7 @@
   V(OptimizeFunction)                                                          \
   V(InvokeDartCode)                                                            \
   V(DebugStepCheck)                                                            \
+  V(UnlinkedCall)                                                              \
   V(MonomorphicMiss)                                                           \
   V(SingleTargetCall)                                                          \
   V(ICCallThroughFunction)                                                     \
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index 82c50a1..c000508 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -286,7 +286,7 @@
   // calling into the runtime.
   __ EnterStubFrame();
   // Setup space on stack for return value and preserve arguments descriptor.
-  __ LoadObject(R0, Object::null_object());
+  __ LoadImmediate(R0, 0);
   __ PushList((1 << R0) | (1 << R4));
   __ CallRuntime(kPatchStaticCallRuntimeEntry, 0);
   // Get Code object result and restore arguments descriptor array.
@@ -312,7 +312,7 @@
   // calling into the runtime.
   __ EnterStubFrame();
   // Setup space on stack for return value and preserve arguments descriptor.
-  __ LoadObject(R0, Object::null_object());
+  __ LoadImmediate(R0, 0);
   __ PushList((1 << R0) | (1 << R4));
   __ CallRuntime(kFixCallersTargetRuntimeEntry, 0);
   // Get Code object result and restore arguments descriptor array.
@@ -335,7 +335,7 @@
   __ ldr(CODE_REG, Address(THR, Thread::fix_allocation_stub_code_offset()));
   __ EnterStubFrame();
   // Setup space on stack for return value.
-  __ LoadObject(R0, Object::null_object());
+  __ LoadImmediate(R0, 0);
   __ Push(R0);
   __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0);
   // Get Code object result.
@@ -542,7 +542,8 @@
   __ ldr(R2, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
   __ add(IP, FP, Operand(R2, LSL, 1));  // R2 is Smi.
   __ ldr(R8, Address(IP, kParamEndSlotFromFp * kWordSize));
-  __ PushObject(Object::null_object());
+  __ LoadImmediate(IP, 0);
+  __ Push(IP);  // Result slot.
   __ Push(R8);  // Receiver.
   __ Push(R9);  // ICData/MegamorphicCache.
   __ Push(R4);  // Arguments descriptor.
@@ -568,8 +569,8 @@
   // Preserve IC data and arguments descriptor.
   __ PushList((1 << R4) | (1 << R9));
 
-  __ LoadObject(IP, Object::null_object());
-  __ Push(IP);  // result
+  __ LoadImmediate(IP, 0);
+  __ Push(IP);  // result slot
   __ Push(R8);  // receiver
   __ Push(R9);  // ICData
   __ Push(R4);  // arguments descriptor
@@ -710,7 +711,7 @@
   // Create a stub frame as we are pushing some objects on the stack before
   // calling into the runtime.
   __ EnterStubFrame();
-  __ LoadObject(IP, Object::null_object());
+  __ LoadImmediate(IP, 0);
   // Setup space on stack for return value.
   // Push array length as Smi and element type.
   __ PushList((1 << R1) | (1 << R2) | (1 << IP));
@@ -952,7 +953,7 @@
   // calling into the runtime.
   __ EnterStubFrame();
   // Setup space on stack for return value.
-  __ LoadObject(R2, Object::null_object());
+  __ LoadImmediate(R2, 0);
   __ SmiTag(R1);
   __ PushList((1 << R1) | (1 << R2));
   __ CallRuntime(kAllocateContextRuntimeEntry, 1);  // Allocate context.
@@ -1193,7 +1194,7 @@
   // Push space for the return value.
   // Push the receiver.
   // Push arguments descriptor array.
-  __ LoadObject(IP, Object::null_object());
+  __ LoadImmediate(IP, 0);
   __ PushList((1 << R4) | (1 << R8) | (1 << IP));
 
   // R2: Smi-tagged arguments array length.
@@ -1422,7 +1423,7 @@
   // Create a stub frame as we are pushing some objects on the stack before
   // calling into the runtime.
   __ EnterStubFrame();
-  __ LoadObject(R0, Object::null_object());
+  __ LoadImmediate(R0, 0);
   // Preserve IC data object and arguments descriptor array and
   // setup space on stack for result (target code object).
   __ PushList((1 << R0) | (1 << R4) | (1 << R9));
@@ -1655,7 +1656,7 @@
 // R9: Contains an ICData.
 void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) {
   __ EnterStubFrame();
-  __ LoadObject(R0, Object::null_object());
+  __ LoadImmediate(R0, 0);
   // Preserve arguments descriptor and make room for result.
   __ PushList((1 << R0) | (1 << R9));
   __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
@@ -1669,7 +1670,7 @@
 
 void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) {
   __ EnterStubFrame();
-  __ LoadObject(R0, Object::null_object());
+  __ LoadImmediate(R0, 0);
   // Make room for result.
   __ PushList((1 << R0));
   __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
@@ -1841,6 +1842,9 @@
   // Clear top exit frame.
   __ LoadImmediate(R2, 0);
   __ StoreToOffset(kWord, R2, THR, Thread::top_exit_frame_info_offset());
+  // Restore the pool pointer.
+  __ RestoreCodePointer();
+  __ LoadPoolPointer();
   __ bx(LR);  // Jump to the exception handler code.
 }
 
@@ -1851,7 +1855,7 @@
 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) {
   __ EnterStubFrame();
   __ Push(R4);
-  __ LoadObject(IP, Object::null_object());
+  __ LoadImmediate(IP, 0);
   __ Push(IP);  // Setup space on stack for return value.
   __ Push(R8);
   __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1);
@@ -2125,6 +2129,32 @@
 
 // Called from switchable IC calls.
 //  R0: receiver
+//  R9: UnlinkedCall
+void StubCode::GenerateUnlinkedCallStub(Assembler* assembler) {
+  __ NoMonomorphicCheckedEntry();
+
+  __ EnterStubFrame();
+  __ Push(R0);  // Preserve receiver.
+
+  __ LoadImmediate(IP, 0);
+  __ Push(IP);  // Result slot
+  __ Push(R0);  // Arg0: Receiver
+  __ Push(R9);  // Arg1: UnlinkedCall
+  __ CallRuntime(kUnlinkedCallRuntimeEntry, 2);
+  __ Drop(2);
+  __ Pop(R9);  // result = IC
+
+  __ Pop(R0);  // Restore receiver.
+  __ LeaveStubFrame();
+
+  __ ldr(CODE_REG, Address(THR, Thread::ic_lookup_through_code_stub_offset()));
+  __ ldr(R1, FieldAddress(CODE_REG, Code::checked_entry_point_offset()));
+  __ bx(R1);
+}
+
+
+// Called from switchable IC calls.
+//  R0: receiver
 //  R9: SingleTargetCache
 // Passed to target:
 //  CODE_REG: target Code object
@@ -2150,8 +2180,9 @@
   __ EnterStubFrame();
   __ Push(R0);  // Preserve receiver.
 
-  __ PushObject(Object::null_object());  // Result.
-  __ Push(R0);                           // Arg0: Receiver
+  __ LoadImmediate(IP, 0);
+  __ Push(IP);  // Result slot
+  __ Push(R0);  // Arg0: Receiver
   __ CallRuntime(kSingleTargetMissRuntimeEntry, 1);
   __ Drop(1);
   __ Pop(R9);  // result = IC
@@ -2171,8 +2202,9 @@
   __ EnterStubFrame();
   __ Push(R0);  // Preserve receiver.
 
-  __ PushObject(Object::null_object());  // Result.
-  __ Push(R0);                           // Arg0: Receiver
+  __ LoadImmediate(IP, 0);
+  __ Push(IP);  // Result slot
+  __ Push(R0);  // Arg0: Receiver
   __ CallRuntime(kMonomorphicMissRuntimeEntry, 1);
   __ Drop(1);
   __ Pop(R9);  // result = IC
diff --git a/runtime/vm/stub_code_arm64.cc b/runtime/vm/stub_code_arm64.cc
index f550777..6d97d6a 100644
--- a/runtime/vm/stub_code_arm64.cc
+++ b/runtime/vm/stub_code_arm64.cc
@@ -324,7 +324,7 @@
   __ EnterStubFrame();
   // Setup space on stack for return value and preserve arguments descriptor.
   __ Push(R4);
-  __ PushObject(Object::null_object());
+  __ Push(ZR);
   __ CallRuntime(kPatchStaticCallRuntimeEntry, 0);
   // Get Code object result and restore arguments descriptor array.
   __ Pop(CODE_REG);
@@ -350,7 +350,7 @@
   __ EnterStubFrame();
   // Setup space on stack for return value and preserve arguments descriptor.
   __ Push(R4);
-  __ PushObject(Object::null_object());
+  __ Push(ZR);
   __ CallRuntime(kFixCallersTargetRuntimeEntry, 0);
   // Get Code object result and restore arguments descriptor array.
   __ Pop(CODE_REG);
@@ -372,7 +372,7 @@
   __ ldr(CODE_REG, Address(THR, Thread::fix_allocation_stub_code_offset()));
   __ EnterStubFrame();
   // Setup space on stack for return value.
-  __ PushObject(Object::null_object());
+  __ Push(ZR);
   __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0);
   // Get Code object result.
   __ Pop(CODE_REG);
@@ -563,7 +563,7 @@
   __ LoadFieldFromOffset(R2, R4, ArgumentsDescriptor::count_offset());
   __ add(TMP, FP, Operand(R2, LSL, 2));  // R2 is Smi.
   __ LoadFromOffset(R6, TMP, kParamEndSlotFromFp * kWordSize);
-  __ PushObject(Object::null_object());
+  __ Push(ZR);  // Result slot.
   __ Push(R6);  // Receiver.
   __ Push(R5);  // ICData/MegamorphicCache.
   __ Push(R4);  // Arguments descriptor.
@@ -594,7 +594,7 @@
   // Push the receiver.
   // Push IC data object.
   // Push arguments descriptor array.
-  __ PushObject(Object::null_object());
+  __ Push(ZR);
   __ Push(R6);
   __ Push(R5);
   __ Push(R4);
@@ -756,7 +756,7 @@
   __ EnterStubFrame();
   // Setup space on stack for return value.
   // Push array length as Smi and element type.
-  __ PushObject(Object::null_object());
+  __ Push(ZR);
   __ Push(R2);
   __ Push(R1);
   __ CallRuntime(kAllocateArrayRuntimeEntry, 2);
@@ -1189,8 +1189,7 @@
   // Create a stub frame as we are pushing some objects on the stack before
   // calling into the runtime.
   __ EnterStubFrame();  // Uses pool pointer to pass cls to runtime.
-  // Setup space on stack for return value.
-  __ PushObject(Object::null_object());
+  __ Push(ZR);  // Result slot.
   __ PushObject(cls);  // Push class of object to be allocated.
   if (is_cls_parameterized) {
     // Push type arguments.
@@ -1227,7 +1226,7 @@
   // Push space for the return value.
   // Push the receiver.
   // Push arguments descriptor array.
-  __ PushObject(Object::null_object());
+  __ Push(ZR);
   __ Push(R6);
   __ Push(R4);
 
@@ -1482,7 +1481,7 @@
   __ Push(R4);  // Preserve arguments descriptor array.
   __ Push(R5);  // Preserve IC Data.
   // Setup space on stack for the result (target code object).
-  __ PushObject(Object::null_object());
+  __ Push(ZR);
   // Push call arguments.
   for (intptr_t i = 0; i < num_args; i++) {
     __ LoadFromOffset(TMP, R7, -i * kWordSize);
@@ -1713,7 +1712,7 @@
 void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) {
   __ EnterStubFrame();
   __ Push(R5);
-  __ PushObject(Object::null_object());  // Space for result.
+  __ Push(ZR);  // Space for result.
   __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
   __ Pop(CODE_REG);
   __ Pop(R5);
@@ -1725,7 +1724,7 @@
 
 void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) {
   __ EnterStubFrame();
-  __ PushObject(Object::null_object());  // Space for result.
+  __ Push(ZR);  // Space for result.
   __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
   __ Pop(CODE_REG);
   __ LeaveStubFrame();
@@ -1895,6 +1894,9 @@
   __ StoreToOffset(R2, THR, Thread::vm_tag_offset());
   // Clear top exit frame.
   __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset());
+  // Restore the pool pointer.
+  __ RestoreCodePointer();
+  __ LoadPoolPointer();
   __ ret();  // Jump to the exception handler code.
 }
 
@@ -1906,7 +1908,7 @@
   __ EnterStubFrame();
   __ Push(R4);
   // Setup space on stack for the return value.
-  __ PushObject(Object::null_object());
+  __ Push(ZR);
   __ Push(R6);
   __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1);
   __ Pop(R0);  // Discard argument.
@@ -2186,6 +2188,31 @@
 // Called from switchable IC calls.
 //  R0: receiver
 //  R5: SingleTargetCache
+void StubCode::GenerateUnlinkedCallStub(Assembler* assembler) {
+  __ NoMonomorphicCheckedEntry();
+
+  __ EnterStubFrame();
+  __ Push(R0);  // Preserve receiver.
+
+  __ Push(ZR);  // Result slot.
+  __ Push(R0);  // Arg0: Receiver
+  __ Push(R5);  // Arg1: UnlinkedCall
+  __ CallRuntime(kUnlinkedCallRuntimeEntry, 2);
+  __ Drop(2);
+  __ Pop(R5);  // result = IC
+
+  __ Pop(R0);  // Restore receiver.
+  __ LeaveStubFrame();
+
+  __ ldr(CODE_REG, Address(THR, Thread::ic_lookup_through_code_stub_offset()));
+  __ ldr(R1, FieldAddress(CODE_REG, Code::checked_entry_point_offset()));
+  __ br(R1);
+}
+
+
+// Called from switchable IC calls.
+//  R0: receiver
+//  R5: SingleTargetCache
 // Passed to target:
 //  CODE_REG: target Code object
 void StubCode::GenerateSingleTargetCallStub(Assembler* assembler) {
@@ -2212,8 +2239,8 @@
   __ EnterStubFrame();
   __ Push(R0);  // Preserve receiver.
 
-  __ PushObject(Object::null_object());  // Result.
-  __ Push(R0);                           // Arg0: Receiver
+  __ Push(ZR);  // Result slot.
+  __ Push(R0);  // Arg0: Receiver
   __ CallRuntime(kSingleTargetMissRuntimeEntry, 1);
   __ Drop(1);
   __ Pop(R5);  // result = IC
@@ -2233,8 +2260,8 @@
   __ EnterStubFrame();
   __ Push(R0);  // Preserve receiver.
 
-  __ PushObject(Object::null_object());  // Result.
-  __ Push(R0);                           // Arg0: Receiver
+  __ Push(ZR);  // Result slot.
+  __ Push(R0);  // Arg0: Receiver
   __ CallRuntime(kMonomorphicMissRuntimeEntry, 1);
   __ Drop(1);
   __ Pop(R5);  // result = IC
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index 3b1ba83..cb805c6 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -248,11 +248,9 @@
 // Input parameters:
 //   EDX: arguments descriptor array.
 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) {
-  const Immediate& raw_null =
-      Immediate(reinterpret_cast<intptr_t>(Object::null()));
   __ EnterStubFrame();
   __ pushl(EDX);  // Preserve arguments descriptor array.
-  __ pushl(raw_null);  // Setup space on stack for return value.
+  __ pushl(Immediate(0));  // Setup space on stack for return value.
   __ CallRuntime(kPatchStaticCallRuntimeEntry, 0);
   __ popl(EAX);  // Get Code object result.
   __ popl(EDX);  // Restore arguments descriptor array.
@@ -268,13 +266,11 @@
 // (invalid because its function was optimized or deoptimized).
 // EDX: arguments descriptor array.
 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) {
-  const Immediate& raw_null =
-      Immediate(reinterpret_cast<intptr_t>(Object::null()));
   // Create a stub frame as we are pushing some objects on the stack before
   // calling into the runtime.
   __ EnterStubFrame();
   __ pushl(EDX);  // Preserve arguments descriptor array.
-  __ pushl(raw_null);  // Setup space on stack for return value.
+  __ pushl(Immediate(0));  // Setup space on stack for return value.
   __ CallRuntime(kFixCallersTargetRuntimeEntry, 0);
   __ popl(EAX);  // Get Code object.
   __ popl(EDX);  // Restore arguments descriptor array.
@@ -288,10 +284,8 @@
 // Called from object allocate instruction when the allocation stub has been
 // disabled.
 void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) {
-  const Immediate& raw_null =
-      Immediate(reinterpret_cast<intptr_t>(Object::null()));
   __ EnterStubFrame();
-  __ pushl(raw_null);  // Setup space on stack for return value.
+  __ pushl(Immediate(0));  // Setup space on stack for return value.
   __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0);
   __ popl(EAX);  // Get Code object.
   __ movl(EAX, FieldAddress(EAX, Code::entry_point_offset()));
@@ -476,7 +470,7 @@
   __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
   __ movl(EAX, Address(
       EBP, EDI, TIMES_HALF_WORD_SIZE, kParamEndSlotFromFp * kWordSize));
-  __ pushl(raw_null);  // Setup space on stack for result.
+  __ pushl(Immediate(0));  // Setup space on stack for result.
   __ pushl(EAX);  // Receiver.
   __ pushl(ECX);  // ICData/MegamorphicCache.
   __ pushl(EDX);  // Arguments descriptor array.
@@ -504,9 +498,7 @@
   __ pushl(ECX);
   __ pushl(EDX);
 
-  const Immediate& raw_null =
-      Immediate(reinterpret_cast<intptr_t>(Instructions::null()));
-  __ pushl(raw_null);  // Space for the result of the runtime call.
+  __ pushl(Immediate(0));  // Space for the result of the runtime call.
   __ pushl(EAX);  // Pass receiver.
   __ pushl(ECX);  // Pass IC data.
   __ pushl(EDX);  // Pass arguments descriptor.
@@ -539,8 +531,6 @@
 // The newly allocated object is returned in EAX.
 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) {
   Label slow_case;
-  const Immediate& raw_null =
-      Immediate(reinterpret_cast<intptr_t>(Object::null()));
   // Compute the size to be allocated, it is based on the array length
   // and is computed as:
   // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)).
@@ -661,7 +651,7 @@
   // Create a stub frame as we are pushing some objects on the stack before
   // calling into the runtime.
   __ EnterStubFrame();
-  __ pushl(raw_null);  // Setup space on stack for return value.
+  __ pushl(Immediate(0));  // Setup space on stack for return value.
   __ pushl(EDX);  // Array length as Smi.
   __ pushl(ECX);  // Element type.
   __ CallRuntime(kAllocateArrayRuntimeEntry, 2);
@@ -789,8 +779,6 @@
 // EAX: new allocated RawContext object.
 // EBX and EDX are destroyed.
 void StubCode::GenerateAllocateContextStub(Assembler* assembler) {
-  const Immediate& raw_null =
-      Immediate(reinterpret_cast<intptr_t>(Object::null()));
   if (FLAG_inline_alloc) {
     Label slow_case;
     // First compute the rounded instance size.
@@ -905,7 +893,7 @@
   // Create a stub frame as we are pushing some objects on the stack before
   // calling into the runtime.
   __ EnterStubFrame();
-  __ pushl(raw_null);  // Setup space on stack for return value.
+  __ pushl(Immediate(0));  // Setup space on stack for return value.
   __ SmiTag(EDX);
   __ pushl(EDX);
   __ CallRuntime(kAllocateContextRuntimeEntry, 1);  // Allocate context.
@@ -1133,9 +1121,7 @@
   __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
   __ movl(EAX, Address(EBP, EDI, TIMES_2, kParamEndSlotFromFp * kWordSize));
 
-  const Immediate& raw_null =
-      Immediate(reinterpret_cast<intptr_t>(Object::null()));
-  __ pushl(raw_null);  // Setup space on stack for result from noSuchMethod.
+  __ pushl(Immediate(0));  // Setup space on stack for result from noSuchMethod.
   __ pushl(EAX);  // Receiver.
   __ pushl(EDX);  // Arguments descriptor array.
 
@@ -1368,8 +1354,6 @@
   __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
 
   __ Comment("IC miss");
-  const Immediate& raw_null =
-      Immediate(reinterpret_cast<intptr_t>(Object::null()));
   // Compute address of arguments (first read number of arguments from
   // arguments descriptor array and then compute address on the stack).
   __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
@@ -1379,7 +1363,7 @@
   __ EnterStubFrame();
   __ pushl(EDX);  // Preserve arguments descriptor array.
   __ pushl(ECX);  // Preserve IC data object.
-  __ pushl(raw_null);  // Setup space on stack for result (target code object).
+  __ pushl(Immediate(0));  // Result slot.
   // Push call arguments.
   for (intptr_t i = 0; i < num_args; i++) {
     __ movl(EBX, Address(EAX, -kWordSize * i));
@@ -1624,9 +1608,7 @@
   __ pushl(ECX);
   // Room for result. Debugger stub returns address of the
   // unpatched runtime stub.
-  const Immediate& raw_null =
-      Immediate(reinterpret_cast<intptr_t>(Object::null()));
-  __ pushl(raw_null);  // Room for result.
+  __ pushl(Immediate(0));  // Room for result.
   __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
   __ popl(EAX);  // Code of original stub.
   __ popl(ECX);  // Restore IC data.
@@ -1641,9 +1623,7 @@
   __ EnterStubFrame();
   // Room for result. Debugger stub returns address of the
   // unpatched runtime stub.
-  const Immediate& raw_null =
-      Immediate(reinterpret_cast<intptr_t>(Object::null()));
-  __ pushl(raw_null);  // Room for result.
+  __ pushl(Immediate(0));  // Room for result.
   __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
   __ popl(EAX);  // Code of the original stub
   __ LeaveFrame();
@@ -1827,11 +1807,9 @@
 // EBX: function to be reoptimized.
 // EDX: argument descriptor (preserved).
 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) {
-  const Immediate& raw_null =
-      Immediate(reinterpret_cast<intptr_t>(Object::null()));
   __ EnterStubFrame();
   __ pushl(EDX);
-  __ pushl(raw_null);  // Setup space on stack for return value.
+  __ pushl(Immediate(0));  // Setup space on stack for return value.
   __ pushl(EBX);
   __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1);
   __ popl(EAX);  // Discard argument.
@@ -2044,6 +2022,11 @@
 }
 
 
+void StubCode::GenerateUnlinkedCallStub(Assembler* assembler) {
+  __ int3();
+}
+
+
 void StubCode::GenerateSingleTargetCallStub(Assembler* assembler) {
   __ int3();
 }
diff --git a/runtime/vm/stub_code_mips.cc b/runtime/vm/stub_code_mips.cc
index 6560d9f..e6384d8 100644
--- a/runtime/vm/stub_code_mips.cc
+++ b/runtime/vm/stub_code_mips.cc
@@ -299,8 +299,7 @@
 
   __ addiu(SP, SP, Immediate(-2 * kWordSize));
   __ sw(S4, Address(SP, 1 * kWordSize));
-  __ LoadObject(TMP, Object::null_object());
-  __ sw(TMP, Address(SP, 0 * kWordSize));
+  __ sw(ZR, Address(SP, 0 * kWordSize));
 
   __ CallRuntime(kPatchStaticCallRuntimeEntry, 0);
   __ Comment("CallStaticFunctionStub return");
@@ -331,8 +330,7 @@
   // Setup space on stack for return value and preserve arguments descriptor.
   __ addiu(SP, SP, Immediate(-2 * kWordSize));
   __ sw(S4, Address(SP, 1 * kWordSize));
-  __ LoadObject(TMP, Object::null_object());
-  __ sw(TMP, Address(SP, 0 * kWordSize));
+  __ sw(ZR, Address(SP, 0 * kWordSize));
   __ CallRuntime(kFixCallersTargetRuntimeEntry, 0);
   // Get Code object result and restore arguments descriptor array.
   __ lw(CODE_REG, Address(SP, 0 * kWordSize));
@@ -357,8 +355,7 @@
   __ EnterStubFrame();
   // Setup space on stack for return value.
   __ addiu(SP, SP, Immediate(-1 * kWordSize));
-  __ LoadObject(TMP, Object::null_object());
-  __ sw(TMP, Address(SP, 0 * kWordSize));
+  __ sw(ZR, Address(SP, 0 * kWordSize));
   __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0);
   // Get Code object result.
   __ lw(CODE_REG, Address(SP, 0 * kWordSize));
@@ -564,8 +561,7 @@
   // Push arguments descriptor array.
   // Push original arguments array.
   __ addiu(SP, SP, Immediate(-4 * kWordSize));
-  __ LoadObject(TMP, Object::null_object());
-  __ sw(TMP, Address(SP, 3 * kWordSize));
+  __ sw(ZR, Address(SP, 3 * kWordSize));
   __ sw(T6, Address(SP, 2 * kWordSize));
   __ sw(S5, Address(SP, 1 * kWordSize));
   __ sw(S4, Address(SP, 0 * kWordSize));
@@ -598,8 +594,7 @@
   // Push the receiver.
   // Push IC data object.
   // Push arguments descriptor array.
-  __ LoadObject(TMP, Object::null_object());
-  __ sw(TMP, Address(SP, 3 * kWordSize));
+  __ sw(ZR, Address(SP, 3 * kWordSize));
   __ sw(T6, Address(SP, 2 * kWordSize));
   __ sw(S5, Address(SP, 1 * kWordSize));
   __ sw(S4, Address(SP, 0 * kWordSize));
@@ -757,8 +752,7 @@
   // Setup space on stack for return value.
   // Push array length as Smi and element type.
   __ addiu(SP, SP, Immediate(-3 * kWordSize));
-  __ LoadObject(TMP, Object::null_object());
-  __ sw(TMP, Address(SP, 2 * kWordSize));
+  __ sw(ZR, Address(SP, 2 * kWordSize));
   __ sw(A1, Address(SP, 1 * kWordSize));
   __ sw(A0, Address(SP, 0 * kWordSize));
   __ CallRuntime(kAllocateArrayRuntimeEntry, 2);
@@ -1260,8 +1254,7 @@
   // Push arguments descriptor array.
   const intptr_t kNumArgs = 3;
   __ addiu(SP, SP, Immediate(-kNumArgs * kWordSize));
-  __ LoadObject(TMP, Object::null_object());
-  __ sw(TMP, Address(SP, 2 * kWordSize));
+  __ sw(ZR, Address(SP, 2 * kWordSize));
   __ sw(T6, Address(SP, 1 * kWordSize));
   __ sw(S4, Address(SP, 0 * kWordSize));
 
@@ -1524,8 +1517,7 @@
   __ addiu(SP, SP, Immediate(-num_slots * kWordSize));
   __ sw(S5, Address(SP, (num_slots - 1) * kWordSize));
   __ sw(S4, Address(SP, (num_slots - 2) * kWordSize));
-  __ LoadObject(TMP, Object::null_object());
-  __ sw(TMP, Address(SP, (num_slots - 3) * kWordSize));
+  __ sw(ZR, Address(SP, (num_slots - 3) * kWordSize));
   // Push call arguments.
   for (intptr_t i = 0; i < num_args; i++) {
     __ lw(TMP, Address(T1, -i * kWordSize));
@@ -1777,8 +1769,7 @@
   __ EnterStubFrame();
   __ addiu(SP, SP, Immediate(-2 * kWordSize));
   __ sw(S5, Address(SP, 1 * kWordSize));
-  __ LoadObject(TMP, Object::null_object());
-  __ sw(TMP, Address(SP, 0 * kWordSize));
+  __ sw(ZR, Address(SP, 0 * kWordSize));
 
   __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
 
@@ -1795,8 +1786,7 @@
   __ Comment("RuntimeCallBreakpoint stub");
   __ EnterStubFrame();
   __ addiu(SP, SP, Immediate(-1 * kWordSize));
-  __ LoadObject(TMP, Object::null_object());
-  __ sw(TMP, Address(SP, 0 * kWordSize));
+  __ sw(ZR, Address(SP, 0 * kWordSize));
 
   __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
 
@@ -1977,7 +1967,9 @@
   __ sw(A2, Assembler::VMTagAddress());
   // Clear top exit frame.
   __ sw(ZR, Address(THR, Thread::top_exit_frame_info_offset()));
-
+  // Restore pool pointer.
+  __ RestoreCodePointer();
+  __ LoadPoolPointer();
   __ jr(A0);  // Jump to the exception handler code.
   __ delay_slot()->mov(SP, A1);  // Stack pointer.
 }
@@ -1992,8 +1984,7 @@
   __ addiu(SP, SP, Immediate(-3 * kWordSize));
   __ sw(S4, Address(SP, 2 * kWordSize));
   // Setup space on stack for return value.
-  __ LoadObject(TMP, Object::null_object());
-  __ sw(TMP, Address(SP, 1 * kWordSize));
+  __ sw(ZR, Address(SP, 1 * kWordSize));
   __ sw(T0, Address(SP, 0 * kWordSize));
   __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1);
   __ Comment("OptimizeFunctionStub return");
@@ -2277,6 +2268,30 @@
 }
 
 
+// Called from switchable IC calls.
+//  T0: receiver
+//  S5: SingleTargetCache
+void StubCode::GenerateUnlinkedCallStub(Assembler* assembler) {
+  __ NoMonomorphicCheckedEntry();
+
+  __ EnterStubFrame();
+  __ Push(T0);  // Preserve receiver.
+
+  __ Push(ZR);  // Result slot.
+  __ Push(T0);  // Arg0: Receiver
+  __ Push(S5);  // Arg1: UnlinkedCall
+  __ CallRuntime(kUnlinkedCallRuntimeEntry, 2);
+  __ Drop(2);
+  __ Pop(S5);  // result = IC
+
+  __ Pop(T0);  // Restore receiver.
+  __ LeaveStubFrame();
+
+  __ lw(CODE_REG, Address(THR, Thread::ic_lookup_through_code_stub_offset()));
+  __ lw(T1, FieldAddress(CODE_REG, Code::checked_entry_point_offset()));
+  __ jr(T1);
+}
+
 
 // Called from switchable IC calls.
 //  T0: receiver
@@ -2303,8 +2318,8 @@
   __ EnterStubFrame();
   __ Push(T0);  // Preserve receiver.
 
-  __ PushObject(Object::null_object());  // Result.
-  __ Push(T0);                           // Arg0: Receiver
+  __ Push(ZR);  // Result slot.
+  __ Push(T0);  // Arg0: Receiver
   __ CallRuntime(kSingleTargetMissRuntimeEntry, 1);
   __ Drop(1);
   __ Pop(S5);  // result = IC
@@ -2324,8 +2339,8 @@
   __ EnterStubFrame();
   __ Push(T0);  // Preserve receiver.
 
-  __ PushObject(Object::null_object());  // Result.
-  __ Push(T0);                           // Arg0: Receiver
+  __ Push(ZR);  // Result slot.
+  __ Push(T0);  // Arg0: Receiver
   __ CallRuntime(kMonomorphicMissRuntimeEntry, 1);
   __ Drop(1);
   __ Pop(S5);  // result = IC
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index daf1e5e..5c4384c 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -261,7 +261,7 @@
   __ EnterStubFrame();
   __ pushq(R10);  // Preserve arguments descriptor array.
   // Setup space on stack for return value.
-  __ PushObject(Object::null_object());
+  __ pushq(Immediate(0));
   __ CallRuntime(kPatchStaticCallRuntimeEntry, 0);
   __ popq(CODE_REG);  // Get Code object result.
   __ popq(R10);  // Restore arguments descriptor array.
@@ -284,7 +284,7 @@
   __ EnterStubFrame();
   __ pushq(R10);  // Preserve arguments descriptor array.
   // Setup space on stack for return value.
-  __ PushObject(Object::null_object());
+  __ pushq(Immediate(0));
   __ CallRuntime(kFixCallersTargetRuntimeEntry, 0);
   __ popq(CODE_REG);  // Get Code object.
   __ popq(R10);  // Restore arguments descriptor array.
@@ -304,7 +304,7 @@
   __ movq(CODE_REG, Address(THR, Thread::fix_allocation_stub_code_offset()));
   __ EnterStubFrame();
   // Setup space on stack for return value.
-  __ PushObject(Object::null_object());
+  __ pushq(Immediate(0));
   __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0);
   __ popq(CODE_REG);  // Get Code object.
   __ movq(RAX, FieldAddress(CODE_REG, Code::entry_point_offset()));
@@ -505,7 +505,7 @@
   __ movq(RDI, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
   __ movq(RAX, Address(
       RBP, RDI, TIMES_HALF_WORD_SIZE, kParamEndSlotFromFp * kWordSize));
-  __ PushObject(Object::null_object());  // Setup space on stack for result.
+  __ pushq(Immediate(0));  // Setup space on stack for result.
   __ pushq(RAX);  // Receiver.
   __ pushq(RBX);  // ICData/MegamorphicCache.
   __ pushq(R10);  // Arguments descriptor array.
@@ -535,7 +535,7 @@
   __ pushq(R10);
 
   // Space for the result of the runtime call.
-  __ PushObject(Object::null_object());
+  __ pushq(Immediate(0));
   __ pushq(RAX);  // Receiver.
   __ pushq(RBX);  // IC data.
   __ pushq(R10);  // Arguments descriptor.
@@ -682,7 +682,7 @@
   // calling into the runtime.
   __ EnterStubFrame();
   // Setup space on stack for return value.
-  __ PushObject(Object::null_object());
+  __ pushq(Immediate(0));
   __ pushq(R10);  // Array length as Smi.
   __ pushq(RBX);  // Element type.
   __ CallRuntime(kAllocateArrayRuntimeEntry, 2);
@@ -1168,8 +1168,7 @@
   __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
   __ movq(RAX, Address(RBP, R13, TIMES_4, kParamEndSlotFromFp * kWordSize));
 
-  __ LoadObject(R12, Object::null_object());
-  __ pushq(R12);  // Setup space on stack for result from noSuchMethod.
+  __ pushq(Immediate(0));  // Result slot.
   __ pushq(RAX);  // Receiver.
   __ pushq(R10);  // Arguments descriptor array.
 
@@ -1400,7 +1399,6 @@
   __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
 
   __ Comment("IC miss");
-  __ LoadObject(R13, Object::null_object());
   // Compute address of arguments (first read number of arguments from
   // arguments descriptor array and then compute address on the stack).
   __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
@@ -1408,7 +1406,7 @@
   __ EnterStubFrame();
   __ pushq(R10);  // Preserve arguments descriptor array.
   __ pushq(RBX);  // Preserve IC data object.
-  __ pushq(R13);  // Setup space on stack for result (target code object).
+  __ pushq(Immediate(0));  // Result slot.
   // Push call arguments.
   for (intptr_t i = 0; i < num_args; i++) {
     __ movq(RCX, Address(RAX, -kWordSize * i));
@@ -1667,14 +1665,10 @@
 // TOS(0): return address (Dart code).
 void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) {
   __ EnterStubFrame();
-  // Preserve IC data.
-  __ pushq(RBX);
-  // Room for result. Debugger stub returns address of the
-  // unpatched runtime stub.
-  __ LoadObject(R12, Object::null_object());
-  __ pushq(R12);  // Room for result.
+  __ pushq(RBX);  // Preserve IC data.
+  __ pushq(Immediate(0));  // Result slot.
   __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
-  __ popq(CODE_REG);  // Address of original.
+  __ popq(CODE_REG);  // Original stub.
   __ popq(RBX);  // Restore IC data.
   __ LeaveStubFrame();
 
@@ -1686,12 +1680,9 @@
 //  TOS(0): return address (Dart code).
 void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) {
   __ EnterStubFrame();
-  // Room for result. Debugger stub returns address of the
-  // unpatched runtime stub.
-  __ LoadObject(R12, Object::null_object());
-  __ pushq(R12);  // Room for result.
+  __ pushq(Immediate(0));  // Result slot.
   __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
-  __ popq(CODE_REG);  // Address of original.
+  __ popq(CODE_REG);  // Original stub.
   __ LeaveStubFrame();
 
   __ movq(RAX, FieldAddress(CODE_REG, Code::entry_point_offset()));
@@ -1874,6 +1865,9 @@
   // Clear top exit frame.
   __ movq(Address(THR, Thread::top_exit_frame_info_offset()),
           Immediate(0));
+  // Restore the pool pointer.
+  __ RestoreCodePointer();
+  __ LoadPoolPointer(PP);
   __ jmp(CallingConventions::kArg1Reg);  // Jump to the exception handler code.
 }
 
@@ -1883,10 +1877,9 @@
 // R10: argument descriptor (preserved).
 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) {
   __ EnterStubFrame();
-  __ LoadObject(R12, Object::null_object());
-  __ pushq(R10);
-  __ pushq(R12);  // Setup space on stack for return value.
-  __ pushq(RDI);
+  __ pushq(R10);  // Preserve args descriptor.
+  __ pushq(Immediate(0));  // Result slot.
+  __ pushq(RDI);  // Arg0: function to optimize
   __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1);
   __ popq(RAX);  // Disard argument.
   __ popq(CODE_REG);  // Get Code object.
@@ -2167,6 +2160,31 @@
 }
 
 
+//  RDI: receiver
+//  RBX: UnlinkedCall
+void StubCode::GenerateUnlinkedCallStub(Assembler* assembler) {
+  __ NoMonomorphicCheckedEntry();
+
+  __ EnterStubFrame();
+  __ pushq(RDI);  // Preserve receiver.
+
+  __ pushq(Immediate(0));  // Result slot.
+  __ pushq(RDI);           // Arg0: Receiver
+  __ pushq(RBX);           // Arg1: UnlinkedCall
+  __ CallRuntime(kUnlinkedCallRuntimeEntry, 2);
+  __ popq(RBX);
+  __ popq(RBX);
+  __ popq(RBX);  // result = IC
+
+  __ popq(RDI);  // Restore receiver.
+  __ LeaveStubFrame();
+
+  __ movq(CODE_REG, Address(THR, Thread::ic_lookup_through_code_stub_offset()));
+  __ movq(RCX, FieldAddress(CODE_REG, Code::checked_entry_point_offset()));
+  __ jmp(RCX);
+}
+
+
 // Called from switchable IC calls.
 //  RDI: receiver
 //  RBX: SingleTargetCache
@@ -2191,8 +2209,8 @@
   __ EnterStubFrame();
   __ pushq(RDI);  // Preserve receiver.
 
-  __ PushObject(Object::null_object());  // Result.
-  __ pushq(RDI);                         // Arg0: Receiver
+  __ pushq(Immediate(0));  // Result slot.
+  __ pushq(RDI);           // Arg0: Receiver
   __ CallRuntime(kSingleTargetMissRuntimeEntry, 1);
   __ popq(RBX);
   __ popq(RBX);  // result = IC
@@ -2212,8 +2230,8 @@
   __ EnterStubFrame();
   __ pushq(RDI);  // Preserve receiver.
 
-  __ PushObject(Object::null_object());  // Result.
-  __ pushq(RDI);                         // Arg0: Receiver
+  __ pushq(Immediate(0));  // Result slot.
+  __ pushq(RDI);           // Arg0: Receiver
   __ CallRuntime(kMonomorphicMissRuntimeEntry, 1);
   __ popq(RBX);
   __ popq(RBX);  // result = IC
diff --git a/runtime/vm/symbols.cc b/runtime/vm/symbols.cc
index a0b6c83..0f91fb6 100644
--- a/runtime/vm/symbols.cc
+++ b/runtime/vm/symbols.cc
@@ -5,7 +5,6 @@
 #include "vm/symbols.h"
 
 #include "vm/handles.h"
-#include "vm/handles_impl.h"
 #include "vm/hash_table.h"
 #include "vm/isolate.h"
 #include "vm/object.h"
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 8730c9e..29cdb8a 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -175,6 +175,7 @@
   V(Context, "Context")                                                        \
   V(ContextScope, "ContextScope")                                              \
   V(SingleTargetCache, "SingleTargetCache")                                    \
+  V(UnlinkedCall, "UnlinkedCall")                                              \
   V(ICData, "ICData")                                                          \
   V(MegamorphicCache, "MegamorphicCache")                                      \
   V(SubtypeTestCache, "SubtypeTestCache")                                      \
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 967bac0..d3534af 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -21,6 +21,7 @@
 #include "vm/thread_interrupter.h"
 #include "vm/thread_registry.h"
 #include "vm/timeline.h"
+#include "vm/zone.h"
 
 namespace dart {
 
@@ -423,6 +424,19 @@
 }
 
 
+bool Thread::ZoneIsOwnedByThread(Zone* zone) const {
+  ASSERT(zone != NULL);
+  Zone* current = zone_;
+  while (current != NULL) {
+    if (current == zone) {
+      return true;
+    }
+    current = current->previous();
+  }
+  return false;
+}
+
+
 void Thread::DeferOOBMessageInterrupts() {
   MonitorLocker ml(thread_lock_);
   defer_oob_messages_count_++;
@@ -553,10 +567,13 @@
 
 
 bool Thread::CanCollectGarbage() const {
-  // We have non mutator threads grow the heap instead of triggering
-  // a garbage collection when they are at a safepoint (e.g: background
-  // compiler thread finalizing and installing code at a safepoint).
-  return (IsMutatorThread() || IsAtSafepoint());
+  // We grow the heap instead of triggering a garbage collection when a
+  // thread is at a safepoint in the following situations :
+  //   - background compiler thread finalizing and installing code
+  //   - disassembly of the generated code is done after compilation
+  // So essentially we state that garbage collection is possible only
+  // when we are not at a safepoint.
+  return !IsAtSafepoint();
 }
 
 
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index 149a8e1..50b5c47 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -259,6 +259,8 @@
   // The topmost zone used for allocation in this thread.
   Zone* zone() const { return zone_; }
 
+  bool ZoneIsOwnedByThread(Zone* zone) const;
+
   // The reusable api local scope for this thread.
   ApiLocalScope* api_reusable_scope() const { return api_reusable_scope_; }
   void set_api_reusable_scope(ApiLocalScope* value) {
diff --git a/runtime/vm/virtual_memory_fuchsia.cc b/runtime/vm/virtual_memory_fuchsia.cc
index b7b8b89..8cbc836 100644
--- a/runtime/vm/virtual_memory_fuchsia.cc
+++ b/runtime/vm/virtual_memory_fuchsia.cc
@@ -26,7 +26,7 @@
 
 
 VirtualMemory* VirtualMemory::ReserveInternal(intptr_t size) {
-  mx_handle_t vmo = mx_vm_object_create(size);
+  mx_handle_t vmo = mx_vmo_create(size);
   if (vmo <= 0) {
     return NULL;
   }
diff --git a/runtime/vm/zone.cc b/runtime/vm/zone.cc
index 743727a..ac79f35 100644
--- a/runtime/vm/zone.cc
+++ b/runtime/vm/zone.cc
@@ -72,6 +72,31 @@
 }
 
 
+Zone::Zone()
+    : initial_buffer_(buffer_, kInitialChunkSize),
+      position_(initial_buffer_.start()),
+      limit_(initial_buffer_.end()),
+      head_(NULL),
+      large_segments_(NULL),
+      handles_(),
+      previous_(NULL) {
+  ASSERT(Utils::IsAligned(position_, kAlignment));
+#ifdef DEBUG
+  // Zap the entire initial buffer.
+  memset(initial_buffer_.pointer(), kZapUninitializedByte,
+         initial_buffer_.size());
+#endif
+}
+
+
+Zone::~Zone() {
+  if (FLAG_trace_zones) {
+    DumpZoneSizes();
+  }
+  DeleteAll();
+}
+
+
 void Zone::DeleteAll() {
   // Traverse the chained list of segments, zapping (in debug mode)
   // and freeing every zone segment.
@@ -234,4 +259,25 @@
 }
 
 
+StackZone::StackZone(Thread* thread) : StackResource(thread), zone_() {
+  if (FLAG_trace_zones) {
+    OS::PrintErr("*** Starting a new Stack zone 0x%" Px "(0x%" Px ")\n",
+                 reinterpret_cast<intptr_t>(this),
+                 reinterpret_cast<intptr_t>(&zone_));
+  }
+  zone_.Link(thread->zone());
+  thread->set_zone(&zone_);
+}
+
+
+StackZone::~StackZone() {
+  ASSERT(thread()->zone() == &zone_);
+  thread()->set_zone(zone_.previous_);
+  if (FLAG_trace_zones) {
+    OS::PrintErr("*** Deleting Stack zone 0x%" Px "(0x%" Px ")\n",
+                 reinterpret_cast<intptr_t>(this),
+                 reinterpret_cast<intptr_t>(&zone_));
+  }
+}
+
 }  // namespace dart
diff --git a/runtime/vm/zone.h b/runtime/vm/zone.h
index 29d2765..0d274ad 100644
--- a/runtime/vm/zone.h
+++ b/runtime/vm/zone.h
@@ -70,29 +70,11 @@
 
   void VisitObjectPointers(ObjectPointerVisitor* visitor);
 
- private:
-  Zone()
-    : initial_buffer_(buffer_, kInitialChunkSize),
-      position_(initial_buffer_.start()),
-      limit_(initial_buffer_.end()),
-      head_(NULL),
-      large_segments_(NULL),
-      handles_(),
-      previous_(NULL) {
-    ASSERT(Utils::IsAligned(position_, kAlignment));
-#ifdef DEBUG
-    // Zap the entire initial buffer.
-    memset(initial_buffer_.pointer(), kZapUninitializedByte,
-           initial_buffer_.size());
-#endif
-  }
+  Zone* previous() const { return previous_; }
 
-  ~Zone() {  // Delete all memory associated with the zone.
-    if (FLAG_trace_zones) {
-      DumpZoneSizes();
-    }
-    DeleteAll();
-  }
+ private:
+  Zone();
+  ~Zone();  // Delete all memory associated with the zone.
 
   // All pointers returned from AllocateUnsafe() and New() have this alignment.
   static const intptr_t kAlignment = kDoubleSize;
@@ -185,26 +167,10 @@
 class StackZone : public StackResource {
  public:
   // Create an empty zone and set is at the current zone for the Thread.
-  explicit StackZone(Thread* thread) : StackResource(thread), zone_() {
-    if (FLAG_trace_zones) {
-      OS::PrintErr("*** Starting a new Stack zone 0x%" Px "(0x%" Px ")\n",
-                   reinterpret_cast<intptr_t>(this),
-                   reinterpret_cast<intptr_t>(&zone_));
-    }
-    zone_.Link(thread->zone());
-    thread->set_zone(&zone_);
-  }
+  explicit StackZone(Thread* thread);
 
   // Delete all memory associated with the zone.
-  ~StackZone() {
-    ASSERT(thread()->zone() == &zone_);
-    thread()->set_zone(zone_.previous_);
-    if (FLAG_trace_zones) {
-      OS::PrintErr("*** Deleting Stack zone 0x%" Px "(0x%" Px ")\n",
-                   reinterpret_cast<intptr_t>(this),
-                   reinterpret_cast<intptr_t>(&zone_));
-    }
-  }
+  ~StackZone();
 
   // Compute the total size of this zone. This includes wasted space that is
   // due to internal fragmentation in the segments.
diff --git a/sdk/bin/dart2js b/sdk/bin/dart2js
index 17559bf..d2e9833 100755
--- a/sdk/bin/dart2js
+++ b/sdk/bin/dart2js
@@ -52,4 +52,4 @@
 
 DART2JS="$DART_ROOT/pkg/compiler/lib/src/dart2js.dart"
 
-exec "$DART" "${EXTRA_VM_OPTIONS[@]}" "$DART2JS" "${EXTRA_OPTIONS[@]}" "$@"
+exec "$DART" "--packages=$DART_ROOT/.packages" "${EXTRA_VM_OPTIONS[@]}" "$DART2JS" "${EXTRA_OPTIONS[@]}" "$@"
diff --git a/sdk/bin/dart2js.bat b/sdk/bin/dart2js.bat
index 4c6669a..7660182 100644
--- a/sdk/bin/dart2js.bat
+++ b/sdk/bin/dart2js.bat
@@ -39,7 +39,7 @@
 
 set DART2JS=%DART_ROOT%\pkg\compiler\lib\src\dart2js.dart
 
-"%DART%" %EXTRA_VM_OPTIONS% "%DART2JS%" %EXTRA_OPTIONS% %*
+"%DART%" "--packages=%DART_ROOT%\.packages" %EXTRA_VM_OPTIONS% "%DART2JS%" %EXTRA_OPTIONS% %*
 
 endlocal
 
diff --git a/sdk/bin/dartanalyzer b/sdk/bin/dartanalyzer
index c508c62..34ce895 100755
--- a/sdk/bin/dartanalyzer
+++ b/sdk/bin/dartanalyzer
@@ -45,4 +45,4 @@
 
 ANALYZER="$DART_ROOT/pkg/analyzer_cli/bin/analyzer.dart"
 
-exec "$DART" "${EXTRA_VM_OPTIONS[@]}" "$ANALYZER" "$SDK_ARG" "$@"
+exec "$DART" "--packages=$DART_ROOT/.packages" "${EXTRA_VM_OPTIONS[@]}" "$ANALYZER" "$SDK_ARG" "$@"
diff --git a/sdk/bin/dartanalyzer.bat b/sdk/bin/dartanalyzer.bat
index f03dfbd..4e8ba54 100644
--- a/sdk/bin/dartanalyzer.bat
+++ b/sdk/bin/dartanalyzer.bat
@@ -40,7 +40,7 @@
 
 set ANALYZER=%DART_ROOT%\pkg\analyzer_cli\bin\analyzer.dart
 
-"%DART%" %EXTRA_VM_OPTIONS% "%ANALYZER%" "%SDK_ARG%" %*
+"%DART%" "--packages=%DART_ROOT%\.packages" %EXTRA_VM_OPTIONS% "%ANALYZER%" "%SDK_ARG%" %*
 
 endlocal
 
diff --git a/sdk/bin/dartdevc b/sdk/bin/dartdevc
index 246f6b7..5b75ad2 100755
--- a/sdk/bin/dartdevc
+++ b/sdk/bin/dartdevc
@@ -45,4 +45,4 @@
 
 DEV_COMPILER="$DART_ROOT/pkg/dev_compiler/bin/dartdevc.dart"
 
-exec "$DART" "${EXTRA_VM_OPTIONS[@]}" "$DEV_COMPILER" "$SDK_ARG" "$@"
+exec "$DART" "--packages=$DART_ROOT/.packages" "${EXTRA_VM_OPTIONS[@]}" "$DEV_COMPILER" "$SDK_ARG" "$@"
diff --git a/sdk/bin/dartdevc.bat b/sdk/bin/dartdevc.bat
index 5c714ca..dd49b43 100644
--- a/sdk/bin/dartdevc.bat
+++ b/sdk/bin/dartdevc.bat
@@ -36,7 +36,7 @@
 
 set DEV_COMPILER=%DART_ROOT%\third_party\pkg\dev_compiler\bin\dartdevc.dart
 
-"%DART%" %EXTRA_VM_OPTIONS% "DEV_COMPILER%" "%SDK_ARG%" %*
+"%DART%" "--packages=%DART_ROOT%\.packages" %EXTRA_VM_OPTIONS% "DEV_COMPILER%" "%SDK_ARG%" %*
 
 endlocal
 
diff --git a/sdk/bin/dartfmt b/sdk/bin/dartfmt
index a671c50..ad54140 100755
--- a/sdk/bin/dartfmt
+++ b/sdk/bin/dartfmt
@@ -28,4 +28,4 @@
 
 DARTFMT="$DART_ROOT/third_party/pkg_tested/dart_style/bin/format.dart"
 
-exec "$DART" "$DARTFMT" "$@"
+exec "$DART" "--packages=$DART_ROOT/.packages" "$DARTFMT" "$@"
diff --git a/sdk/bin/dartfmt.bat b/sdk/bin/dartfmt.bat
index edab2dd..cd59302 100644
--- a/sdk/bin/dartfmt.bat
+++ b/sdk/bin/dartfmt.bat
@@ -27,7 +27,7 @@
 
 set DARTFMT=%DART_ROOT%\third_party\pkg_tested\dart_style\bin\format.dart
 
-"%DART%" "%DARTFMT%" %*
+"%DART%" "--packages=%DART_ROOT%\.packages" "%DARTFMT%" %*
 
 endlocal
 
diff --git a/sdk/bin/pub b/sdk/bin/pub
index 403635f..20e9d3d 100755
--- a/sdk/bin/pub
+++ b/sdk/bin/pub
@@ -82,4 +82,4 @@
 
 # Run pub.
 PUB="$SDK_DIR/../third_party/pkg/pub/bin/pub.dart"
-exec "$DART" "${VM_OPTIONS[@]}" "$PUB" "$@"
+exec "$DART" "--packages=$SDK_DIR/../.packages" "${VM_OPTIONS[@]}" "$PUB" "$@"
diff --git a/sdk/bin/pub.bat b/sdk/bin/pub.bat
index 03c7bf0..2ad2baa 100644
--- a/sdk/bin/pub.bat
+++ b/sdk/bin/pub.bat
@@ -35,7 +35,7 @@
 
 rem Run pub.
 set PUB="%SDK_DIR%\..\third_party\pkg\pub\bin\pub.dart"
-"%DART%" %VM_OPTIONS% "%PUB%" %*
+"%DART%" "--packages=%SDK_DIR%\..\.packages" %VM_OPTIONS% "%PUB%" %*
 
 endlocal
 
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index f4abf9a..9a9487a 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -1767,7 +1767,7 @@
   factory StreamIterator(Stream<T> stream)
       // TODO(lrn): use redirecting factory constructor when type
       // arguments are supported.
-      => new _StreamIteratorImpl<T>(stream);
+      => new _StreamIterator<T>(stream);
 
   /**
    * Wait for the next stream value to be available.
@@ -1809,7 +1809,7 @@
    * automatically closed, you must call [cancel] to ensure that the stream
    * is properly closed.
    *
-   * If [moveNext] has been called when the iterator is cancelled,
+   * If [moveNext] has been called when the iterator is canceled,
    * its returned future will complete with `false` as value,
    * as will all further calls to [moveNext].
    *
diff --git a/sdk/lib/async/stream_impl.dart b/sdk/lib/async/stream_impl.dart
index cb2e20d..7f89464 100644
--- a/sdk/lib/async/stream_impl.dart
+++ b/sdk/lib/async/stream_impl.dart
@@ -86,7 +86,6 @@
   static const int _STATE_IN_CALLBACK = 32;
   static const int _STATE_HAS_PENDING = 64;
   static const int _STATE_PAUSE_COUNT = 128;
-  static const int _STATE_PAUSE_COUNT_SHIFT = 7;
 
   /* Event handlers provided in constructor. */
   _DataHandler<T> _onData;
@@ -239,15 +238,6 @@
   }
 
   /**
-   * Increment the pause count.
-   *
-   * Also marks input as paused.
-   */
-  void _incrementPauseCount() {
-    _state = (_state + _STATE_PAUSE_COUNT) | _STATE_INPUT_PAUSED;
-  }
-
-  /**
    * Decrements the pause count.
    *
    * Does not automatically unpause the input (call [_onResume]) when
@@ -722,25 +712,6 @@
   }
 }
 
-class _BroadcastLinkedList {
-  _BroadcastLinkedList _next;
-  _BroadcastLinkedList _previous;
-
-  void _unlink() {
-    _previous._next = _next;
-    _next._previous = _previous;
-    _next = _previous = this;
-  }
-
-  void _insertBefore(_BroadcastLinkedList newNext) {
-    _BroadcastLinkedList newPrevious = newNext._previous;
-    newPrevious._next = this;
-    newNext._previous = _previous;
-    _previous._next = newNext;
-    _previous = newPrevious;
-  }
-}
-
 typedef void _BroadcastCallback<T>(StreamSubscription<T> subscription);
 
 /**
@@ -941,156 +912,139 @@
 
 /**
  * Simple implementation of [StreamIterator].
+ *
+ * Pauses the stream between calls to [moveNext].
  */
-class _StreamIteratorImpl<T> implements StreamIterator<T> {
-  // Internal state of the stream iterator.
-  // At any time, it is in one of these states.
-  // The interpretation of the [_futureOrPrefecth] field depends on the state.
-  // In _STATE_MOVING, the _data field holds the most recently returned
-  // future.
-  // When in one of the _STATE_EXTRA_* states, the it may hold the
-  // next data/error object, and the subscription is paused.
-
-  /// The simple state where [_data] holds the data to return, and [moveNext]
-  /// is allowed. The subscription is actively listening.
-  static const int _STATE_FOUND = 0;
-  /// State set after [moveNext] has returned false or an error,
-  /// or after calling [cancel]. The subscription is always canceled.
-  static const int _STATE_DONE = 1;
-  /// State set after calling [moveNext], but before its returned future has
-  /// completed. Calling [moveNext] again is not allowed in this state.
-  /// The subscription is actively listening.
-  static const int _STATE_MOVING = 2;
-  /// States set when another event occurs while in _STATE_FOUND.
-  /// This extra overflow event is cached until the next call to [moveNext],
-  /// which will complete as if it received the event normally.
-  /// The subscription is paused in these states, so we only ever get one
-  /// event too many.
-  static const int _STATE_EXTRA_DATA = 3;
-  static const int _STATE_EXTRA_ERROR = 4;
-  static const int _STATE_EXTRA_DONE = 5;
+class _StreamIterator<T> implements StreamIterator<T> {
+  // The stream iterator is always in one of four states.
+  // The value of the [_stateData] field depends on the state.
+  //
+  // When `_subscription == null` and `_stateData != null`:
+  // The stream iterator has been created, but [moveNext] has not been called
+  // yet. The [_stateData] field contains the stream to listen to on the first
+  // call to [moveNext] and [current] returns `null`.
+  //
+  // When `_subscription != null` and `!_isPaused`:
+  // The user has called [moveNext] and the iterator is waiting for the next
+  // event. The [_stateData] field contains the [_Future] returned by the
+  // [_moveNext] call and [current] returns `null.`
+  //
+  // When `_subscription != null` and `_isPaused`:
+  // The most recent call to [moveNext] has completed with a `true` value
+  // and [current] provides the value of the data event.
+  // The [_stateData] field contains the [current] value.
+  //
+  // When `_subscription == null` and `_stateData == null`:
+  // The stream has completed or been canceled using [cancel].
+  // The stream completes on either a done event or an error event.
+  // The last call to [moveNext] has completed with `false` and [current]
+  // returns `null`.
 
   /// Subscription being listened to.
+  ///
+  /// Set to `null` when the stream subscription is done or canceled.
   StreamSubscription _subscription;
 
-  /// The current element represented by the most recent call to moveNext.
+  /// Data value depending on the current state.
   ///
-  /// Is null between the time moveNext is called and its future completes.
-  T _current = null;
-
-  /// The future returned by the most recent call to [moveNext].
+  /// Before first call to [moveNext]: The stream to listen to.
   ///
-  /// Also used to store the next value/error in case the stream provides an
-  /// event before [moveNext] is called again. In that case, the stream will
-  /// be paused to prevent further events.
-  var/*Future<bool> or T*/ _futureOrPrefetch = null;
+  /// After calling [moveNext] but before the returned future completes:
+  /// The returned future.
+  ///
+  /// After calling [moveNext] and the returned future has completed
+  /// with `true`: The value of [current].
+  ///
+  /// After calling [moveNext] and the returned future has completed
+  /// with `false`, or after calling [cancel]: `null`.
+  Object _stateData;
 
-  /// The current state.
-  int _state = _STATE_FOUND;
+  /// Whether the iterator is between calls to `moveNext`.
+  /// This will usually cause the [_subscription] to be paused, but as an
+  /// optimization, we only pause after the [moveNext] future has been
+  /// completed.
+  bool _isPaused = false;
 
-  _StreamIteratorImpl(final Stream<T> stream) {
-    _subscription = stream.listen(_onData,
-                                  onError: _onError,
-                                  onDone: _onDone,
-                                  cancelOnError: true);
+  _StreamIterator(final Stream<T> stream) : _stateData = stream;
+
+  T get current {
+    if (_subscription != null && _isPaused) {
+      return _stateData as Object /*=T*/;
+    }
+    return null;
   }
 
-  T get current => _current;
-
   Future<bool> moveNext() {
-    if (_state == _STATE_DONE) {
-      return new _Future<bool>.immediate(false);
-    }
-    if (_state == _STATE_MOVING) {
+    if (_subscription != null) {
+      if (_isPaused) {
+        var future = new _Future<bool>();
+        _stateData = future;
+        _isPaused = false;
+        _subscription.resume();
+        return future;
+      }
       throw new StateError("Already waiting for next.");
     }
-    if (_state == _STATE_FOUND) {
-      _state = _STATE_MOVING;
-      _current = null;
-      var result = new _Future<bool>();
-      _futureOrPrefetch = result;
-      return result;
-    } else {
-      assert(_state >= _STATE_EXTRA_DATA);
-      switch (_state) {
-        case _STATE_EXTRA_DATA:
-          _state = _STATE_FOUND;
-          _current = _futureOrPrefetch as Object /*=T*/;
-          _futureOrPrefetch = null;
-          _subscription.resume();
-          return new _Future<bool>.immediate(true);
-        case _STATE_EXTRA_ERROR:
-          AsyncError prefetch = _futureOrPrefetch;
-          _clear();
-          return new _Future<bool>.immediateError(prefetch.error,
-                                                  prefetch.stackTrace);
-        case _STATE_EXTRA_DONE:
-          _clear();
-          return new _Future<bool>.immediate(false);
-      }
-    }
+    return _initializeOrDone();
   }
 
-  /** Clears up the internal state when the iterator ends. */
-  void _clear() {
-    _subscription = null;
-    _futureOrPrefetch = null;
-    _current = null;
-    _state = _STATE_DONE;
+  /// Called if there is no active subscription when [moveNext] is called.
+  ///
+  /// Either starts listening on the stream if this is the first call to
+  /// [moveNext], or returns a `false` future because the stream has already
+  /// ended.
+  Future<bool> _initializeOrDone() {
+    assert(_subscription == null);
+    var stateData = _stateData;
+    if (stateData != null) {
+      Stream<T> stream = stateData as Object /*=Stream<T>*/;
+      _subscription = stream.listen(
+          _onData, onError: _onError, onDone: _onDone, cancelOnError: true);
+      var future = new _Future<bool>();
+      _stateData = future;
+      return future;
+    }
+    return new _Future<bool>.immediate(false);
   }
 
   Future cancel() {
-    StreamSubscription subscription = _subscription;
-    if (subscription == null) return Future._nullFuture;
-    if (_state == _STATE_MOVING) {
-      _Future<bool> hasNext = _futureOrPrefetch as Object /*=_Future<bool>*/;
-      _clear();
-      hasNext._complete(false);
-    } else {
-      _clear();
+    StreamSubscription<T> subscription = _subscription;
+    Object stateData = _stateData;
+    _stateData = null;
+    if (subscription != null) {
+      _subscription = null;
+      if (!_isPaused) {
+        _Future<bool> future = stateData as Object /*=_Future<bool>*/;
+        future._asyncComplete(false);
+      }
+      return subscription.cancel();
     }
-    return subscription.cancel();
+    return Future._nullFuture;
   }
 
   void _onData(T data) {
-    if (_state == _STATE_MOVING) {
-      _current = data;
-      _Future<bool> hasNext = _futureOrPrefetch as Object /*=_Future<bool>*/;
-      _futureOrPrefetch = null;
-      _state = _STATE_FOUND;
-      hasNext._complete(true);
-      return;
-    }
-    _subscription.pause();
-    assert(_futureOrPrefetch == null);
-    _futureOrPrefetch = data;
-    _state = _STATE_EXTRA_DATA;
+    assert(_subscription != null && !_isPaused);
+    _Future<bool> moveNextFuture = _stateData as Object /*=_Future<bool>*/;
+    _stateData = data;
+    _isPaused = true;
+    moveNextFuture._complete(true);
+    if (_subscription != null && _isPaused) _subscription.pause();
   }
 
   void _onError(Object error, [StackTrace stackTrace]) {
-    if (_state == _STATE_MOVING) {
-      _Future<bool> hasNext = _futureOrPrefetch as Object /*=_Future<bool>*/;
-      // We have cancelOnError: true, so the subscription is canceled.
-      _clear();
-      hasNext._completeError(error, stackTrace);
-      return;
-    }
-    _subscription.pause();
-    assert(_futureOrPrefetch == null);
-    _futureOrPrefetch = new AsyncError(error, stackTrace);
-    _state = _STATE_EXTRA_ERROR;
+    assert(_subscription != null && !_isPaused);
+    _Future<bool> moveNextFuture = _stateData as Object /*=_Future<bool>*/;
+    _subscription = null;
+    _stateData = null;
+    moveNextFuture._completeError(error, stackTrace);
   }
 
   void _onDone() {
-     if (_state == _STATE_MOVING) {
-      _Future<bool> hasNext = _futureOrPrefetch as Object /*=_Future<bool>*/;
-      _clear();
-      hasNext._complete(false);
-      return;
-    }
-    _subscription.pause();
-    _futureOrPrefetch = null;
-    _state = _STATE_EXTRA_DONE;
+    assert(_subscription != null && !_isPaused);
+    _Future<bool> moveNextFuture = _stateData as Object /*=_Future<bool>*/;
+    _subscription = null;
+    _stateData = null;
+    moveNextFuture._complete(false);
   }
 }
 
diff --git a/sdk/lib/internal/iterable.dart b/sdk/lib/internal/iterable.dart
index 2bedb48..0e7b171 100644
--- a/sdk/lib/internal/iterable.dart
+++ b/sdk/lib/internal/iterable.dart
@@ -426,6 +426,10 @@
   WhereIterable(this._iterable, bool this._f(E element));
 
   Iterator<E> get iterator => new WhereIterator<E>(_iterable.iterator, _f);
+
+  // Specialization of [Iterable.map] to non-EfficientLength.
+  Iterable/*<T>*/ map/*<T>*/(/*=T*/ f(E element)) =>
+     new MappedIterable<E, dynamic/*=T*/>._(this, f);
 }
 
 class WhereIterator<E> extends Iterator<E> {
diff --git a/tests/compiler/dart2js/class_set_test.dart b/tests/compiler/dart2js/class_set_test.dart
index 52f436f..64442b1 100644
--- a/tests/compiler/dart2js/class_set_test.dart
+++ b/tests/compiler/dart2js/class_set_test.dart
@@ -50,7 +50,7 @@
       }
       """,
       useMockCompiler: false);
-  World world = env.compiler.world;
+  ClosedWorld world = env.compiler.closedWorld;
 
   ClassElement A = env.getElement("A");
   ClassElement B = env.getElement("B");
@@ -383,7 +383,7 @@
       }
       """,
       useMockCompiler: false);
-  World world = env.compiler.world;
+  ClosedWorld world = env.compiler.closedWorld;
 
   ClassElement A = env.getElement("A");
   ClassElement B = env.getElement("B");
diff --git a/tests/compiler/dart2js/compiler_helper.dart b/tests/compiler/dart2js/compiler_helper.dart
index ad2c0f7..c9bd508 100644
--- a/tests/compiler/dart2js/compiler_helper.dart
+++ b/tests/compiler/dart2js/compiler_helper.dart
@@ -75,7 +75,7 @@
     compiler.backend.enqueueHelpers(
         compiler.enqueuer.resolution, compiler.globalDependencies);
     compiler.processQueue(compiler.enqueuer.resolution, element);
-    compiler.world.populate();
+    compiler.openWorld.closeWorld();
     compiler.backend.onResolutionComplete();
     ResolutionWorkItem resolutionWork = new ResolutionWorkItem(element);
     resolutionWork.run(compiler, compiler.enqueuer.resolution);
@@ -210,17 +210,17 @@
   Expect.isNotNull(element, 'Could not locate $name');
   switch (how) {
     case 'exact':
-      return new types.TypeMask.exact(element, compiler.world);
+      return new types.TypeMask.exact(element, compiler.closedWorld);
     case 'nonNullExact':
-      return new types.TypeMask.nonNullExact(element, compiler.world);
+      return new types.TypeMask.nonNullExact(element, compiler.closedWorld);
     case 'subclass':
-      return new types.TypeMask.subclass(element, compiler.world);
+      return new types.TypeMask.subclass(element, compiler.closedWorld);
     case 'nonNullSubclass':
-      return new types.TypeMask.nonNullSubclass(element, compiler.world);
+      return new types.TypeMask.nonNullSubclass(element, compiler.closedWorld);
     case 'subtype':
-      return new types.TypeMask.subtype(element, compiler.world);
+      return new types.TypeMask.subtype(element, compiler.closedWorld);
     case 'nonNullSubtype':
-      return new types.TypeMask.nonNullSubtype(element, compiler.world);
+      return new types.TypeMask.nonNullSubtype(element, compiler.closedWorld);
   }
   Expect.fail('Unknown TypeMask constructor $how');
   return null;
diff --git a/tests/compiler/dart2js/concrete_type_inference_test.dart b/tests/compiler/dart2js/concrete_type_inference_test.dart
index 1be4e18..e3833ad 100644
--- a/tests/compiler/dart2js/concrete_type_inference_test.dart
+++ b/tests/compiler/dart2js/concrete_type_inference_test.dart
@@ -60,8 +60,8 @@
     Expect.identical(compiler.commonMasks.nullType, type);
   });
   checkPrintType('"foo"', (compiler, type) {
-    Expect.isTrue(
-        compiler.commonMasks.stringType.containsOnlyString(compiler.world));
+    Expect.isTrue(compiler.commonMasks.stringType
+        .containsOnlyString(compiler.closedWorld));
   });
 }
 
diff --git a/tests/compiler/dart2js/container_mask_equal_test.dart b/tests/compiler/dart2js/container_mask_equal_test.dart
index 54e71e1..21836b7 100644
--- a/tests/compiler/dart2js/container_mask_equal_test.dart
+++ b/tests/compiler/dart2js/container_mask_equal_test.dart
@@ -44,7 +44,7 @@
     element = compiler.mainApp.find('d');
     var mask4 = typesInferrer.getReturnTypeOfElement(element);
 
-    Expect.notEquals(
-        mask1.union(mask2, compiler.world), mask3.union(mask4, compiler.world));
+    Expect.notEquals(mask1.union(mask2, compiler.closedWorld),
+        mask3.union(mask4, compiler.closedWorld));
   });
 }
diff --git a/tests/compiler/dart2js/dictionary_types_test.dart b/tests/compiler/dart2js/dictionary_types_test.dart
index 2f52323..0a169d6 100644
--- a/tests/compiler/dart2js/dictionary_types_test.dart
+++ b/tests/compiler/dart2js/dictionary_types_test.dart
@@ -113,7 +113,8 @@
     });
     await compileAndTest("Union.dart", (types, getType, compiler) {
       Expect.equals(getType('nullOrInt'), types.uint31Type.nullable());
-      Expect.isTrue(getType('aString').containsOnlyString(compiler.world));
+      Expect
+          .isTrue(getType('aString').containsOnlyString(compiler.closedWorld));
       Expect.equals(getType('doubleOrNull'), types.doubleType.nullable());
     });
     await compileAndTest("ValueType.dart", (types, getType, compiler) {
diff --git a/tests/compiler/dart2js/exit_code_test.dart b/tests/compiler/dart2js/exit_code_test.dart
index e60072e..1ca76fc 100644
--- a/tests/compiler/dart2js/exit_code_test.dart
+++ b/tests/compiler/dart2js/exit_code_test.dart
@@ -152,7 +152,7 @@
 
   TestResolver(TestCompiler compiler, ConstantCompiler constantCompiler)
       : this.compiler = compiler,
-        super(compiler.resolution, constantCompiler, compiler.world,
+        super(compiler.resolution, constantCompiler, compiler.openWorld,
             compiler.measurer);
 
   void computeClassMembers(ClassElement element) {
diff --git a/tests/compiler/dart2js/expect_annotations_test.dart b/tests/compiler/dart2js/expect_annotations_test.dart
index 1d1a235..10ee78c 100644
--- a/tests/compiler/dart2js/expect_annotations_test.dart
+++ b/tests/compiler/dart2js/expect_annotations_test.dart
@@ -103,8 +103,8 @@
 
     TypeMask jsStringType = compiler.commonMasks.stringType;
     TypeMask jsIntType = compiler.commonMasks.intType;
-    TypeMask coreStringType =
-        new TypeMask.subtype(compiler.coreClasses.stringClass, compiler.world);
+    TypeMask coreStringType = new TypeMask.subtype(
+        compiler.coreClasses.stringClass, compiler.closedWorld);
 
     test('method');
     test('methodAssumeDynamic', expectAssumeDynamic: true);
diff --git a/tests/compiler/dart2js/field_type_simple_inferer_test.dart b/tests/compiler/dart2js/field_type_simple_inferer_test.dart
index 59ae877..03d7de3 100644
--- a/tests/compiler/dart2js/field_type_simple_inferer_test.dart
+++ b/tests/compiler/dart2js/field_type_simple_inferer_test.dart
@@ -522,7 +522,7 @@
   runTest(TEST_15, {
     'f': (types) {
       ClassElement cls = types.compiler.backend.helpers.jsIndexableClass;
-      return new TypeMask.nonNullSubtype(cls, types.compiler.world);
+      return new TypeMask.nonNullSubtype(cls, types.compiler.closedWorld);
     }
   });
   runTest(TEST_16, {'f': subclassOfInterceptor});
diff --git a/tests/compiler/dart2js/gvn_dynamic_field_get_test.dart b/tests/compiler/dart2js/gvn_dynamic_field_get_test.dart
index cf9deec..eb58e74 100644
--- a/tests/compiler/dart2js/gvn_dynamic_field_get_test.dart
+++ b/tests/compiler/dart2js/gvn_dynamic_field_get_test.dart
@@ -36,6 +36,7 @@
         var element = cls.lookupLocalMember(name);
         Expect.isNotNull(element);
         Selector selector = new Selector.getter(new PublicName(name));
-        Expect.isFalse(compiler.world.hasAnyUserDefinedGetter(selector, null));
+        Expect.isFalse(
+            compiler.closedWorld.hasAnyUserDefinedGetter(selector, null));
       }));
 }
diff --git a/tests/compiler/dart2js/jsinterop/world_test.dart b/tests/compiler/dart2js/jsinterop/world_test.dart
index 185e092..e994791 100644
--- a/tests/compiler/dart2js/jsinterop/world_test.dart
+++ b/tests/compiler/dart2js/jsinterop/world_test.dart
@@ -86,7 +86,7 @@
       return cls;
     }
 
-    ClassWorld world = env.compiler.world;
+    ClosedWorld world = env.compiler.closedWorld;
     JavaScriptBackend backend = env.compiler.backend;
     ClassElement Object_ = registerClass(env.compiler.coreClasses.objectClass);
     ClassElement Interceptor =
diff --git a/tests/compiler/dart2js/kernel/expressions_test.dart b/tests/compiler/dart2js/kernel/expressions_test.dart
new file mode 100644
index 0000000..7074c4c
--- /dev/null
+++ b/tests/compiler/dart2js/kernel/expressions_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2016, 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:test/test.dart';
+
+import 'helper.dart' show check;
+
+main() {
+  group('string literals', () {
+    test('juxtaposition', () {
+      return check('main() { return "abc" "def"; }');
+    });
+    test('literal interpolation', () {
+      return check('main() { return "abc\${1}def"; }');
+    });
+    test('complex interpolation', () {
+      String code = '''
+foo() => 1;
+main() => "abc\${foo()}"
+          "\${foo()}def";''';
+      return check(code);
+    });
+  });
+}
diff --git a/tests/compiler/dart2js/kernel/impact_test.dart b/tests/compiler/dart2js/kernel/impact_test.dart
index 9581e13..2716d53 100644
--- a/tests/compiler/dart2js/kernel/impact_test.dart
+++ b/tests/compiler/dart2js/kernel/impact_test.dart
@@ -6,18 +6,22 @@
 
 import 'dart:async';
 import 'package:async_helper/async_helper.dart';
-import 'package:compiler/src/common.dart';
 import 'package:compiler/src/commandline_options.dart';
+import 'package:compiler/src/common.dart';
+import 'package:compiler/src/common/names.dart';
 import 'package:compiler/src/common/resolution.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/elements/elements.dart';
+import 'package:compiler/src/resolution/registry.dart';
 import 'package:compiler/src/ssa/kernel_impact.dart';
 import 'package:compiler/src/serialization/equivalence.dart';
+import 'package:compiler/src/universe/feature.dart';
+import 'package:compiler/src/universe/use.dart';
 import '../memory_compiler.dart';
 import '../serialization/test_helper.dart';
 
 const Map<String, String> SOURCE = const <String, String>{
-  'main.dart': '''
+  'main.dart': r'''
 import 'helper.dart';
 
 main() {
@@ -28,6 +32,9 @@
   testInt();
   testDouble();
   testString();
+  testStringInterpolation();
+  testStringInterpolationConst();
+  testStringJuxtaposition();
   testSymbol();
   testEmptyListLiteral();
   testEmptyListLiteralDynamic();
@@ -50,12 +57,22 @@
   testIfThenElse();
   testTopLevelInvoke();
   testTopLevelInvokeTyped();
+  testTopLevelFunctionTyped();
+  testTopLevelFunctionGet();
   testTopLevelField();
   testTopLevelFieldTyped();
   testDynamicInvoke(null);
   testDynamicGet(null);
   testDynamicSet(null);
+  testLocalWithoutInitializer();
   testLocalWithInitializer();
+  testLocalWithInitializerTyped();
+  testLocalFunction();
+  testLocalFunctionTyped();
+  testLocalFunctionInvoke();
+  testLocalFunctionGet();
+  testClosure();
+  testClosureInvoke();
   testInvokeIndex(null);
   testInvokeIndexSet(null);
   testAssert();
@@ -64,6 +81,10 @@
   testFactoryInvokeGeneric();
   testFactoryInvokeGenericRaw();
   testFactoryInvokeGenericDynamic();
+  testRedirectingFactoryInvoke();
+  testRedirectingFactoryInvokeGeneric();
+  testRedirectingFactoryInvokeGenericRaw();
+  testRedirectingFactoryInvokeGenericDynamic();
 }
 
 testEmpty() {}
@@ -73,6 +94,11 @@
 testInt() => 42;
 testDouble() => 37.5;
 testString() => 'foo';
+testStringInterpolation() => '${0}';
+testStringInterpolationConst() {
+  const b = '${0}';
+}
+testStringJuxtaposition() => 'a' 'b';
 testSymbol() => #main;
 testEmptyListLiteral() => [];
 testEmptyListLiteralDynamic() => <dynamic>[];
@@ -132,6 +158,19 @@
   topLevelFunction3Typed(true, b: [13], c: {'14': true});
   topLevelFunction3Typed(false, c: {'16': false}, b: [17]);
 }
+
+topLevelFunctionTyped1(void a(num b)) {}
+topLevelFunctionTyped2(void a(num b, [String c])) {}
+topLevelFunctionTyped3(void a(num b, {String c, int d})) {}
+topLevelFunctionTyped4(void a(num b, {String d, int c})) {}
+testTopLevelFunctionTyped() {
+  topLevelFunctionTyped1(null);
+  topLevelFunctionTyped2(null);
+  topLevelFunctionTyped3(null);
+  topLevelFunctionTyped4(null);
+}
+testTopLevelFunctionGet() => topLevelFunction1;
+
 var topLevelField;
 testTopLevelField() => topLevelField;
 int topLevelFieldTyped;
@@ -149,9 +188,35 @@
 }
 testDynamicGet(o) => o.foo;
 testDynamicSet(o) => o.foo = 42;
+testLocalWithoutInitializer() {
+  var l;
+}
 testLocalWithInitializer() {
   var l = 42;
 }
+testLocalWithInitializerTyped() {
+  int l = 42;
+}
+testLocalFunction() {
+  localFunction() {}
+}
+testLocalFunctionTyped() {
+  int localFunction(String a) => 42;
+}
+testLocalFunctionInvoke() {
+  localFunction() {}
+  localFunction();
+}
+testLocalFunctionGet() {
+  localFunction() {}
+  localFunction;
+}
+testClosure() {
+  () {};
+}
+testClosureInvoke() {
+  () {} ();
+}
 testInvokeIndex(o) => o[42];
 testInvokeIndexSet(o) => o[42] = null;
 testAssert() {
@@ -172,13 +237,29 @@
 testFactoryInvokeGenericDynamic() {
   new GenericClass<dynamic, dynamic>.fact();
 }
+testRedirectingFactoryInvoke() {
+  new Class.redirect();
+}
+testRedirectingFactoryInvokeGeneric() {
+  new GenericClass<int, String>.redirect();
+}
+testRedirectingFactoryInvokeGenericRaw() {
+  new GenericClass.redirect();
+}
+testRedirectingFactoryInvokeGenericDynamic() {
+  new GenericClass<dynamic, dynamic>.redirect();
+}
 ''',
   'helper.dart': '''
 class Class {
+  Class.generative();
   factory Class.fact() => null;
+  factory Class.redirect() = Class.generative;
 }
 class GenericClass<X, Y> {
+  GenericClass.generative();
   factory GenericClass.fact() => null;
+  factory GenericClass.redirect() = GenericClass.generative;
 }
 ''',
 };
@@ -213,7 +294,37 @@
 
 void checkElement(Compiler compiler, AstElement element) {
   ResolutionImpact astImpact = compiler.resolution.getResolutionImpact(element);
+  astImpact = laxImpact(element, astImpact);
   ResolutionImpact kernelImpact = build(compiler, element.resolvedAst);
   testResolutionImpactEquivalence(
       astImpact, kernelImpact, const CheckStrategy());
 }
+
+/// Lax the precision of [impact] to meet expectancy of the corresponding impact
+/// generated from kernel.
+ResolutionImpact laxImpact(AstElement element, ResolutionImpact impact) {
+  ResolutionWorldImpactBuilder builder =
+      new ResolutionWorldImpactBuilder('Lax impact of ${element}');
+  impact.staticUses.forEach(builder.registerStaticUse);
+  impact.dynamicUses.forEach(builder.registerDynamicUse);
+  impact.typeUses.forEach(builder.registerTypeUse);
+  impact.constantLiterals.forEach(builder.registerConstantLiteral);
+  impact.constSymbolNames.forEach(builder.registerConstSymbolName);
+  impact.listLiterals.forEach(builder.registerListLiteral);
+  impact.mapLiterals.forEach(builder.registerMapLiteral);
+  for (Feature feature in impact.features) {
+    builder.registerFeature(feature);
+    switch (feature) {
+      case Feature.STRING_INTERPOLATION:
+      case Feature.STRING_JUXTAPOSITION:
+        // These are both converted into a string concatenation in kernel so
+        // we cannot tell the diferrence.
+        builder.registerFeature(Feature.STRING_INTERPOLATION);
+        builder.registerFeature(Feature.STRING_JUXTAPOSITION);
+        break;
+      default:
+    }
+  }
+  impact.nativeData.forEach(builder.registerNativeData);
+  return builder;
+}
diff --git a/tests/compiler/dart2js/kernel/literals_test.dart b/tests/compiler/dart2js/kernel/literals_test.dart
index bf84989..4bdf271 100644
--- a/tests/compiler/dart2js/kernel/literals_test.dart
+++ b/tests/compiler/dart2js/kernel/literals_test.dart
@@ -16,7 +16,7 @@
   test('compile function that returns a literal map', () {
     return check('main() { return {"a": 1, "b": 2, "c": 3}; }');
   });
-  test('compile function that returns a literal map', () {
+  test('compile function that returns a const map', () {
     return check('main() { return const {"a": 1, "b": 2, "c": 3}; }');
   });
 }
diff --git a/tests/compiler/dart2js/kernel/loops_test.dart b/tests/compiler/dart2js/kernel/loops_test.dart
new file mode 100644
index 0000000..6535e95
--- /dev/null
+++ b/tests/compiler/dart2js/kernel/loops_test.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2016, 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:test/test.dart';
+
+import 'helper.dart' show check;
+
+main() {
+  test('for-loop', () {
+    String code = '''
+main() {
+  var a = 0;
+  for (var i = 0; i < 10; i++) {
+    a += i;
+  }
+  return a;
+}''';
+    return check(code);
+  });
+
+  test('while-loop', () {
+    String code = '''
+main() {
+  var a = 0;
+  while (a < 100) {
+    a *= 2;
+  }
+  return a;
+}''';
+    return check(code);
+  });
+}
diff --git a/tests/compiler/dart2js/kernel/visitor_test.dart b/tests/compiler/dart2js/kernel/visitor_test.dart
new file mode 100644
index 0000000..1edd591
--- /dev/null
+++ b/tests/compiler/dart2js/kernel/visitor_test.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Test that the dart2js copy of [KernelVisitor] generates the expected IR as
+/// defined by kernel spec-mode test files.
+
+import 'dart:io';
+import 'package:compiler/src/compiler.dart' show Compiler;
+import 'package:compiler/src/js_backend/backend.dart' show JavaScriptBackend;
+import 'package:compiler/src/commandline_options.dart' show Flags;
+import 'package:kernel/ast.dart';
+import 'package:kernel/text/ast_to_text.dart';
+import 'package:kernel/transformations/mixin_full_resolution.dart';
+import 'package:path/path.dart' as pathlib;
+import 'package:test/test.dart';
+
+import '../memory_compiler.dart';
+
+const String TESTCASE_DIR = 'third_party/pkg/kernel/testcases/';
+
+const List<String> SKIP_TESTS = const <String>[];
+
+main(List<String> arguments) {
+  Directory directory = new Directory('${TESTCASE_DIR}/input');
+  for (FileSystemEntity file in directory.listSync()) {
+    if (file is File && file.path.endsWith('.dart')) {
+      String name = pathlib.basenameWithoutExtension(file.path);
+      bool selected = arguments.contains(name);
+      if (!selected) {
+        if (arguments.isNotEmpty) continue;
+        if (SKIP_TESTS.contains(name)) continue;
+      }
+
+      test(name, () async {
+        var result = await runCompiler(
+            entryPoint: file.absolute.uri,
+            options: [Flags.analyzeOnly, Flags.useKernel]);
+        Compiler compiler = result.compiler;
+        JavaScriptBackend backend = compiler.backend;
+        StringBuffer buffer = new StringBuffer();
+        Program program = backend.kernelTask.program;
+        new MixinFullResolution().transform(program);
+        new Printer(buffer).writeLibraryFile(
+            backend.kernelTask.program.mainMethod.enclosingLibrary);
+        String actual = buffer.toString();
+        String expected =
+            new File('${TESTCASE_DIR}/spec-mode/$name.baseline.txt')
+                .readAsStringSync();
+        if (selected) {
+          String input =
+              new File('${TESTCASE_DIR}/input/$name.dart').readAsStringSync();
+          print('============================================================');
+          print(name);
+          print('--input-----------------------------------------------------');
+          print(input);
+          print('--expected--------------------------------------------------');
+          print(expected);
+          print('--actual----------------------------------------------------');
+          print(actual);
+        }
+        expect(actual, equals(expected));
+      });
+    }
+  }
+}
diff --git a/tests/compiler/dart2js/map_tracer_test.dart b/tests/compiler/dart2js/map_tracer_test.dart
index 1f8e806..6c4af67 100644
--- a/tests/compiler/dart2js/map_tracer_test.dart
+++ b/tests/compiler/dart2js/map_tracer_test.dart
@@ -211,7 +211,7 @@
   Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(generateTest(allocation), uri,
       expectedErrors: 0, expectedWarnings: 1);
-  var classWorld = compiler.world;
+  var classWorld = compiler.openWorld.closeWorld();
   asyncTest(() => compiler.run(uri).then((_) {
         var keyType, valueType;
         var commonMasks = compiler.commonMasks;
diff --git a/tests/compiler/dart2js/patch_test.dart b/tests/compiler/dart2js/patch_test.dart
index f981843..3990949 100644
--- a/tests/compiler/dart2js/patch_test.dart
+++ b/tests/compiler/dart2js/patch_test.dart
@@ -920,8 +920,7 @@
       """,
       runCompiler: true,
       analyzeOnly: true);
-  World world = compiler.world;
-  world.populate();
+  ClosedWorld world = compiler.openWorld.closeWorld();
 
   ClassElement cls = ensure(
       compiler, "A", compiler.commonElements.coreLibrary.find,
@@ -943,7 +942,7 @@
   TypeMask typeMask = new TypeMask.exact(cls, world);
   FunctionElement method = cls.implementation.lookupLocalMember('method');
   method.computeType(compiler.resolution);
-  Expect.isTrue(selector.applies(method, world));
+  Expect.isTrue(selector.applies(method, world.backend));
   Expect.isTrue(typeMask.canHit(method, selector, world));
 
   // Check that the declaration method in the declaration class is a target
@@ -953,7 +952,7 @@
   typeMask = new TypeMask.exact(cls, world);
   method = cls.lookupLocalMember('clear');
   method.computeType(compiler.resolution);
-  Expect.isTrue(selector.applies(method, world));
+  Expect.isTrue(selector.applies(method, world.backend));
   Expect.isTrue(typeMask.canHit(method, selector, world));
 
   // Check that the declaration method in the declaration class is a target
@@ -961,7 +960,7 @@
   cls = ensure(compiler, "B", compiler.commonElements.coreLibrary.find);
   cls.ensureResolved(compiler.resolution);
   typeMask = new TypeMask.exact(cls, world);
-  Expect.isTrue(selector.applies(method, world));
+  Expect.isTrue(selector.applies(method, world.backend));
   Expect.isTrue(typeMask.canHit(method, selector, world));
 }
 
diff --git a/tests/compiler/dart2js/related_types.dart b/tests/compiler/dart2js/related_types.dart
index 7d56a65..09b28ea 100644
--- a/tests/compiler/dart2js/related_types.dart
+++ b/tests/compiler/dart2js/related_types.dart
@@ -35,6 +35,7 @@
 
 /// Check all loaded libraries in [compiler] for unrelated types.
 void checkRelatedTypes(Compiler compiler) {
+  compiler.openWorld.closeWorld();
   for (LibraryElement library in compiler.libraryLoader.libraries) {
     checkLibraryElement(compiler, library);
   }
@@ -76,7 +77,7 @@
       : this.resolvedAst = resolvedAst,
         super(resolvedAst.elements);
 
-  ClassWorld get world => compiler.world;
+  ClosedWorld get world => compiler.closedWorld;
 
   CoreClasses get coreClasses => compiler.coreClasses;
 
diff --git a/tests/compiler/dart2js/related_types_test.dart b/tests/compiler/dart2js/related_types_test.dart
index f5209b2..38449bc 100644
--- a/tests/compiler/dart2js/related_types_test.dart
+++ b/tests/compiler/dart2js/related_types_test.dart
@@ -267,6 +267,7 @@
     Expect.isFalse(
         collector.hasRegularMessages, "Unexpected analysis messages.");
     Compiler compiler = result.compiler;
+    compiler.openWorld.closeWorld();
 
     void checkMember(MemberElement member) {
       if (!member.name.startsWith('test_')) return;
diff --git a/tests/compiler/dart2js/serialization/model_test_helper.dart b/tests/compiler/dart2js/serialization/model_test_helper.dart
index 6952d35..90cde97 100644
--- a/tests/compiler/dart2js/serialization/model_test_helper.dart
+++ b/tests/compiler/dart2js/serialization/model_test_helper.dart
@@ -73,7 +73,7 @@
     compilerNormal.resolution.retainCachesForTesting = true;
     await compilerNormal.run(entryPoint);
     compilerNormal.phase = Compiler.PHASE_DONE_RESOLVING;
-    compilerNormal.world.populate();
+    compilerNormal.openWorld.closeWorld();
     compilerNormal.backend.onResolutionComplete();
     compilerNormal.deferredLoadTask
         .onResolutionComplete(compilerNormal.mainFunction);
@@ -89,7 +89,7 @@
     compilerDeserialized.resolution.retainCachesForTesting = true;
     await compilerDeserialized.run(entryPoint);
     compilerDeserialized.phase = Compiler.PHASE_DONE_RESOLVING;
-    compilerDeserialized.world.populate();
+    compilerDeserialized.openWorld.closeWorld();
     compilerDeserialized.backend.onResolutionComplete();
     compilerDeserialized.deferredLoadTask
         .onResolutionComplete(compilerDeserialized.mainFunction);
@@ -132,9 +132,9 @@
     checkClassHierarchyNodes(
         compilerNormal,
         compilerDeserialized,
-        compilerNormal.world
+        compilerNormal.closedWorld
             .getClassHierarchyNode(compilerNormal.coreClasses.objectClass),
-        compilerDeserialized.world.getClassHierarchyNode(
+        compilerDeserialized.closedWorld.getClassHierarchyNode(
             compilerDeserialized.coreClasses.objectClass),
         verbose: verbose);
 
@@ -271,8 +271,8 @@
     ClassElement class2,
     {bool verbose: false}) {
   checkSets(
-      compiler1.world.mixinUsesOf(class1),
-      compiler2.world.mixinUsesOf(class2),
+      compiler1.closedWorld.mixinUsesOf(class1),
+      compiler2.closedWorld.mixinUsesOf(class2),
       "Mixin uses of $class1 vs $class2",
       areElementsEquivalent,
       verbose: verbose);
@@ -312,9 +312,9 @@
       if (child.isInstantiated) {
         print('Missing subclass ${child.cls} of ${node1.cls} '
             'in ${node2.directSubclasses}');
-        print(compiler1.world
+        print(compiler1.closedWorld
             .dump(verbose ? compiler1.coreClasses.objectClass : node1.cls));
-        print(compiler2.world
+        print(compiler2.closedWorld
             .dump(verbose ? compiler2.coreClasses.objectClass : node2.cls));
       }
       Expect.isFalse(
diff --git a/tests/compiler/dart2js/serialization/test_helper.dart b/tests/compiler/dart2js/serialization/test_helper.dart
index db97fc4..f081bbd 100644
--- a/tests/compiler/dart2js/serialization/test_helper.dart
+++ b/tests/compiler/dart2js/serialization/test_helper.dart
@@ -240,7 +240,8 @@
   Set remaining = computeSetDifference(set1, set2, common, unfound,
       sameElement: sameElement, checkElements: onSameElement);
   if (unfound.isNotEmpty || remaining.isNotEmpty) {
-    String message = "Set mismatch for `$property` on $object1 vs $object2: \n"
+    String message = "Set mismatch for `$property` on\n"
+        "$object1\n vs\n$object2:\n"
         "Common:\n ${common.join('\n ')}\n"
         "Unfound:\n ${unfound.join('\n ')}\n"
         "Extra: \n ${remaining.join('\n ')}";
diff --git a/tests/compiler/dart2js/simple_inferrer_closure_test.dart b/tests/compiler/dart2js/simple_inferrer_closure_test.dart
index 1ca210e..5a12baa 100644
--- a/tests/compiler/dart2js/simple_inferrer_closure_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_closure_test.dart
@@ -154,6 +154,6 @@
 
         var cls = findElement(compiler, 'A');
         checkReturnInClass(
-            'A', 'foo', new TypeMask.nonNullExact(cls, compiler.world));
+            'A', 'foo', new TypeMask.nonNullExact(cls, compiler.closedWorld));
       }));
 }
diff --git a/tests/compiler/dart2js/simple_inferrer_const_closure_default_test.dart b/tests/compiler/dart2js/simple_inferrer_const_closure_default_test.dart
index 33fdc43..0a97f95 100644
--- a/tests/compiler/dart2js/simple_inferrer_const_closure_default_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_const_closure_default_test.dart
@@ -7,8 +7,6 @@
 import 'compiler_helper.dart';
 import 'type_mask_test_helper.dart';
 
-
-
 const String TEST = """
 
 // [defaultFn_i] is called only via [foo_i]'s default value with a small integer.
@@ -40,45 +38,70 @@
 }
 """;
 
-
 void main() {
   Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(TEST, uri);
   asyncTest(() => compiler.run(uri).then((_) {
-    var typesInferrer = compiler.globalInference.typesInferrer;
+        var typesInferrer = compiler.globalInference.typesInferrer;
 
-    checkArgument(String functionName, type) {
-      var functionElement = findElement(compiler, functionName);
-      var signature = functionElement.functionSignature;
-      var element = signature.requiredParameterCount > 0
-          ? signature.requiredParameters.first
-          : signature.optionalParameters.first;
-      Expect.equals(type,
-          simplify(typesInferrer.getTypeOfElement(element), compiler),
-          functionName);
-    }
+        checkArgument(String functionName, type) {
+          var functionElement = findElement(compiler, functionName);
+          var signature = functionElement.functionSignature;
+          var element = signature.requiredParameterCount > 0
+              ? signature.requiredParameters.first
+              : signature.optionalParameters.first;
+          Expect.equals(
+              type,
+              simplify(typesInferrer.getTypeOfElement(element), compiler),
+              functionName);
+        }
 
-    checkOptionalArgument(String functionName, type) {
-      var functionElement = findElement(compiler, functionName);
-      var signature = functionElement.functionSignature;
-      var element = signature.optionalParameters.first;
-      Expect.equals(type,
-          simplify(typesInferrer.getTypeOfElement(element), compiler),
-          functionName);
-    }
+        checkOptionalArgument(String functionName, type) {
+          var functionElement = findElement(compiler, functionName);
+          var signature = functionElement.functionSignature;
+          var element = signature.optionalParameters.first;
+          Expect.equals(
+              type,
+              simplify(typesInferrer.getTypeOfElement(element), compiler),
+              functionName);
+        }
 
-    checkArgument('foo1', compiler.commonMasks.functionType);   /// 01: ok
-    checkArgument('foo2', compiler.commonMasks.functionType);   /// 02: ok
-    checkArgument('foo3', compiler.commonMasks.functionType);   /// 03: ok
-    checkArgument('foo4', compiler.commonMasks.functionType);   /// 04: ok
-    checkArgument('foo5', compiler.commonMasks.dynamicType);    /// 05: ok
-    checkArgument('foo6', compiler.commonMasks.dynamicType);    /// 06: ok
+        checkArgument('foo1', compiler.commonMasks.functionType);
 
-    checkArgument('defaultFn1', compiler.commonMasks.uint31Type);   /// 07: ok
-    checkArgument('defaultFn2', compiler.commonMasks.uint31Type);   /// 08: ok
-    checkArgument('defaultFn3', compiler.commonMasks.uint31Type);   /// 09: ok
-    checkArgument('defaultFn4', compiler.commonMasks.uint31Type);   /// 10: ok
-    checkArgument('defaultFn5', compiler.commonMasks.uint31Type);   /// 11: ok
-    checkArgument('defaultFn6', compiler.commonMasks.uint31Type);   /// 12: ok
-  }));
+        /// 01: ok
+        checkArgument('foo2', compiler.commonMasks.functionType);
+
+        /// 02: ok
+        checkArgument('foo3', compiler.commonMasks.functionType);
+
+        /// 03: ok
+        checkArgument('foo4', compiler.commonMasks.functionType);
+
+        /// 04: ok
+        checkArgument('foo5', compiler.commonMasks.dynamicType);
+
+        /// 05: ok
+        checkArgument('foo6', compiler.commonMasks.dynamicType);
+
+        /// 06: ok
+
+        checkArgument('defaultFn1', compiler.commonMasks.uint31Type);
+
+        /// 07: ok
+        checkArgument('defaultFn2', compiler.commonMasks.uint31Type);
+
+        /// 08: ok
+        checkArgument('defaultFn3', compiler.commonMasks.uint31Type);
+
+        /// 09: ok
+        checkArgument('defaultFn4', compiler.commonMasks.uint31Type);
+
+        /// 10: ok
+        checkArgument('defaultFn5', compiler.commonMasks.uint31Type);
+
+        /// 11: ok
+        checkArgument('defaultFn6', compiler.commonMasks.uint31Type);
+
+        /// 12: ok
+      }));
 }
diff --git a/tests/compiler/dart2js/simple_inferrer_test.dart b/tests/compiler/dart2js/simple_inferrer_test.dart
index 70270da..ccb07a8 100644
--- a/tests/compiler/dart2js/simple_inferrer_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_test.dart
@@ -729,7 +729,7 @@
   asyncTest(() => compiler.run(uri).then((_) {
         var commonMasks = compiler.commonMasks;
         var typesInferrer = compiler.globalInference.typesInferrer;
-        var world = compiler.world;
+        var world = compiler.closedWorld;
 
         checkReturn(String name, type) {
           var element = findElement(compiler, name);
@@ -761,7 +761,7 @@
         checkReturn('returnEmpty1', const TypeMask.nonNullEmpty());
         checkReturn('returnEmpty2', const TypeMask.nonNullEmpty());
         TypeMask intType = new TypeMask.nonNullSubtype(
-            compiler.coreClasses.intClass, compiler.world);
+            compiler.coreClasses.intClass, compiler.closedWorld);
         checkReturn('testIsCheck1', intType);
         checkReturn('testIsCheck2', intType);
         checkReturn('testIsCheck3', intType.nullable());
@@ -796,7 +796,7 @@
         checkReturn(
             'returnAsString',
             new TypeMask.subtype(
-                compiler.coreClasses.stringClass, compiler.world));
+                compiler.coreClasses.stringClass, compiler.closedWorld));
         checkReturn('returnIntAsNum', commonMasks.uint31Type);
         checkReturn('returnAsTypedef', commonMasks.functionType.nullable());
         checkReturn('returnTopLevelGetter', commonMasks.uint31Type);
@@ -806,7 +806,7 @@
             'testSwitch1',
             simplify(
                 commonMasks.intType
-                    .union(commonMasks.doubleType, compiler.world)
+                    .union(commonMasks.doubleType, compiler.closedWorld)
                     .nullable(),
                 compiler));
         checkReturn('testSwitch2', commonMasks.uint31Type);
diff --git a/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart b/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart
index f17308b..28c8fde 100644
--- a/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart
@@ -186,7 +186,7 @@
         checkReturn(
             'returnInt6',
             new TypeMask.nonNullSubtype(
-                compiler.coreClasses.intClass, compiler.world));
+                compiler.coreClasses.intClass, compiler.closedWorld));
 
         var subclassOfInterceptor =
             findTypeMask(compiler, 'Interceptor', 'nonNullSubclass');
diff --git a/tests/compiler/dart2js/subtypeset_test.dart b/tests/compiler/dart2js/subtypeset_test.dart
index 38bac61..1f0fd7f 100644
--- a/tests/compiler/dart2js/subtypeset_test.dart
+++ b/tests/compiler/dart2js/subtypeset_test.dart
@@ -47,7 +47,7 @@
       """,
               useMockCompiler: false)
           .then((env) {
-        World world = env.compiler.world;
+        ClosedWorld world = env.compiler.closedWorld;
 
         ClassElement A = env.getElement("A");
         ClassElement B = env.getElement("B");
diff --git a/tests/compiler/dart2js/trust_type_annotations_test.dart b/tests/compiler/dart2js/trust_type_annotations_test.dart
index 6e86bc0..c140fed 100644
--- a/tests/compiler/dart2js/trust_type_annotations_test.dart
+++ b/tests/compiler/dart2js/trust_type_annotations_test.dart
@@ -58,17 +58,18 @@
           var element = classA.lookupMember(name);
           var mask = typesInferrer.getReturnTypeOfElement(element);
           Expect.isTrue(type.containsMask(
-              typesInferrer.getReturnTypeOfElement(element), compiler.world));
+              typesInferrer.getReturnTypeOfElement(element),
+              compiler.closedWorld));
         }
 
         checkType(String name, type) {
           var element = classA.lookupMember(name);
           Expect.isTrue(type.containsMask(
-              typesInferrer.getTypeOfElement(element), compiler.world));
+              typesInferrer.getTypeOfElement(element), compiler.closedWorld));
         }
 
-        var intMask =
-            new TypeMask.subtype(compiler.coreClasses.intClass, compiler.world);
+        var intMask = new TypeMask.subtype(
+            compiler.coreClasses.intClass, compiler.closedWorld);
 
         checkReturn('foo', intMask);
         checkReturn('faa', intMask);
diff --git a/tests/compiler/dart2js/type_combination_test.dart b/tests/compiler/dart2js/type_combination_test.dart
index 5a32503..f15d471f 100644
--- a/tests/compiler/dart2js/type_combination_test.dart
+++ b/tests/compiler/dart2js/type_combination_test.dart
@@ -100,8 +100,8 @@
 }
 
 void testUnion(MockCompiler compiler) {
-  RuleSet ruleSet = new RuleSet(
-      'union', (t1, t2) => simplify(t1.union(t2, compiler.world), compiler));
+  RuleSet ruleSet = new RuleSet('union',
+      (t1, t2) => simplify(t1.union(t2, compiler.closedWorld), compiler));
   rule(type1, type2, result) => ruleSet.rule(type1, type2, result);
   check(type1, type2, predicate) => ruleSet.check(type1, type2, predicate);
 
@@ -414,7 +414,7 @@
   JavaScriptBackend backend = compiler.backend;
   BackendHelpers helpers = backend.helpers;
   RuleSet ruleSet = new RuleSet(
-      'intersection', (t1, t2) => t1.intersection(t2, compiler.world));
+      'intersection', (t1, t2) => t1.intersection(t2, compiler.closedWorld));
   rule(type1, type2, result) => ruleSet.rule(type1, type2, result);
 
   rule(emptyType, emptyType, emptyType);
@@ -555,9 +555,9 @@
   rule(jsIndexable, nonPrimitive1, emptyType);
   rule(jsIndexable, nonPrimitive2, emptyType);
   rule(jsIndexable, potentialArray,
-      new TypeMask.nonNullSubtype(helpers.jsArrayClass, compiler.world));
+      new TypeMask.nonNullSubtype(helpers.jsArrayClass, compiler.closedWorld));
   rule(jsIndexable, potentialString,
-      new TypeMask.nonNullSubtype(helpers.jsStringClass, compiler.world));
+      new TypeMask.nonNullSubtype(helpers.jsStringClass, compiler.closedWorld));
   rule(jsIndexable, jsBooleanOrNull, emptyType);
   rule(jsIndexable, jsNumberOrNull, emptyType);
   rule(jsIndexable, jsIntegerOrNull, emptyType);
@@ -723,9 +723,9 @@
 
 void testRegressions(MockCompiler compiler) {
   TypeMask nonNullPotentialString =
-      new TypeMask.nonNullSubtype(patternClass, compiler.world);
+      new TypeMask.nonNullSubtype(patternClass, compiler.closedWorld);
   Expect.equals(potentialString,
-      jsStringOrNull.union(nonNullPotentialString, compiler.world));
+      jsStringOrNull.union(nonNullPotentialString, compiler.closedWorld));
 }
 
 void main() {
@@ -736,7 +736,7 @@
     """);
     JavaScriptBackend backend = compiler.backend;
     BackendHelpers helpers = backend.helpers;
-    World world = compiler.world;
+    ClosedWorld world = compiler.openWorld.closeWorld();
     helpers.interceptorsLibrary.forEachLocalMember((element) {
       if (element.isClass) {
         element.ensureResolved(compiler.resolution);
@@ -753,7 +753,7 @@
         compiler.enqueuer.resolution, compiler.globalDependencies);
     backend.registerInstantiatedType(patternImplClass.rawType,
         compiler.enqueuer.resolution, compiler.globalDependencies);
-    compiler.world.populate();
+    compiler.openWorld.closeWorld();
 
     // Grab hold of a supertype for String so we can produce potential
     // string types.
diff --git a/tests/compiler/dart2js/type_mask2_test.dart b/tests/compiler/dart2js/type_mask2_test.dart
index 648cf76..78791cb 100644
--- a/tests/compiler/dart2js/type_mask2_test.dart
+++ b/tests/compiler/dart2js/type_mask2_test.dart
@@ -10,7 +10,7 @@
 import 'type_test_helper.dart';
 import 'package:compiler/src/elements/elements.dart' show Element, ClassElement;
 import 'package:compiler/src/types/types.dart';
-import 'package:compiler/src/world.dart' show ClassWorld;
+import 'package:compiler/src/world.dart' show ClosedWorld;
 
 isCheckedMode() {
   try {
@@ -29,14 +29,14 @@
   });
 }
 
-checkMasks(ClassWorld classWorld, List<ClassElement> allClasses,
+checkMasks(ClosedWorld closedWorld, List<ClassElement> allClasses,
     List<FlatTypeMask> masks,
     {FlatTypeMask result,
     List<FlatTypeMask> disjointMasks,
     FlatTypeMask flattened,
     List<ClassElement> containedClasses}) {
   List<FlatTypeMask> disjoint = <FlatTypeMask>[];
-  UnionTypeMask.unionOfHelper(masks, disjoint, classWorld);
+  UnionTypeMask.unionOfHelper(masks, disjoint, closedWorld);
   Expect.listEquals(disjointMasks, disjoint,
       'Unexpected disjoint masks: $disjoint, expected $disjointMasks.');
   if (flattened == null) {
@@ -45,19 +45,19 @@
     // reliably tested.
     if (isCheckedMode()) {
       Expect.throws(
-          () => UnionTypeMask.flatten(disjoint, classWorld),
+          () => UnionTypeMask.flatten(disjoint, closedWorld),
           (e) => e is AssertionError,
           'Expect assertion failure on flattening of $disjoint.');
     }
   } else {
-    TypeMask flattenResult = UnionTypeMask.flatten(disjoint, classWorld);
+    TypeMask flattenResult = UnionTypeMask.flatten(disjoint, closedWorld);
     Expect.equals(
         flattened,
         flattenResult,
         'Unexpected flattening of $disjoint: '
         '$flattenResult, expected $flattened.');
   }
-  var union = UnionTypeMask.unionOf(masks, classWorld);
+  var union = UnionTypeMask.unionOf(masks, closedWorld);
   if (result == null) {
     Expect.isTrue(union is UnionTypeMask,
         'Expected union of $masks to be a union-type: $union.');
@@ -73,10 +73,10 @@
   if (containedClasses != null) {
     for (ClassElement cls in allClasses) {
       if (containedClasses.contains(cls)) {
-        Expect.isTrue(union.contains(cls, classWorld),
+        Expect.isTrue(union.contains(cls, closedWorld),
             'Expected $union to contain $cls.');
       } else {
-        Expect.isFalse(union.contains(cls, classWorld),
+        Expect.isFalse(union.contains(cls, closedWorld),
             '$union not expected to contain $cls.');
       }
     }
@@ -104,7 +104,7 @@
       """,
       useMockCompiler: false);
 
-  ClassWorld classWorld = env.compiler.world;
+  ClosedWorld closedWorld = env.compiler.closedWorld;
 
   ClassElement Object_ = env.getElement("Object");
   ClassElement A = env.getElement("A");
@@ -120,7 +120,7 @@
       List<FlatTypeMask> disjointMasks,
       FlatTypeMask flattened,
       List<ClassElement> containedClasses}) {
-    return checkMasks(classWorld, allClasses, masks,
+    return checkMasks(closedWorld, allClasses, masks,
         result: result,
         disjointMasks: disjointMasks,
         flattened: flattened,
@@ -128,15 +128,15 @@
   }
 
   TypeMask empty = const TypeMask.nonNullEmpty();
-  TypeMask subclassObject = new TypeMask.nonNullSubclass(Object_, classWorld);
-  TypeMask exactA = new TypeMask.nonNullExact(A, classWorld);
-  TypeMask subclassA = new TypeMask.nonNullSubclass(A, classWorld);
-  TypeMask subtypeA = new TypeMask.nonNullSubtype(A, classWorld);
-  TypeMask exactB = new TypeMask.nonNullExact(B, classWorld);
-  TypeMask subclassB = new TypeMask.nonNullSubclass(B, classWorld);
-  TypeMask exactC = new TypeMask.nonNullExact(C, classWorld);
-  TypeMask exactD = new TypeMask.nonNullExact(D, classWorld);
-  TypeMask exactE = new TypeMask.nonNullExact(E, classWorld);
+  TypeMask subclassObject = new TypeMask.nonNullSubclass(Object_, closedWorld);
+  TypeMask exactA = new TypeMask.nonNullExact(A, closedWorld);
+  TypeMask subclassA = new TypeMask.nonNullSubclass(A, closedWorld);
+  TypeMask subtypeA = new TypeMask.nonNullSubtype(A, closedWorld);
+  TypeMask exactB = new TypeMask.nonNullExact(B, closedWorld);
+  TypeMask subclassB = new TypeMask.nonNullSubclass(B, closedWorld);
+  TypeMask exactC = new TypeMask.nonNullExact(C, closedWorld);
+  TypeMask exactD = new TypeMask.nonNullExact(D, closedWorld);
+  TypeMask exactE = new TypeMask.nonNullExact(E, closedWorld);
 
   check([], result: empty, disjointMasks: [], containedClasses: []);
 
@@ -213,7 +213,7 @@
       }
       """,
       useMockCompiler: false);
-  var classWorld = env.compiler.world;
+  var closedWorld = env.compiler.closedWorld;
   var backend = env.compiler.backend;
 
   ClassElement Object_ = env.getElement("Object");
@@ -222,23 +222,23 @@
 
   List<ClassElement> allClasses = <ClassElement>[Object_, String_];
 
-  Expect.isFalse(classWorld.isDirectlyInstantiated(Object_));
-  Expect.isTrue(classWorld.isIndirectlyInstantiated(Object_));
-  Expect.isTrue(classWorld.isInstantiated(Object_));
+  Expect.isFalse(closedWorld.isDirectlyInstantiated(Object_));
+  Expect.isTrue(closedWorld.isIndirectlyInstantiated(Object_));
+  Expect.isTrue(closedWorld.isInstantiated(Object_));
 
-  Expect.isFalse(classWorld.isDirectlyInstantiated(String_));
-  Expect.isFalse(classWorld.isIndirectlyInstantiated(String_));
-  Expect.isFalse(classWorld.isInstantiated(String_));
+  Expect.isFalse(closedWorld.isDirectlyInstantiated(String_));
+  Expect.isFalse(closedWorld.isIndirectlyInstantiated(String_));
+  Expect.isFalse(closedWorld.isInstantiated(String_));
 
-  Expect.isTrue(classWorld.isDirectlyInstantiated(JSString));
-  Expect.isFalse(classWorld.isIndirectlyInstantiated(JSString));
-  Expect.isTrue(classWorld.isInstantiated(JSString));
+  Expect.isTrue(closedWorld.isDirectlyInstantiated(JSString));
+  Expect.isFalse(closedWorld.isIndirectlyInstantiated(JSString));
+  Expect.isTrue(closedWorld.isInstantiated(JSString));
 
-  TypeMask subtypeString = new TypeMask.nonNullSubtype(String_, classWorld);
-  TypeMask exactJSString = new TypeMask.nonNullExact(JSString, classWorld);
-  TypeMask subtypeJSString = new TypeMask.nonNullSubtype(JSString, classWorld);
+  TypeMask subtypeString = new TypeMask.nonNullSubtype(String_, closedWorld);
+  TypeMask exactJSString = new TypeMask.nonNullExact(JSString, closedWorld);
+  TypeMask subtypeJSString = new TypeMask.nonNullSubtype(JSString, closedWorld);
   TypeMask subclassJSString =
-      new TypeMask.nonNullSubclass(JSString, classWorld);
+      new TypeMask.nonNullSubclass(JSString, closedWorld);
 
   Expect.equals(exactJSString, subtypeString);
   Expect.equals(exactJSString, subtypeJSString);
diff --git a/tests/compiler/dart2js/type_mask_disjoint_test.dart b/tests/compiler/dart2js/type_mask_disjoint_test.dart
index f27ac57..7c643a5 100644
--- a/tests/compiler/dart2js/type_mask_disjoint_test.dart
+++ b/tests/compiler/dart2js/type_mask_disjoint_test.dart
@@ -36,7 +36,7 @@
 
 Uri uri = new Uri(scheme: 'source');
 var compiler = compilerFor(CODE, uri);
-var world = compiler.world;
+var world = compiler.closedWorld;
 
 main() {
   asyncTest(() => compiler.run(uri).then((_) {
diff --git a/tests/compiler/dart2js/type_mask_test.dart b/tests/compiler/dart2js/type_mask_test.dart
index 29a89ce..00508d1 100644
--- a/tests/compiler/dart2js/type_mask_test.dart
+++ b/tests/compiler/dart2js/type_mask_test.dart
@@ -21,7 +21,7 @@
 main() {
   Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(CODE, uri);
-  var classWorld = compiler.world;
+  var classWorld = compiler.openWorld.closeWorld();
 
   asyncTest(() => compiler.run(uri).then((_) {
         var classA = findElement(compiler, 'A');
diff --git a/tests/compiler/dart2js/type_mask_test_helper.dart b/tests/compiler/dart2js/type_mask_test_helper.dart
index 0d2d41d..a6c8604 100644
--- a/tests/compiler/dart2js/type_mask_test_helper.dart
+++ b/tests/compiler/dart2js/type_mask_test_helper.dart
@@ -11,7 +11,7 @@
   if (mask is ForwardingTypeMask) {
     return simplify(mask.forwardTo, compiler);
   } else if (mask is UnionTypeMask) {
-    return UnionTypeMask.flatten(mask.disjointMasks, compiler.world);
+    return UnionTypeMask.flatten(mask.disjointMasks, compiler.closedWorld);
   } else {
     return mask;
   }
diff --git a/tests/compiler/dart2js/union_type_test.dart b/tests/compiler/dart2js/union_type_test.dart
index 2d18f18..336ce10 100644
--- a/tests/compiler/dart2js/union_type_test.dart
+++ b/tests/compiler/dart2js/union_type_test.dart
@@ -22,8 +22,7 @@
       }
       """,
         useMockCompiler: false);
-    World world = env.compiler.world;
-    world.populate();
+    ClosedWorld world = env.compiler.openWorld.closeWorld();
     FlatTypeMask mask1 = new FlatTypeMask.exact(env.getElement('A'));
     FlatTypeMask mask2 = new FlatTypeMask.exact(env.getElement('B'));
     UnionTypeMask union1 = mask1.nonNullable().union(mask2, world);
diff --git a/tests/compiler/dart2js/world_test.dart b/tests/compiler/dart2js/world_test.dart
index b80f0c0..c68e05a 100644
--- a/tests/compiler/dart2js/world_test.dart
+++ b/tests/compiler/dart2js/world_test.dart
@@ -10,7 +10,7 @@
 import 'package:compiler/src/common.dart';
 import 'package:compiler/src/elements/elements.dart' show Element, ClassElement;
 import 'package:compiler/src/universe/class_set.dart';
-import 'package:compiler/src/world.dart' show ClassWorld;
+import 'package:compiler/src/world.dart' show ClosedWorld;
 
 void main() {
   asyncTest(() async {
@@ -44,7 +44,7 @@
       }
       """,
       useMockCompiler: false);
-  ClassWorld classWorld = env.compiler.world;
+  ClosedWorld closedWorld = env.compiler.closedWorld;
 
   ClassElement Object_ = env.getElement("Object");
   ClassElement A = env.getElement("A");
@@ -64,7 +64,7 @@
           foundClasses.contains(expectedClass),
           "Expect $expectedClass in '$property' on $cls. "
           "Found:\n ${foundClasses.join('\n ')}\n"
-          "${env.compiler.world.dump(cls)}");
+          "${env.compiler.closedWorld.dump(cls)}");
     }
     if (exact) {
       Expect.equals(
@@ -73,7 +73,7 @@
           "Unexpected classes "
           "${foundClasses.where((c) => !expectedClasses.contains(c))} "
           "in '$property' on $cls.\n"
-          "${env.compiler.world.dump(cls)}");
+          "${env.compiler.closedWorld.dump(cls)}");
     }
   }
 
@@ -99,38 +99,38 @@
           expectedClasses.length,
           count,
           "Unexpected class count in '$property' on $cls.\n"
-          "${env.compiler.world.dump(cls)}");
+          "${env.compiler.closedWorld.dump(cls)}");
     }
   }
 
   void testSubclasses(ClassElement cls, List<ClassElement> expectedClasses,
       {bool exact: true}) {
-    check('subclassesOf', cls, classWorld.subclassesOf(cls), expectedClasses,
+    check('subclassesOf', cls, closedWorld.subclassesOf(cls), expectedClasses,
         exact: exact);
   }
 
   void testStrictSubclasses(
       ClassElement cls, List<ClassElement> expectedClasses,
       {bool exact: true}) {
-    check('strictSubclassesOf', cls, classWorld.strictSubclassesOf(cls),
+    check('strictSubclassesOf', cls, closedWorld.strictSubclassesOf(cls),
         expectedClasses,
         exact: exact,
-        forEach: classWorld.forEachStrictSubclassOf,
-        getCount: classWorld.strictSubclassCount);
+        forEach: closedWorld.forEachStrictSubclassOf,
+        getCount: closedWorld.strictSubclassCount);
   }
 
   void testStrictSubtypes(ClassElement cls, List<ClassElement> expectedClasses,
       {bool exact: true}) {
-    check('strictSubtypesOf', cls, classWorld.strictSubtypesOf(cls),
+    check('strictSubtypesOf', cls, closedWorld.strictSubtypesOf(cls),
         expectedClasses,
         exact: exact,
-        forEach: classWorld.forEachStrictSubtypeOf,
-        getCount: classWorld.strictSubtypeCount);
+        forEach: closedWorld.forEachStrictSubtypeOf,
+        getCount: closedWorld.strictSubtypeCount);
   }
 
   void testMixinUses(ClassElement cls, List<ClassElement> expectedClasses,
       {bool exact: true}) {
-    check('mixinUsesOf', cls, classWorld.mixinUsesOf(cls), expectedClasses,
+    check('mixinUsesOf', cls, closedWorld.mixinUsesOf(cls), expectedClasses,
         exact: exact);
   }
 
@@ -234,13 +234,13 @@
       }
       """,
       useMockCompiler: false);
-  ClassWorld classWorld = env.compiler.world;
+  ClosedWorld closedWorld = env.compiler.closedWorld;
 
   check(String name, {bool hasStrictSubtype, bool hasOnlySubclasses}) {
     ClassElement cls = env.getElement(name);
-    Expect.equals(hasStrictSubtype, classWorld.hasAnyStrictSubtype(cls),
+    Expect.equals(hasStrictSubtype, closedWorld.hasAnyStrictSubtype(cls),
         "Unexpected hasAnyStrictSubtype property on $cls.");
-    Expect.equals(hasOnlySubclasses, classWorld.hasOnlySubclasses(cls),
+    Expect.equals(hasOnlySubclasses, closedWorld.hasOnlySubclasses(cls),
         "Unexpected hasOnlySubclasses property on $cls.");
   }
 
diff --git a/tests/compiler/dart2js_extra/mirrors_used_warning_test.dart b/tests/compiler/dart2js_extra/mirrors_used_warning_test.dart
index 4a8a649..9a4eeaa 100644
--- a/tests/compiler/dart2js_extra/mirrors_used_warning_test.dart
+++ b/tests/compiler/dart2js_extra/mirrors_used_warning_test.dart
@@ -24,15 +24,12 @@
   Expect.equals("foo", new A().foo);
   Expect.isTrue(lines.isEmpty);
   var barResult = new A().bar;
-  Expect.equals("bar", barResult);
-
-  /// minif: ok
+  Expect.equals("bar", barResult);          /// minif: ok
+  
   Expect.isTrue(lines.length == 1);
   var line = lines.first;
   Expect.isTrue(line.contains("Warning") &&
-      line.contains("bar") &&
-
-      /// minif: continued
+      line.contains("bar") &&               /// minif: continued
       line.contains("minif"));
 }
 
diff --git a/tests/compiler/dart2js_native/dispatch_property_initialization_test.dart b/tests/compiler/dart2js_native/dispatch_property_initialization_test.dart
new file mode 100644
index 0000000..174eaf8
--- /dev/null
+++ b/tests/compiler/dart2js_native/dispatch_property_initialization_test.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test for initialization of dispatchPropertyName.
+
+import "package:expect/expect.dart";
+import 'dart:_foreign_helper' show JS;
+import 'dart:_js_helper' show Native;
+
+@Native("Foo")
+class Foo {
+  String method(String x) native;
+}
+
+makeFoo() native;
+
+void setup() native r"""
+function Foo() {}
+Foo.prototype.method = function(x) { return 'Foo ' + x; }
+
+self.makeFoo = function() { return new Foo(); }
+""";
+
+
+main() {
+  setup();
+
+  // If the dispatchPropertyName is uninitialized, it will be `undefined` or
+  // `null` instead of the secret string or Symbol. These properties on
+  // `Object.prototype` will be retrieved by the lookup instead of `undefined`
+  // for the dispatch record.
+  JS('', r'self.Object.prototype["undefined"] = {}');
+  JS('', r'self.Object.prototype["null"] = {}');
+  Expect.equals('Foo A', makeFoo().method('A'));
+
+  // Slightly different version that has malformed dispatch records.
+  JS('', r'self.Object.prototype["undefined"] = {p: false}');
+  JS('', r'self.Object.prototype["null"] = {p: false}');
+  Expect.equals('Foo B', makeFoo().method('B'));
+}
diff --git a/tests/compiler/dart2js_native/foreign_test.dart b/tests/compiler/dart2js_native/foreign_test.dart
index dcefa26..e2a4c4e 100644
--- a/tests/compiler/dart2js_native/foreign_test.dart
+++ b/tests/compiler/dart2js_native/foreign_test.dart
@@ -22,7 +22,7 @@
 }
 
 foreign11(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) {
-  return JS("num", r"# + # + # + # + # + # + # + # + # + # + #",
+  return JS("num|String", r"# + # + # + # + # + # + # + # + # + # + #",
       a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11);
 }
 
diff --git a/tests/compiler/dart2js_native/load_elim_refinement_test.dart b/tests/compiler/dart2js_native/load_elim_refinement_test.dart
new file mode 100644
index 0000000..026b142
--- /dev/null
+++ b/tests/compiler/dart2js_native/load_elim_refinement_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+import 'dart:_foreign_helper' show JS;
+
+class A {
+  int a;
+}
+
+class B extends A {
+  int b;
+}
+
+@NoInline()
+escape(v) { g = v; }
+var g;
+
+main() {
+  g = new A();
+  var a = JS('returns:A;new:true', '(1,#)', new B());
+
+  a.a = 1;
+  if (a is B) {
+    escape(a);  // Here we need to escape 'a' not the refinement of a to B.
+    g.a = 2;
+    Expect.equals(2, a.a);
+  }
+}
diff --git a/tests/html/js_dispatch_property_test.dart b/tests/html/js_dispatch_property_test.dart
new file mode 100644
index 0000000..ebcd2af
--- /dev/null
+++ b/tests/html/js_dispatch_property_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test for dart2js initialization of dispatchPropertyName.
+
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
+
+import 'package:expect/expect.dart' show NoInline, AssumeDynamic;
+
+import 'js_dispatch_property_test_lib.dart';
+
+@NoInline() @AssumeDynamic()
+confuse(x) => x;
+
+main() {
+  useHtmlConfiguration();
+
+  group('group', () {
+    test('test', () {
+      // Force dynamic interceptor dispatch.
+      var a = confuse(create());
+      expect(a.foo('A'), equals('Foo A'));
+    });
+  });
+}
diff --git a/tests/html/js_dispatch_property_test.html b/tests/html/js_dispatch_property_test.html
new file mode 100644
index 0000000..c17424b
--- /dev/null
+++ b/tests/html/js_dispatch_property_test.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<--
+// Copyright (c) 2016, 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.
+-->
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> js_type_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+</head>
+<body>
+  <h1> Running js_type_test </h1>
+  <script type="text/javascript"
+      src="/root_dart/tests/html/js_dispatch_property_test_js.js"></script>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/html/js_dispatch_property_test_js.js b/tests/html/js_dispatch_property_test_js.js
new file mode 100644
index 0000000..8f10dcc
--- /dev/null
+++ b/tests/html/js_dispatch_property_test_js.js
@@ -0,0 +1,17 @@
+// Copyright (c) 2016, 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.
+
+self.create = function() {
+  return {
+    // If the dispatch property name is uninitialized, it will be `undefined` or
+    // `null`, which will match these properties on dispatch record
+    // lookup. These properties map to malformed dispatch records to force an
+    // error.
+
+    'undefined': {p: false},
+    'null': {p: false},
+
+    foo: function(x) { return 'Foo ' + x; },
+  };
+}
diff --git a/tests/html/js_dispatch_property_test_lib.dart b/tests/html/js_dispatch_property_test_lib.dart
new file mode 100644
index 0000000..77e371c
--- /dev/null
+++ b/tests/html/js_dispatch_property_test_lib.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2016, 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.
+
+@JS()
+library js_dispatch_property_test_lib;
+
+import 'package:js/js.dart';
+
+@JS()
+external A create();
+
+@JS() @anonymous
+class A {
+  external String foo(String x);
+}
diff --git a/tests/language/async_star_pause_test.dart b/tests/language/async_star_pause_test.dart
new file mode 100644
index 0000000..c21519d
--- /dev/null
+++ b/tests/language/async_star_pause_test.dart
@@ -0,0 +1,32 @@
+// 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.
+
+library async_star_pause_test;
+
+import "package:unittest/unittest.dart";
+import "dart:async";
+
+main() {
+  test("await for pauses stream during body", () async {
+    // Assumes await-for uses streamIterator.
+    var log = [];
+    var s = () async* {
+      for (int i = 0; i < 3; i++) {
+        log.add("$i-");
+        yield i;
+        // Should pause here until next iteration of await-for loop.
+        log.add("$i+");
+      }
+    }();
+    await for (var i in s) {
+      log.add("$i?");
+      await nextMicrotask();
+      log.add("$i!");
+    }
+    expect(log, ["0-", "0?", "0!", "0+",
+                 "1-", "1?", "1!", "1+",
+                 "2-", "2?", "2!", "2+"]);
+  });
+}
+Future nextMicrotask() => new Future.microtask((){});
diff --git a/tests/language/async_star_test.dart b/tests/language/async_star_test.dart
index c30f50e..fb7d2e4 100644
--- a/tests/language/async_star_test.dart
+++ b/tests/language/async_star_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library async_start_test;
+library async_star_test;
 
 import "package:unittest/unittest.dart";
 import "dart:async";
diff --git a/tests/language/language.status b/tests/language/language.status
index 001cf0e..de99e84 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -5,9 +5,15 @@
 # This directory contains tests that are intended to show the
 # current state of the language.
 
+[ ($compiler == dart2app || $compiler == dart2appjit) ]
+string_literals_test: Skip # Issue 27433
+
 [ ($compiler == none || $compiler == precompiler || $compiler == dart2app || $compiler == dart2appjit) ]
 tearoff_constructor_basic_test: Skip # Crashes in checked mode -- hausner investigating
 
+# This is OK for now, but we may want to change the semantics to match the test.
+async_star_pause_test: Fail, OK
+
 # These tests are skipped in the VM because it has "--supermixin"
 # functionality enabled unconditionally.  The tests should be removed
 # once the same is true for analyzer (#24478) and dart2js (#23773)
diff --git a/tests/language/string_literals_test.dart b/tests/language/string_literals_test.dart
new file mode 100644
index 0000000..4f7cc04
--- /dev/null
+++ b/tests/language/string_literals_test.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2016, 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";
+
+main() {
+  var expect = new String.fromCharCodes([
+    0, 0x0a, 0x0d, 0x7f, 0xff, 0xffff, 0xd800, 0xdc00, 0xdbff, 0xdfff
+  ]);
+  test(string) {
+    Expect.equals(expect, string);
+  }
+
+  // Plain escapes of code points.
+  test("\x00\x0a\x0d\x7f\xff\uffff\u{10000}\u{10ffff}");
+  test("""\x00\x0a\x0d\x7f\xff\uffff\u{10000}\u{10ffff}""");
+  test('\x00\x0a\x0d\x7f\xff\uffff\u{10000}\u{10ffff}');
+  test('''\x00\x0a\x0d\x7f\xff\uffff\u{10000}\u{10ffff}''');
+  // Plain escapes of individual code units.
+  test("\x00\x0a\x0d\x7f\xff\uffff\ud800\udc00\udbff\udfff");
+  test("""\x00\x0a\x0d\x7f\xff\uffff\ud800\udc00\udbff\udfff""");
+  test('\x00\x0a\x0d\x7f\xff\uffff\ud800\udc00\udbff\udfff');
+  test('''\x00\x0a\x0d\x7f\xff\uffff\ud800\udc00\udbff\udfff''');
+  // Insert newline into multiline string.
+  test("""\x00
+\x0d\x7f\xff\uffff\ud800\udc00\udbff\udfff""");
+  test('''\x00
+\x0d\x7f\xff\uffff\ud800\udc00\udbff\udfff''');
+  // Extract code points from multi-character escape string.
+  test("\x00\x0a\x0d\x7f\xff\uffff"
+       "${"\u{10000}"[0]}${"\u{10000}"[1]}"
+       "${"\u{10FFFF}"[0]}${"\u{10FFFF}"[1]}");
+  test("\x00\x0a\x0d\x7f\xff\uffff" +
+      "\ud800" + "\udc00\udbff" + "\udfff");
+  // Single line string over multiple lines with newlines inside interpolation.
+  test("\x00\x0a\x0d\x7f\xff${
+           ""
+       }\uffff\ud800\udc00\udbff\udfff");
+}
diff --git a/tests/language/string_unicode4_negative_test.dart b/tests/language/string_unicode4_negative_test.dart
index b4ee30f..c7bdf60 100644
--- a/tests/language/string_unicode4_negative_test.dart
+++ b/tests/language/string_unicode4_negative_test.dart
@@ -5,10 +5,8 @@
 class StringUnicode4NegativeTest {
 
   static testMain() {
-    // Unicode escapes must refer to valid Unicode points and not surrogate characters
+    // Unicode escapes must refer to valid Unicode points.
     String str = "Foo\u{FFFFFF}";
-    str = "Foo\uD800";
-    str = "Foo\uDC00";
   }
 }
 
diff --git a/tests/language/vm/lazy_deopt_with_exception_test.dart b/tests/language/vm/lazy_deopt_with_exception_test.dart
new file mode 100644
index 0000000..a494366
--- /dev/null
+++ b/tests/language/vm/lazy_deopt_with_exception_test.dart
@@ -0,0 +1,64 @@
+// Copyright (c) 2016, 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 deoptimization on an optimistically hoisted smi check.
+// VMOptions=--optimization-counter-threshold=10  --no-background-compilation --enable-inlining-annotations
+
+// Test that lazy deoptimization works if the program returns to a function
+// that is scheduled for lazy deoptimization via an exception.
+
+import 'package:expect/expect.dart';
+
+class C {
+  var x = 42;
+}
+
+
+const NeverInline = "NeverInline";
+
+@NeverInline
+AA(C c, bool b) {
+  if (b) {
+    c.x = 2.5;
+    throw 123;
+  }
+}
+
+@NeverInline
+T1(C c, bool b) {
+  try {
+    AA(c, b);
+  } on dynamic {
+  }
+  return c.x + 1;
+}
+
+
+@NeverInline
+T2(C c, bool b) {
+  try {
+    AA(c, b);
+  } on String {
+    Expect.isTrue(false);
+  } on int catch(e) {
+    Expect.equals(e, 123);
+    Expect.equals(b, true);
+    Expect.equals(c.x, 2.5);
+  }
+  return c.x + 1;
+}
+
+
+main() {
+  var c = new C();
+  for (var i = 0; i < 10000; ++i) {
+    T1(c, false);
+    T2(c, false);
+  }
+  Expect.equals(43, T1(c, false));
+  Expect.equals(43, T2(c, false));
+  Expect.equals(3.5, T1(c, true));
+  Expect.equals(3.5, T2(c, true));
+}
+
+
diff --git a/tests/standalone/io/skipping_dart2js_compilations_test.dart b/tests/standalone/io/skipping_dart2js_compilations_test.dart
index 27d896f..c175383 100644
--- a/tests/standalone/io/skipping_dart2js_compilations_test.dart
+++ b/tests/standalone/io/skipping_dart2js_compilations_test.dart
@@ -165,6 +165,9 @@
 }
 
 void main() {
+  // This script is in [sdk]/tests/standalone/io.
+  suite.TestUtils.setDartDirUri(Platform.script.resolve('../../..'));
+
   var fs_noTestJs = new FileUtils(createJs: false,
                                   createJsDeps: true,
                                   createDart: true,
diff --git a/tests/standalone/io/socket_invalid_arguments_test.dart b/tests/standalone/io/socket_invalid_arguments_test.dart
index 803e106..4bc34b6 100644
--- a/tests/standalone/io/socket_invalid_arguments_test.dart
+++ b/tests/standalone/io/socket_invalid_arguments_test.dart
@@ -20,12 +20,17 @@
 
 testSocketCreation(host, port) {
   asyncStart();
-  Socket.connect(host, port)
-      .then((socket) => Expect.fail("Shouldn't get connected"))
-      .catchError((e) {
-        Expect.isTrue(e is ArgumentError || e is SocketException);
-        asyncEnd();
-      });
+  try {
+    Socket.connect(host, port)
+        .then((socket) => Expect.fail("Shouldn't get connected"))
+        .catchError((e) {
+          Expect.isTrue(e is ArgumentError || e is SocketException);
+          asyncEnd();
+        });
+  } catch (e) {
+    Expect.isTrue(e is ArgumentError || e is SocketException);
+    asyncEnd();
+  }
 }
 
 testAdd(buffer) {
@@ -71,6 +76,8 @@
   testSocketCreation(123, 123);
   testSocketCreation("string", null);
   testSocketCreation(null, null);
+  testSocketCreation("localhost", -1);
+  testSocketCreation("localhost", 65536);
   testAdd(null);
   testAdd(new NotAList());
   testAdd(42);
@@ -82,4 +89,6 @@
   testServerSocketCreation(123, 123, 123);
   testServerSocketCreation("string", null, null);
   testServerSocketCreation("string", 123, null);
+  testServerSocketCreation("localhost", -1, 123);
+  testServerSocketCreation("localhost", 65536, 123);
 }
diff --git a/tests/standalone/io/test_runner_test.dart b/tests/standalone/io/test_runner_test.dart
index b216562..d4d6076 100644
--- a/tests/standalone/io/test_runner_test.dart
+++ b/tests/standalone/io/test_runner_test.dart
@@ -141,6 +141,8 @@
 }
 
 void main(List<String> arguments) {
+  // This script is in [sdk]/tests/standalone/io.
+  TestUtils.setDartDirUri(Platform.script.resolve('../../..'));
   // Run the test_runner_test if there are no command-line options.
   // Otherwise, run one of the component tests that always pass,
   // fail, or timeout.
diff --git a/tests/standalone/package/scenarios/empty_packages_file/empty_packages_file_noimports_test.dart b/tests/standalone/package/scenarios/empty_packages_file/empty_packages_file_noimports_test.dart
index 580bb01..afaeff5 100644
--- a/tests/standalone/package/scenarios/empty_packages_file/empty_packages_file_noimports_test.dart
+++ b/tests/standalone/package/scenarios/empty_packages_file/empty_packages_file_noimports_test.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// PackageRoot=none
 // Packages=.packages
 
 // We expect this to not cause any errors. An empty packages file is valid,
diff --git a/tests/standalone/package/scenarios/empty_packages_file/empty_packages_file_option_test.dart b/tests/standalone/package/scenarios/empty_packages_file/empty_packages_file_option_test.dart
index 38fff19..88fa49b 100644
--- a/tests/standalone/package/scenarios/empty_packages_file/empty_packages_file_option_test.dart
+++ b/tests/standalone/package/scenarios/empty_packages_file/empty_packages_file_option_test.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// PackageRoot=none
 // Packages=.packages
 
 library empty_packages_file_option_test;
diff --git a/tests/standalone/package/scenarios/invalid/invalid_package_name_test.dart b/tests/standalone/package/scenarios/invalid/invalid_package_name_test.dart
index ef37f27..4c278c9 100644
--- a/tests/standalone/package/scenarios/invalid/invalid_package_name_test.dart
+++ b/tests/standalone/package/scenarios/invalid/invalid_package_name_test.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// PackageRoot=none
 // Packages=invalid_package_name.packages
 
 library invalid_package_name_test;
diff --git a/tests/standalone/package/scenarios/invalid/invalid_utf8_test.dart b/tests/standalone/package/scenarios/invalid/invalid_utf8_test.dart
index 0d93b35..2200e96 100644
--- a/tests/standalone/package/scenarios/invalid/invalid_utf8_test.dart
+++ b/tests/standalone/package/scenarios/invalid/invalid_utf8_test.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// PackageRoot=none
 // Packages=invalid_utf8.packages
 
 library invalid_utf8_test;
diff --git a/tests/standalone/package/scenarios/invalid/non_existent_packages_file_test.dart b/tests/standalone/package/scenarios/invalid/non_existent_packages_file_test.dart
index 7c333f7..72a9c65 100644
--- a/tests/standalone/package/scenarios/invalid/non_existent_packages_file_test.dart
+++ b/tests/standalone/package/scenarios/invalid/non_existent_packages_file_test.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// PackageRoot=none
 // Packages=non_existent.packages
 
 library non_existent_packages_file_test;
diff --git a/tests/standalone/package/scenarios/invalid/same_package_twice_test.dart b/tests/standalone/package/scenarios/invalid/same_package_twice_test.dart
index e539e71..b3eae8d 100644
--- a/tests/standalone/package/scenarios/invalid/same_package_twice_test.dart
+++ b/tests/standalone/package/scenarios/invalid/same_package_twice_test.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// PackageRoot=none
 // Packages=same_package_twice.packages
 
 library same_package_twice_test;
diff --git a/tests/standalone/package/scenarios/packages_file_strange_formatting/empty_lines_test.dart b/tests/standalone/package/scenarios/packages_file_strange_formatting/empty_lines_test.dart
index a5ec547..665597a 100644
--- a/tests/standalone/package/scenarios/packages_file_strange_formatting/empty_lines_test.dart
+++ b/tests/standalone/package/scenarios/packages_file_strange_formatting/empty_lines_test.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// PackageRoot=none
 // Packages=empty_lines.packages
 
 library empty_lines_test;
diff --git a/tests/standalone/package/scenarios/packages_file_strange_formatting/empty_package_dir_test.dart b/tests/standalone/package/scenarios/packages_file_strange_formatting/empty_package_dir_test.dart
index 5c7eb39..6c65971 100644
--- a/tests/standalone/package/scenarios/packages_file_strange_formatting/empty_package_dir_test.dart
+++ b/tests/standalone/package/scenarios/packages_file_strange_formatting/empty_package_dir_test.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// PackageRoot=none
 // Packages=empty_package_dir.packages
 
 // In this test, we give a packages file that associates the package 'foo' with
diff --git a/tests/standalone/package/scenarios/packages_file_strange_formatting/mixed_line_ends_test.dart b/tests/standalone/package/scenarios/packages_file_strange_formatting/mixed_line_ends_test.dart
index 8f4b629..3e9ec48 100644
--- a/tests/standalone/package/scenarios/packages_file_strange_formatting/mixed_line_ends_test.dart
+++ b/tests/standalone/package/scenarios/packages_file_strange_formatting/mixed_line_ends_test.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// PackageRoot=none
 // Packages=mixed_line_ends.packages
 
 library mixed_line_ends_test;
diff --git a/tests/standalone/package/scenarios/packages_option_only/packages_option_only_noimports_test.dart b/tests/standalone/package/scenarios/packages_option_only/packages_option_only_noimports_test.dart
index a6a8273..a519877 100644
--- a/tests/standalone/package/scenarios/packages_option_only/packages_option_only_noimports_test.dart
+++ b/tests/standalone/package/scenarios/packages_option_only/packages_option_only_noimports_test.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// PackageRoot=none
 // Packages=sub/.packages
 
 library packages_option_only_noimports_test;
diff --git a/tests/standalone/package/scenarios/packages_option_only/packages_option_only_test.dart b/tests/standalone/package/scenarios/packages_option_only/packages_option_only_test.dart
index e873350..47fdcde 100644
--- a/tests/standalone/package/scenarios/packages_option_only/packages_option_only_test.dart
+++ b/tests/standalone/package/scenarios/packages_option_only/packages_option_only_test.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// PackageRoot=none
 // Packages=sub/.packages
 
 library packages_option_only_test;
diff --git a/third_party/tcmalloc/BUILD.gn b/third_party/tcmalloc/BUILD.gn
new file mode 100644
index 0000000..e970559
--- /dev/null
+++ b/third_party/tcmalloc/BUILD.gn
@@ -0,0 +1,124 @@
+# Copyright (c) 2016, 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.
+
+config("internal_config") {
+  visibility = [ ":*" ]  # Only targets in this file can depend on this.
+  cflags = [
+    "-Wall",
+    "-Wextra",
+    "-Wno-missing-field-initializers",
+    "-Wno-sign-compare",
+    "-Wno-type-limits",
+    "-Wno-unused-result",
+    "-Wno-unused-parameter",
+    "-Wno-unused-function",
+    "-Wno-vla",
+    "-g3",
+    "-ggdb3",
+    "-fstack-protector",
+    "-Wa,--noexecstack",
+    "-fno-omit-frame-pointer",
+    "-fno-builtin-malloc",
+    "-fno-builtin-free",
+    "-fno-builtin-realloc",
+    "-fno-builtin-calloc",
+    "-fno-builtin-cfree",
+    "-fno-builtin-memalign",
+    "-fno-builtin-posix_memalign",
+    "-fno-builtin-valloc",
+    "-fno-builtin-pvalloc",
+  ]
+  if (is_clang) {
+    cflags += [
+      "-Wno-unused-const-variable",
+    ]
+  }
+}
+
+config("link_config") {
+  visibility = [ ":*" ]  # Only targets in this file can depend on this.
+  ldflags = [
+    # Don't let linker rip this symbol out, otherwise the heap&cpu
+    # profilers will not initialize properly on startup.
+    "-Wl,-uIsHeapProfilerRunning,-uProfilerStart",
+  ]
+}
+
+source_set("dynamic_annotations") {
+  configs -= [ "//build/config/compiler:chromium_code" ]
+  configs += [ ":internal_config" ]
+
+  include_dirs = [
+    "include",
+    "gperftools/src/base",
+    "gperftools/src",
+  ]
+
+  sources = [
+    "gperftools/src/base/dynamic_annotations.c",
+    "gperftools/src/base/dynamic_annotations.h",
+  ]
+}
+
+tcmalloc_sources_list = exec_script("../../tools/gypi_to_gn.py",
+                              [rebase_path("tcmalloc_sources.gypi")],
+                              "scope",
+                              ["tcmalloc_sources.gypi"])
+
+
+source_set("tcmalloc") {
+  configs -= [ "//build/config/compiler:chromium_code" ]
+  configs += [ ":internal_config" ]
+
+  public_configs = [":link_config"]
+
+  deps = [
+    ":dynamic_annotations"
+  ]
+
+  include_dirs = [
+    "include",
+    "gperftools/src/base",
+    "gperftools/src",
+  ]
+
+  # Disable the heap checker in tcmalloc.
+  defines = [
+    "ENABLE_EMERGENCY_MALLOC",
+    "NO_HEAP_CHECK",
+    # Disable debug even in a Dart Debug build. It is too slow.
+    "NDEBUG",
+  ]
+
+  # Disable stack sampling for heap profiling in Product builds.
+  if (is_product) {
+    defines += [
+      "NO_TCMALLOC_SAMPLES",
+    ]
+  }
+
+  cflags = [
+    "-Wnon-virtual-dtor",
+    "-Woverloaded-virtual",
+    "-fno-rtti",
+    "-fpermissive",
+  ]
+
+  set_sources_assignment_filter([
+    # No debug allocator.
+    "gperftools/src/debugallocation.cc",
+    # Not needed when using emergency malloc.
+    "gperftools/src/fake_stacktrace_scope.cc",
+    # Not using the cpuprofiler
+    "gperftools/src/base/thread_lister.c",
+    "gperftools/src/base/thread_lister.h",
+    "gperftools/src/profile-handler.cc",
+    "gperftools/src/profile-handler.h",
+    "gperftools/src/profiledata.cc",
+    "gperftools/src/profiledata.h",
+    "gperftools/src/profiler.cc",
+  ])
+
+  sources = tcmalloc_sources_list.sources
+}
diff --git a/third_party/tcmalloc/tcmalloc_sources.gypi b/third_party/tcmalloc/tcmalloc_sources.gypi
index 6325fb7..d8c4d98 100644
--- a/third_party/tcmalloc/tcmalloc_sources.gypi
+++ b/third_party/tcmalloc/tcmalloc_sources.gypi
@@ -11,8 +11,6 @@
     'gperftools/src/common.cc',
     'gperftools/src/common.h',
     'gperftools/src/config_for_unittests.h',
-    'gperftools/src/config.h',
-    'gperftools/src/config.h.in',
     'gperftools/src/debugallocation.cc',
     'gperftools/src/emergency_malloc.cc',
     'gperftools/src/emergency_malloc_for_stacktrace.cc',
@@ -152,8 +150,6 @@
     'gperftools/src/gperftools/malloc_hook.h',
     'gperftools/src/gperftools/profiler.h',
     'gperftools/src/gperftools/stacktrace.h',
-    'gperftools/src/gperftools/tcmalloc.h',
-    'gperftools/src/gperftools/tcmalloc.h.in',
 
     # gperftools/src/third_party/
     'gperftools/src/third_party/valgrind.h',
diff --git a/tools/VERSION b/tools/VERSION
index efeb63c..59e3311 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 1
 MINOR 20
 PATCH 0
-PRERELEASE 7
+PRERELEASE 8
 PRERELEASE_PATCH 0
diff --git a/tools/android_link.py b/tools/android_link.py
index 7854ce4..5de6d45 100755
--- a/tools/android_link.py
+++ b/tools/android_link.py
@@ -132,9 +132,11 @@
   crtend_android = os.path.join(android_ndk_lib, 'crtend_android.o')
 
   if link_target == 'target':
+    # We meddle with the android link command line here because gyp does not
+    # allow configurations to modify link_settings, or set variables.
+
     # Add and remove libraries as listed in configurations_android.gypi
-    libs_to_rm = ['-lrt', '-lpthread', '-lnss3', '-lnssutil3', '-lsmime3',
-                  '-lplds4', '-lplc4', '-lnspr4',]
+    libs_to_rm = ['-lrt', '-lpthread',]
     libs_to_add = ['-lstlport_static', android_libgcc, '-lc', '-ldl',
                    '-lstdc++', '-lm',]
 
@@ -142,9 +144,13 @@
     if link_type == 'executable':
       libs_to_add.extend(['-llog', '-lz', crtend_android])
 
+    # Filter out -l libs and add the right Android ones.
     link_args = [i for i in link_args if i not in libs_to_rm]
     link_args.extend(libs_to_add)
 
+    # Filter out tcmalloc.
+    link_args = [i for i in link_args if "tcmalloc" not in i]
+
     link_args.insert(0, android_linker)
   else:
     link_args.extend(['-ldl', '-lrt'])
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py
new file mode 100755
index 0000000..55b64ee
--- /dev/null
+++ b/tools/clang/scripts/update.py
@@ -0,0 +1,771 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Windows can't run .sh files, so this is a Python implementation of
+update.sh. This script should replace update.sh on all platforms eventually."""
+
+import argparse
+import contextlib
+import cStringIO
+import glob
+import os
+import pipes
+import re
+import shutil
+import subprocess
+import stat
+import sys
+import tarfile
+import time
+import urllib2
+import zipfile
+
+# Do NOT CHANGE this if you don't know what you're doing -- see
+# https://code.google.com/p/chromium/wiki/UpdatingClang
+# Reverting problematic clang rolls is safe, though.
+# Note: this revision is only used for Windows. Other platforms use update.sh.
+# TODO(thakis): Use the same revision on Windows and non-Windows.
+# TODO(thakis): Remove update.sh, use update.py everywhere.
+LLVM_WIN_REVISION = '242415'
+
+use_head_revision = 'LLVM_FORCE_HEAD_REVISION' in os.environ
+if use_head_revision:
+  LLVM_WIN_REVISION = 'HEAD'
+
+# This is incremented when pushing a new build of Clang at the same revision.
+CLANG_SUB_REVISION=1
+
+PACKAGE_VERSION = "%s-%s" % (LLVM_WIN_REVISION, CLANG_SUB_REVISION)
+
+# Path constants. (All of these should be absolute paths.)
+THIS_DIR = os.path.abspath(os.path.dirname(__file__))
+CHROMIUM_DIR = os.path.abspath(os.path.join(THIS_DIR, '..', '..', '..'))
+THIRD_PARTY_DIR = os.path.join(CHROMIUM_DIR, 'third_party')
+LLVM_DIR = os.path.join(THIRD_PARTY_DIR, 'llvm')
+LLVM_BOOTSTRAP_DIR = os.path.join(THIRD_PARTY_DIR, 'llvm-bootstrap')
+LLVM_BOOTSTRAP_INSTALL_DIR = os.path.join(THIRD_PARTY_DIR,
+                                          'llvm-bootstrap-install')
+CHROME_TOOLS_SHIM_DIR = os.path.join(LLVM_DIR, 'tools', 'chrometools')
+LLVM_BUILD_DIR = os.path.join(CHROMIUM_DIR, 'third_party', 'llvm-build',
+                              'Release+Asserts')
+COMPILER_RT_BUILD_DIR = os.path.join(LLVM_BUILD_DIR, '32bit-compiler-rt')
+CLANG_DIR = os.path.join(LLVM_DIR, 'tools', 'clang')
+LLD_DIR = os.path.join(LLVM_DIR, 'tools', 'lld')
+COMPILER_RT_DIR = os.path.join(LLVM_DIR, 'projects', 'compiler-rt')
+LIBCXX_DIR = os.path.join(LLVM_DIR, 'projects', 'libcxx')
+LIBCXXABI_DIR = os.path.join(LLVM_DIR, 'projects', 'libcxxabi')
+LLVM_BUILD_TOOLS_DIR = os.path.abspath(
+    os.path.join(LLVM_DIR, '..', 'llvm-build-tools'))
+STAMP_FILE = os.path.join(LLVM_DIR, '..', 'llvm-build', 'cr_build_revision')
+BINUTILS_DIR = os.path.join(THIRD_PARTY_DIR, 'binutils')
+VERSION = '3.8.0'
+
+# URL for pre-built binaries.
+CDS_URL = 'https://commondatastorage.googleapis.com/chromium-browser-clang'
+
+LLVM_REPO_URL='https://llvm.org/svn/llvm-project'
+if 'LLVM_REPO_URL' in os.environ:
+  LLVM_REPO_URL = os.environ['LLVM_REPO_URL']
+
+
+def DownloadUrl(url, output_file):
+  """Download url into output_file."""
+  CHUNK_SIZE = 4096
+  TOTAL_DOTS = 10
+  sys.stdout.write('Downloading %s ' % url)
+  sys.stdout.flush()
+  response = urllib2.urlopen(url)
+  total_size = int(response.info().getheader('Content-Length').strip())
+  bytes_done = 0
+  dots_printed = 0
+  while True:
+    chunk = response.read(CHUNK_SIZE)
+    if not chunk:
+      break
+    output_file.write(chunk)
+    bytes_done += len(chunk)
+    num_dots = TOTAL_DOTS * bytes_done / total_size
+    sys.stdout.write('.' * (num_dots - dots_printed))
+    sys.stdout.flush()
+    dots_printed = num_dots
+  print ' Done.'
+
+
+def ReadStampFile():
+  """Return the contents of the stamp file, or '' if it doesn't exist."""
+  try:
+    with open(STAMP_FILE, 'r') as f:
+      return f.read()
+  except IOError:
+    return ''
+
+
+def WriteStampFile(s):
+  """Write s to the stamp file."""
+  if not os.path.exists(os.path.dirname(STAMP_FILE)):
+    os.makedirs(os.path.dirname(STAMP_FILE))
+  with open(STAMP_FILE, 'w') as f:
+    f.write(s)
+
+
+def GetSvnRevision(svn_repo):
+  """Returns current revision of the svn repo at svn_repo."""
+  svn_info = subprocess.check_output('svn info ' + svn_repo, shell=True)
+  m = re.search(r'Revision: (\d+)', svn_info)
+  return m.group(1)
+
+
+def RmTree(dir):
+  """Delete dir."""
+  def ChmodAndRetry(func, path, _):
+    # Subversion can leave read-only files around.
+    if not os.access(path, os.W_OK):
+      os.chmod(path, stat.S_IWUSR)
+      return func(path)
+    raise
+
+  shutil.rmtree(dir, onerror=ChmodAndRetry)
+
+
+def RunCommand(command, msvc_arch=None, env=None, fail_hard=True):
+  """Run command and return success (True) or failure; or if fail_hard is
+     True, exit on failure.  If msvc_arch is set, runs the command in a
+     shell with the msvc tools for that architecture."""
+
+  if msvc_arch and sys.platform == 'win32':
+    command = GetVSVersion().SetupScript(msvc_arch) + ['&&'] + command
+
+  # https://docs.python.org/2/library/subprocess.html:
+  # "On Unix with shell=True [...] if args is a sequence, the first item
+  # specifies the command string, and any additional items will be treated as
+  # additional arguments to the shell itself.  That is to say, Popen does the
+  # equivalent of:
+  #   Popen(['/bin/sh', '-c', args[0], args[1], ...])"
+  #
+  # We want to pass additional arguments to command[0], not to the shell,
+  # so manually join everything into a single string.
+  # Annoyingly, for "svn co url c:\path", pipes.quote() thinks that it should
+  # quote c:\path but svn can't handle quoted paths on Windows.  Since on
+  # Windows follow-on args are passed to args[0] instead of the shell, don't
+  # do the single-string transformation there.
+  if sys.platform != 'win32':
+    command = ' '.join([pipes.quote(c) for c in command])
+  print 'Running', command
+  if subprocess.call(command, env=env, shell=True) == 0:
+    return True
+  print 'Failed.'
+  if fail_hard:
+    sys.exit(1)
+  return False
+
+
+def CopyFile(src, dst):
+  """Copy a file from src to dst."""
+  shutil.copy(src, dst)
+  print "Copying %s to %s" % (src, dst)
+
+
+def CopyDirectoryContents(src, dst, filename_filter=None):
+  """Copy the files from directory src to dst
+  with an optional filename filter."""
+  if not os.path.exists(dst):
+    os.makedirs(dst)
+  for root, _, files in os.walk(src):
+    for f in files:
+      if filename_filter and not re.match(filename_filter, f):
+        continue
+      CopyFile(os.path.join(root, f), dst)
+
+
+def Checkout(name, url, dir):
+  """Checkout the SVN module at url into dir. Use name for the log message."""
+  print "Checking out %s r%s into '%s'" % (name, LLVM_WIN_REVISION, dir)
+
+  command = ['svn', 'checkout', '--force', url + '@' + LLVM_WIN_REVISION, dir]
+  if RunCommand(command, fail_hard=False):
+    return
+
+  if os.path.isdir(dir):
+    print "Removing %s." % (dir)
+    RmTree(dir)
+
+  print "Retrying."
+  RunCommand(command)
+
+
+def RevertPreviouslyPatchedFiles():
+  print 'Reverting previously patched files'
+  files = [
+    '%(clang)s/test/Index/crash-recovery-modules.m',
+    '%(clang)s/unittests/libclang/LibclangTest.cpp',
+    '%(compiler_rt)s/lib/asan/asan_rtl.cc',
+    '%(compiler_rt)s/test/asan/TestCases/Linux/new_array_cookie_test.cc',
+    '%(llvm)s/test/DebugInfo/gmlt.ll',
+    '%(llvm)s/lib/CodeGen/SpillPlacement.cpp',
+    '%(llvm)s/lib/CodeGen/SpillPlacement.h',
+    '%(llvm)s/lib/Transforms/Instrumentation/MemorySanitizer.cpp',
+    '%(clang)s/test/Driver/env.c',
+    '%(clang)s/lib/Frontend/InitPreprocessor.cpp',
+    '%(clang)s/test/Frontend/exceptions.c',
+    '%(clang)s/test/Preprocessor/predefined-exceptions.m',
+    '%(llvm)s/test/Bindings/Go/go.test',
+    '%(clang)s/lib/Parse/ParseExpr.cpp',
+    '%(clang)s/lib/Parse/ParseTemplate.cpp',
+    '%(clang)s/lib/Sema/SemaDeclCXX.cpp',
+    '%(clang)s/lib/Sema/SemaExprCXX.cpp',
+    '%(clang)s/test/SemaCXX/default2.cpp',
+    '%(clang)s/test/SemaCXX/typo-correction-delayed.cpp',
+    '%(compiler_rt)s/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc',
+    '%(compiler_rt)s/test/tsan/signal_segv_handler.cc',
+    '%(compiler_rt)s/lib/sanitizer_common/sanitizer_coverage_libcdep.cc',
+    '%(compiler_rt)s/cmake/config-ix.cmake',
+    '%(compiler_rt)s/CMakeLists.txt',
+    '%(compiler_rt)s/lib/ubsan/ubsan_platform.h',
+    ]
+  for f in files:
+    f = f % {
+        'clang': CLANG_DIR,
+        'compiler_rt': COMPILER_RT_DIR,
+        'llvm': LLVM_DIR,
+        }
+    if os.path.exists(f):
+      os.remove(f)  # For unversioned files.
+      RunCommand(['svn', 'revert', f])
+
+
+def ApplyLocalPatches():
+  # There's no patch program on Windows by default.  We don't need patches on
+  # Windows yet, and maybe this not working on Windows will motivate us to
+  # remove patches over time.
+  assert sys.platform != 'win32'
+
+  # Apply patch for tests failing with --disable-pthreads (llvm.org/PR11974)
+  clang_patches = [ r"""\
+--- test/Index/crash-recovery-modules.m	(revision 202554)
++++ test/Index/crash-recovery-modules.m	(working copy)
+@@ -12,6 +12,8 @@
+ 
+ // REQUIRES: crash-recovery
+ // REQUIRES: shell
++// XFAIL: *
++//    (PR11974)
+ 
+ @import Crash;
+""", r"""\
+--- unittests/libclang/LibclangTest.cpp (revision 215949)
++++ unittests/libclang/LibclangTest.cpp (working copy)
+@@ -431,7 +431,7 @@
+   EXPECT_EQ(0U, clang_getNumDiagnostics(ClangTU));
+ }
+
+-TEST_F(LibclangReparseTest, ReparseWithModule) {
++TEST_F(LibclangReparseTest, DISABLED_ReparseWithModule) {
+   const char *HeaderTop = "#ifndef H\n#define H\nstruct Foo { int bar;";
+   const char *HeaderBottom = "\n};\n#endif\n";
+   const char *MFile = "#include \"HeaderFile.h\"\nint main() {"
+"""
+      ]
+
+  # This Go bindings test doesn't work after bootstrap on Linux, PR21552.
+  llvm_patches = [ r"""\
+--- test/Bindings/Go/go.test    (revision 223109)
++++ test/Bindings/Go/go.test    (working copy)
+@@ -1,3 +1,3 @@
+-; RUN: llvm-go test llvm.org/llvm/bindings/go/llvm
++; RUN: true
+ 
+ ; REQUIRES: shell
+"""
+      ]
+
+  # The UBSan run-time, which is now bundled with the ASan run-time, doesn't
+  # work on Mac OS X 10.8 (PR23539).
+  compiler_rt_patches = [ r"""\
+--- CMakeLists.txt	(revision 241602)
++++ CMakeLists.txt	(working copy)
+@@ -305,6 +305,7 @@
+       list(APPEND SANITIZER_COMMON_SUPPORTED_OS iossim)
+     endif()
+   endif()
++  set(SANITIZER_MIN_OSX_VERSION "10.7")
+   if(SANITIZER_MIN_OSX_VERSION VERSION_LESS "10.7")
+     message(FATAL_ERROR "Too old OS X version: ${SANITIZER_MIN_OSX_VERSION}")
+   endif()
+"""
+      ]
+
+  for path, patches in [(LLVM_DIR, llvm_patches),
+                        (CLANG_DIR, clang_patches),
+                        (COMPILER_RT_DIR, compiler_rt_patches)]:
+    print 'Applying patches in', path
+    for patch in patches:
+      print patch
+      p = subprocess.Popen( ['patch', '-p0', '-d', path], stdin=subprocess.PIPE)
+      (stdout, stderr) = p.communicate(input=patch)
+      if p.returncode != 0:
+        raise RuntimeError('stdout %s, stderr %s' % (stdout, stderr))
+
+
+def DeleteChromeToolsShim():
+  shutil.rmtree(CHROME_TOOLS_SHIM_DIR, ignore_errors=True)
+
+
+def CreateChromeToolsShim():
+  """Hooks the Chrome tools into the LLVM build.
+
+  Several Chrome tools have dependencies on LLVM/Clang libraries. The LLVM build
+  detects implicit tools in the tools subdirectory, so this helper install a
+  shim CMakeLists.txt that forwards to the real directory for the Chrome tools.
+
+  Note that the shim directory name intentionally has no - or _. The implicit
+  tool detection logic munges them in a weird way."""
+  assert not any(i in os.path.basename(CHROME_TOOLS_SHIM_DIR) for i in '-_')
+  os.mkdir(CHROME_TOOLS_SHIM_DIR)
+  with file(os.path.join(CHROME_TOOLS_SHIM_DIR, 'CMakeLists.txt'), 'w') as f:
+    f.write('# Automatically generated by tools/clang/scripts/update.py. ' +
+            'Do not edit.\n')
+    f.write('# Since tools/clang is located in another directory, use the \n')
+    f.write('# two arg version to specify where build artifacts go. CMake\n')
+    f.write('# disallows reuse of the same binary dir for multiple source\n')
+    f.write('# dirs, so the build artifacts need to go into a subdirectory.\n')
+    f.write('# dirs, so the build artifacts need to go into a subdirectory.\n')
+    f.write('if (CHROMIUM_TOOLS_SRC)\n')
+    f.write('  add_subdirectory(${CHROMIUM_TOOLS_SRC} ' +
+              '${CMAKE_CURRENT_BINARY_DIR}/a)\n')
+    f.write('endif (CHROMIUM_TOOLS_SRC)\n')
+
+
+def AddCMakeToPath():
+  """Download CMake and add it to PATH."""
+  if sys.platform == 'win32':
+    zip_name = 'cmake-3.2.2-win32-x86.zip'
+    cmake_dir = os.path.join(LLVM_BUILD_TOOLS_DIR,
+                             'cmake-3.2.2-win32-x86', 'bin')
+  else:
+    suffix = 'Darwin' if sys.platform == 'darwin' else 'Linux'
+    zip_name = 'cmake310_%s.tgz' % suffix
+    cmake_dir = os.path.join(LLVM_BUILD_TOOLS_DIR, 'cmake310', 'bin')
+  if not os.path.exists(cmake_dir):
+    if not os.path.exists(LLVM_BUILD_TOOLS_DIR):
+      os.makedirs(LLVM_BUILD_TOOLS_DIR)
+    # The cmake archive is smaller than 20 MB, small enough to keep in memory:
+    with contextlib.closing(cStringIO.StringIO()) as f:
+      DownloadUrl(CDS_URL + '/tools/' + zip_name, f)
+      f.seek(0)
+      if zip_name.endswith('.zip'):
+        zipfile.ZipFile(f).extractall(path=LLVM_BUILD_TOOLS_DIR)
+      else:
+        tarfile.open(mode='r:gz', fileobj=f).extractall(path=
+            LLVM_BUILD_TOOLS_DIR)
+  os.environ['PATH'] = cmake_dir + os.pathsep + os.environ.get('PATH', '')
+
+vs_version = None
+def GetVSVersion():
+  global vs_version
+  if vs_version:
+    return vs_version
+
+  # Try using the toolchain in depot_tools.
+  # This sets environment variables used by SelectVisualStudioVersion below.
+  sys.path.append(os.path.join(CHROMIUM_DIR, 'build'))
+  import vs_toolchain
+  vs_toolchain.SetEnvironmentAndGetRuntimeDllDirs()
+
+  # Use gyp to find the MSVS installation, either in depot_tools as per above,
+  # or a system-wide installation otherwise.
+  sys.path.append(os.path.join(CHROMIUM_DIR, 'tools', 'gyp', 'pylib'))
+  import gyp.MSVSVersion
+  vs_version = gyp.MSVSVersion.SelectVisualStudioVersion('2013')
+  return vs_version
+
+
+def UpdateClang(args):
+  print 'Updating Clang to %s...' % PACKAGE_VERSION
+  if ReadStampFile() == PACKAGE_VERSION:
+    print 'Already up to date.'
+    return 0
+
+  # Reset the stamp file in case the build is unsuccessful.
+  WriteStampFile('')
+
+  if not args.force_local_build:
+    cds_file = "clang-%s.tgz" %  PACKAGE_VERSION
+    cds_full_url = CDS_URL + '/Win/' + cds_file
+
+    # Check if there's a prebuilt binary and if so just fetch that. That's
+    # faster, and goma relies on having matching binary hashes on client and
+    # server too.
+    print 'Trying to download prebuilt clang'
+
+    # clang packages are smaller than 50 MB, small enough to keep in memory.
+    with contextlib.closing(cStringIO.StringIO()) as f:
+      try:
+        DownloadUrl(cds_full_url, f)
+        f.seek(0)
+        tarfile.open(mode='r:gz', fileobj=f).extractall(path=LLVM_BUILD_DIR)
+        print 'clang %s unpacked' % PACKAGE_VERSION
+        # Download the gold plugin if requested to by an environment variable.
+        # This is used by the CFI ClusterFuzz bot.
+        if 'LLVM_DOWNLOAD_GOLD_PLUGIN' in os.environ:
+          RunCommand(['python', CHROMIUM_DIR+'/build/download_gold_plugin.py'])
+        WriteStampFile(PACKAGE_VERSION)
+        return 0
+      except urllib2.HTTPError:
+        print 'Did not find prebuilt clang %s, building locally' % cds_file
+
+  AddCMakeToPath()
+
+  RevertPreviouslyPatchedFiles()
+  DeleteChromeToolsShim()
+
+  Checkout('LLVM', LLVM_REPO_URL + '/llvm/trunk', LLVM_DIR)
+  Checkout('Clang', LLVM_REPO_URL + '/cfe/trunk', CLANG_DIR)
+  if sys.platform == 'win32':
+    Checkout('LLD', LLVM_REPO_URL + '/lld/trunk', LLD_DIR)
+  Checkout('compiler-rt', LLVM_REPO_URL + '/compiler-rt/trunk', COMPILER_RT_DIR)
+  if sys.platform == 'darwin':
+    # clang needs a libc++ checkout, else -stdlib=libc++ won't find includes
+    # (i.e. this is needed for bootstrap builds).
+    Checkout('libcxx', LLVM_REPO_URL + '/libcxx/trunk', LIBCXX_DIR)
+    # While we're bundling our own libc++ on OS X, we need to compile libc++abi
+    # into it too (since OS X 10.6 doesn't have libc++abi.dylib either).
+    Checkout('libcxxabi', LLVM_REPO_URL + '/libcxxabi/trunk', LIBCXXABI_DIR)
+
+  if args.with_patches and sys.platform != 'win32':
+    ApplyLocalPatches()
+
+  cc, cxx = None, None
+  cflags = cxxflags = ldflags = []
+
+  # LLVM uses C++11 starting in llvm 3.5. On Linux, this means libstdc++4.7+ is
+  # needed, on OS X it requires libc++. clang only automatically links to libc++
+  # when targeting OS X 10.9+, so add stdlib=libc++ explicitly so clang can run
+  # on OS X versions as old as 10.7.
+  # TODO(thakis): Some bots are still on 10.6 (nacl...), so for now bundle
+  # libc++.dylib.  Remove this once all bots are on 10.7+, then use
+  # -DLLVM_ENABLE_LIBCXX=ON and change deployment_target to 10.7.
+  deployment_target = ''
+
+  if sys.platform == 'darwin':
+    # When building on 10.9, /usr/include usually doesn't exist, and while
+    # Xcode's clang automatically sets a sysroot, self-built clangs don't.
+    cflags = ['-isysroot', subprocess.check_output(
+        ['xcrun', '--show-sdk-path']).rstrip()]
+    cxxflags = ['-stdlib=libc++', '-nostdinc++',
+                '-I' + os.path.join(LIBCXX_DIR, 'include')] + cflags
+    if args.bootstrap:
+      deployment_target = '10.6'
+
+  base_cmake_args = ['-GNinja',
+                     '-DCMAKE_BUILD_TYPE=Release',
+                     '-DLLVM_ENABLE_ASSERTIONS=ON',
+                     '-DLLVM_ENABLE_THREADS=OFF',
+                     ]
+
+  if args.bootstrap:
+    print 'Building bootstrap compiler'
+    if not os.path.exists(LLVM_BOOTSTRAP_DIR):
+      os.makedirs(LLVM_BOOTSTRAP_DIR)
+    os.chdir(LLVM_BOOTSTRAP_DIR)
+    bootstrap_args = base_cmake_args + [
+        '-DLLVM_TARGETS_TO_BUILD=host',
+        '-DCMAKE_INSTALL_PREFIX=' + LLVM_BOOTSTRAP_INSTALL_DIR,
+        '-DCMAKE_C_FLAGS=' + ' '.join(cflags),
+        '-DCMAKE_CXX_FLAGS=' + ' '.join(cxxflags),
+        ]
+    if cc is not None:  bootstrap_args.append('-DCMAKE_C_COMPILER=' + cc)
+    if cxx is not None: bootstrap_args.append('-DCMAKE_CXX_COMPILER=' + cxx)
+    RunCommand(['cmake'] + bootstrap_args + [LLVM_DIR], msvc_arch='x64')
+    RunCommand(['ninja'], msvc_arch='x64')
+    if args.run_tests:
+      RunCommand(['ninja', 'check-all'], msvc_arch='x64')
+    RunCommand(['ninja', 'install'], msvc_arch='x64')
+
+    if sys.platform == 'win32':
+      cc = os.path.join(LLVM_BOOTSTRAP_INSTALL_DIR, 'bin', 'clang-cl.exe')
+      cxx = os.path.join(LLVM_BOOTSTRAP_INSTALL_DIR, 'bin', 'clang-cl.exe')
+      # CMake has a hard time with backslashes in compiler paths:
+      # https://stackoverflow.com/questions/13050827
+      cc = cc.replace('\\', '/')
+      cxx = cxx.replace('\\', '/')
+    else:
+      cc = os.path.join(LLVM_BOOTSTRAP_INSTALL_DIR, 'bin', 'clang')
+      cxx = os.path.join(LLVM_BOOTSTRAP_INSTALL_DIR, 'bin', 'clang++')
+    print 'Building final compiler'
+
+  if sys.platform == 'darwin':
+    # Build libc++.dylib while some bots are still on OS X 10.6.
+    libcxxbuild = os.path.join(LLVM_BUILD_DIR, 'libcxxbuild')
+    if os.path.isdir(libcxxbuild):
+      RmTree(libcxxbuild)
+    libcxxflags = ['-O3', '-std=c++11', '-fstrict-aliasing']
+
+    # libcxx and libcxxabi both have a file stdexcept.cpp, so put their .o files
+    # into different subdirectories.
+    os.makedirs(os.path.join(libcxxbuild, 'libcxx'))
+    os.chdir(os.path.join(libcxxbuild, 'libcxx'))
+    RunCommand(['c++', '-c'] + cxxflags + libcxxflags +
+                glob.glob(os.path.join(LIBCXX_DIR, 'src', '*.cpp')))
+
+    os.makedirs(os.path.join(libcxxbuild, 'libcxxabi'))
+    os.chdir(os.path.join(libcxxbuild, 'libcxxabi'))
+    RunCommand(['c++', '-c'] + cxxflags + libcxxflags +
+               glob.glob(os.path.join(LIBCXXABI_DIR, 'src', '*.cpp')) +
+               ['-I' + os.path.join(LIBCXXABI_DIR, 'include')])
+
+    os.chdir(libcxxbuild)
+    libdir = os.path.join(LIBCXX_DIR, 'lib')
+    RunCommand(['cc'] + glob.glob('libcxx/*.o') + glob.glob('libcxxabi/*.o') +
+        ['-o', 'libc++.1.dylib', '-dynamiclib', '-nodefaultlibs',
+         '-current_version', '1', '-compatibility_version', '1', '-lSystem',
+         '-install_name', '@executable_path/libc++.dylib',
+         '-Wl,-unexported_symbols_list,' + libdir + '/libc++unexp.exp',
+         '-Wl,-force_symbols_not_weak_list,' + libdir + '/notweak.exp',
+         '-Wl,-force_symbols_weak_list,' + libdir + '/weak.exp'])
+    if os.path.exists('libc++.dylib'):
+      os.remove('libc++.dylib')
+    os.symlink('libc++.1.dylib', 'libc++.dylib')
+    ldflags += ['-stdlib=libc++', '-L' + libcxxbuild]
+
+    if args.bootstrap:
+      # Now that the libc++ headers have been installed and libc++.dylib is
+      # built, delete the libc++ checkout again so that it's not part of the
+      # main build below -- the libc++(abi) tests don't pass on OS X in
+      # bootstrap builds (http://llvm.org/PR24068)
+      RmTree(LIBCXX_DIR)
+      RmTree(LIBCXXABI_DIR)
+      cxxflags = ['-stdlib=libc++', '-nostdinc++',
+                  '-I' + os.path.join(LLVM_BOOTSTRAP_INSTALL_DIR,
+                                      'include/c++/v1')
+                  ] + cflags
+
+  # Build clang.
+  binutils_incdir = ''
+  if sys.platform.startswith('linux'):
+    binutils_incdir = os.path.join(BINUTILS_DIR, 'Linux_x64/Release/include')
+
+  # If building at head, define a macro that plugins can use for #ifdefing
+  # out code that builds at head, but not at LLVM_WIN_REVISION or vice versa.
+  if use_head_revision:
+    cflags += ['-DLLVM_FORCE_HEAD_REVISION']
+    cxxflags += ['-DLLVM_FORCE_HEAD_REVISION']
+
+  CreateChromeToolsShim()
+
+  deployment_env = None
+  if deployment_target:
+    deployment_env = os.environ.copy()
+    deployment_env['MACOSX_DEPLOYMENT_TARGET'] = deployment_target
+
+  cmake_args = base_cmake_args + [
+      '-DLLVM_BINUTILS_INCDIR=' + binutils_incdir,
+      '-DCMAKE_C_FLAGS=' + ' '.join(cflags),
+      '-DCMAKE_CXX_FLAGS=' + ' '.join(cxxflags),
+      '-DCMAKE_EXE_LINKER_FLAGS=' + ' '.join(ldflags),
+      '-DCMAKE_SHARED_LINKER_FLAGS=' + ' '.join(ldflags),
+      '-DCMAKE_MODULE_LINKER_FLAGS=' + ' '.join(ldflags),
+      '-DCMAKE_INSTALL_PREFIX=' + LLVM_BUILD_DIR,
+      '-DCHROMIUM_TOOLS_SRC=%s' % os.path.join(CHROMIUM_DIR, 'tools', 'clang'),
+      '-DCHROMIUM_TOOLS=%s' % ';'.join(args.tools)]
+  # TODO(thakis): Unconditionally append this to base_cmake_args instead once
+  # compiler-rt can build with clang-cl on Windows (http://llvm.org/PR23698)
+  cc_args = base_cmake_args if sys.platform != 'win32' else cmake_args
+  if cc is not None:  cc_args.append('-DCMAKE_C_COMPILER=' + cc)
+  if cxx is not None: cc_args.append('-DCMAKE_CXX_COMPILER=' + cxx)
+
+  if not os.path.exists(LLVM_BUILD_DIR):
+    os.makedirs(LLVM_BUILD_DIR)
+  os.chdir(LLVM_BUILD_DIR)
+  RunCommand(['cmake'] + cmake_args + [LLVM_DIR],
+             msvc_arch='x64', env=deployment_env)
+  RunCommand(['ninja'], msvc_arch='x64')
+
+  if args.tools:
+    # If any Chromium tools were built, install those now.
+    RunCommand(['ninja', 'cr-install'], msvc_arch='x64')
+
+  if sys.platform == 'darwin':
+    CopyFile(os.path.join(LLVM_BUILD_DIR, 'libc++.1.dylib'),
+             os.path.join(LLVM_BUILD_DIR, 'bin'))
+    # See http://crbug.com/256342
+    RunCommand(['strip', '-x', os.path.join(LLVM_BUILD_DIR, 'bin', 'clang')])
+  elif sys.platform.startswith('linux'):
+    RunCommand(['strip', os.path.join(LLVM_BUILD_DIR, 'bin', 'clang')])
+
+  # Do an x86 build of compiler-rt to get the 32-bit ASan run-time.
+  # TODO(hans): Remove once the regular build above produces this.
+  if not os.path.exists(COMPILER_RT_BUILD_DIR):
+    os.makedirs(COMPILER_RT_BUILD_DIR)
+  os.chdir(COMPILER_RT_BUILD_DIR)
+  # TODO(thakis): Add this once compiler-rt can build with clang-cl (see
+  # above).
+  #if args.bootstrap and sys.platform == 'win32':
+    # The bootstrap compiler produces 64-bit binaries by default.
+    #cflags += ['-m32']
+    #cxxflags += ['-m32']
+  compiler_rt_args = base_cmake_args + [
+      '-DCMAKE_C_FLAGS=' + ' '.join(cflags),
+      '-DCMAKE_CXX_FLAGS=' + ' '.join(cxxflags)]
+  if sys.platform != 'win32':
+    compiler_rt_args += ['-DLLVM_CONFIG_PATH=' +
+                         os.path.join(LLVM_BUILD_DIR, 'bin', 'llvm-config')]
+  RunCommand(['cmake'] + compiler_rt_args + [LLVM_DIR],
+              msvc_arch='x86', env=deployment_env)
+  RunCommand(['ninja', 'compiler-rt'], msvc_arch='x86')
+
+  # TODO(hans): Make this (and the .gypi and .isolate files) version number
+  # independent.
+  if sys.platform == 'win32':
+    platform = 'windows'
+  elif sys.platform == 'darwin':
+    platform = 'darwin'
+  else:
+    assert sys.platform.startswith('linux')
+    platform = 'linux'
+  asan_rt_lib_src_dir = os.path.join(COMPILER_RT_BUILD_DIR, 'lib', 'clang',
+                                     VERSION, 'lib', platform)
+  asan_rt_lib_dst_dir = os.path.join(LLVM_BUILD_DIR, 'lib', 'clang',
+                                     VERSION, 'lib', platform)
+  CopyDirectoryContents(asan_rt_lib_src_dir, asan_rt_lib_dst_dir,
+                        r'^.*-i386\.lib$')
+  CopyDirectoryContents(asan_rt_lib_src_dir, asan_rt_lib_dst_dir,
+                        r'^.*-i386\.dll$')
+
+  CopyFile(os.path.join(asan_rt_lib_src_dir, '..', '..', 'asan_blacklist.txt'),
+           os.path.join(asan_rt_lib_dst_dir, '..', '..'))
+
+  if sys.platform == 'win32':
+    # Make an extra copy of the sanitizer headers, to be put on the include path
+    # of the fallback compiler.
+    sanitizer_include_dir = os.path.join(LLVM_BUILD_DIR, 'lib', 'clang',
+                                         VERSION, 'include', 'sanitizer')
+    aux_sanitizer_include_dir = os.path.join(LLVM_BUILD_DIR, 'lib', 'clang',
+                                             VERSION, 'include_sanitizer',
+                                             'sanitizer')
+    if not os.path.exists(aux_sanitizer_include_dir):
+      os.makedirs(aux_sanitizer_include_dir)
+    for _, _, files in os.walk(sanitizer_include_dir):
+      for f in files:
+        CopyFile(os.path.join(sanitizer_include_dir, f),
+                 aux_sanitizer_include_dir)
+
+  # Run tests.
+  if args.run_tests or use_head_revision:
+    os.chdir(LLVM_BUILD_DIR)
+    RunCommand(GetVSVersion().SetupScript('x64') +
+               ['&&', 'ninja', 'cr-check-all'])
+  if args.run_tests:
+    os.chdir(LLVM_BUILD_DIR)
+    RunCommand(GetVSVersion().SetupScript('x64') +
+               ['&&', 'ninja', 'check-all'])
+
+  WriteStampFile(PACKAGE_VERSION)
+  print 'Clang update was successful.'
+  return 0
+
+
+def main():
+  if not sys.platform in ['win32', 'cygwin']:
+    # For non-Windows, fall back to update.sh.
+    # TODO(hans): Make update.py replace update.sh completely.
+
+    # This script is called by gclient. gclient opens its hooks subprocesses
+    # with (stdout=subprocess.PIPE, stderr=subprocess.STDOUT) and then does
+    # custom output processing that breaks printing '\r' characters for
+    # single-line updating status messages as printed by curl and wget.
+    # Work around this by setting stderr of the update.sh process to stdin (!):
+    # gclient doesn't redirect stdin, and while stdin itself is read-only, a
+    # dup()ed sys.stdin is writable, try
+    #   fd2 = os.dup(sys.stdin.fileno()); os.write(fd2, 'hi')
+    # TODO: Fix gclient instead, http://crbug.com/95350
+    if '--no-stdin-hack' in sys.argv:
+      sys.argv.remove('--no-stdin-hack')
+      stderr = None
+    else:
+      try:
+        stderr = os.fdopen(os.dup(sys.stdin.fileno()))
+      except:
+        stderr = sys.stderr
+    return subprocess.call(
+        [os.path.join(os.path.dirname(__file__), 'update.sh')] + sys.argv[1:],
+        stderr=stderr)
+
+  parser = argparse.ArgumentParser(description='Build Clang.')
+  parser.add_argument('--bootstrap', action='store_true',
+                      help='first build clang with CC, then with itself.')
+  parser.add_argument('--if-needed', action='store_true',
+                      help="run only if the script thinks clang is needed")
+  parser.add_argument('--force-local-build', action='store_true',
+                      help="don't try to download prebuild binaries")
+  parser.add_argument('--print-revision', action='store_true',
+                      help='print current clang revision and exit.')
+  parser.add_argument('--print-clang-version', action='store_true',
+                      help='print current clang version (e.g. x.y.z) and exit.')
+  parser.add_argument('--run-tests', action='store_true',
+                      help='run tests after building; only for local builds')
+  parser.add_argument('--tools', nargs='*',
+                      help='select which chrome tools to build',
+                      default=['plugins', 'blink_gc_plugin'])
+  parser.add_argument('--without-patches', action='store_false',
+                      help="don't apply patches (default)", dest='with_patches',
+                      default=True)
+
+  # For now, these flags are only used for the non-Windows flow, but argparser
+  # gets mad if it sees a flag it doesn't recognize.
+  parser.add_argument('--no-stdin-hack', action='store_true')
+
+  args = parser.parse_args()
+
+  if args.if_needed:
+    is_clang_required = False
+    # clang is always used on Mac and Linux.
+    if sys.platform == 'darwin' or sys.platform.startswith('linux'):
+      is_clang_required = True
+    # clang requested via $GYP_DEFINES.
+    if re.search(r'\b(clang|asan|lsan|msan|tsan)=1',
+                 os.environ.get('GYP_DEFINES', '')):
+      is_clang_required = True
+    # clang previously downloaded, keep it up-to-date.
+    # If you don't want this, delete third_party/llvm-build on your machine.
+    if os.path.isdir(LLVM_BUILD_DIR):
+      is_clang_required = True
+    if not is_clang_required:
+      return 0
+    if re.search(r'\b(make_clang_dir)=', os.environ.get('GYP_DEFINES', '')):
+      print 'Skipping Clang update (make_clang_dir= was set in GYP_DEFINES).'
+      return 0
+
+  global LLVM_WIN_REVISION, PACKAGE_VERSION
+  if args.print_revision:
+    if use_head_revision:
+      print GetSvnRevision(LLVM_DIR)
+    else:
+      print PACKAGE_VERSION
+    return 0
+
+  if args.print_clang_version:
+    sys.stdout.write(VERSION)
+    return 0
+
+  # Don't buffer stdout, so that print statements are immediately flushed.
+  # Do this only after --print-revision has been handled, else we'll get
+  # an error message when this script is run from gn for some reason.
+  sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
+
+  if use_head_revision:
+    # Use a real revision number rather than HEAD to make sure that the stamp
+    # file logic works.
+    LLVM_WIN_REVISION = GetSvnRevision(LLVM_REPO_URL)
+    PACKAGE_VERSION = LLVM_WIN_REVISION + '-0'
+
+    args.force_local_build = True
+    # Skip local patches when using HEAD: they probably don't apply anymore.
+    args.with_patches = False
+
+  return UpdateClang(args)
+
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/tools/clang/scripts/update.sh b/tools/clang/scripts/update.sh
new file mode 100755
index 0000000..d85deae
--- /dev/null
+++ b/tools/clang/scripts/update.sh
@@ -0,0 +1,724 @@
+#!/usr/bin/env bash
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This script will check out llvm and clang into third_party/llvm and build it.
+
+# Do NOT CHANGE this if you don't know what you're doing -- see
+# https://code.google.com/p/chromium/wiki/UpdatingClang
+# Reverting problematic clang rolls is safe, though.
+CLANG_REVISION=241602
+
+# This is incremented when pushing a new build of Clang at the same revision.
+CLANG_SUB_REVISION=3
+
+PACKAGE_VERSION="${CLANG_REVISION}-${CLANG_SUB_REVISION}"
+
+THIS_DIR="$(dirname "${0}")"
+LLVM_DIR="${THIS_DIR}/../../../third_party/llvm"
+LLVM_BUILD_DIR="${LLVM_DIR}/../llvm-build/Release+Asserts"
+COMPILER_RT_BUILD_DIR="${LLVM_DIR}/../llvm-build/compiler-rt"
+LLVM_BOOTSTRAP_DIR="${LLVM_DIR}/../llvm-bootstrap"
+LLVM_BOOTSTRAP_INSTALL_DIR="${LLVM_DIR}/../llvm-bootstrap-install"
+CLANG_DIR="${LLVM_DIR}/tools/clang"
+COMPILER_RT_DIR="${LLVM_DIR}/compiler-rt"
+LIBCXX_DIR="${LLVM_DIR}/projects/libcxx"
+LIBCXXABI_DIR="${LLVM_DIR}/projects/libcxxabi"
+ANDROID_NDK_DIR="${THIS_DIR}/../../../third_party/android_tools/ndk"
+STAMP_FILE="${LLVM_DIR}/../llvm-build/cr_build_revision"
+CHROMIUM_TOOLS_DIR="${THIS_DIR}/.."
+BINUTILS_DIR="${THIS_DIR}/../../../third_party/binutils"
+
+ABS_CHROMIUM_TOOLS_DIR="${PWD}/${CHROMIUM_TOOLS_DIR}"
+ABS_LIBCXX_DIR="${PWD}/${LIBCXX_DIR}"
+ABS_LIBCXXABI_DIR="${PWD}/${LIBCXXABI_DIR}"
+ABS_LLVM_DIR="${PWD}/${LLVM_DIR}"
+ABS_LLVM_BUILD_DIR="${PWD}/${LLVM_BUILD_DIR}"
+ABS_COMPILER_RT_DIR="${PWD}/${COMPILER_RT_DIR}"
+ABS_BINUTILS_DIR="${PWD}/${BINUTILS_DIR}"
+
+# ${A:-a} returns $A if it's set, a else.
+LLVM_REPO_URL=${LLVM_URL:-https://llvm.org/svn/llvm-project}
+
+CDS_URL=https://commondatastorage.googleapis.com/chromium-browser-clang
+
+if [[ -z "$GYP_DEFINES" ]]; then
+  GYP_DEFINES=
+fi
+if [[ -z "$GYP_GENERATORS" ]]; then
+  GYP_GENERATORS=
+fi
+if [[ -z "$LLVM_DOWNLOAD_GOLD_PLUGIN" ]]; then
+  LLVM_DOWNLOAD_GOLD_PLUGIN=
+fi
+
+
+# Die if any command dies, error on undefined variable expansions.
+set -eu
+
+
+if [[ -n ${LLVM_FORCE_HEAD_REVISION:-''} ]]; then
+  # Use a real revision number rather than HEAD to make sure that the stamp file
+  # logic works.
+  CLANG_REVISION=$(svn info "$LLVM_REPO_URL" \
+      | grep 'Revision:' | awk '{ printf $2; }')
+  PACKAGE_VERSION="${CLANG_REVISION}-0"
+fi
+
+OS="$(uname -s)"
+
+# Parse command line options.
+if_needed=
+force_local_build=
+run_tests=
+bootstrap=
+with_android=yes
+chrome_tools="plugins;blink_gc_plugin"
+gcc_toolchain=
+with_patches=yes
+
+if [[ "${OS}" = "Darwin" ]]; then
+  with_android=
+fi
+
+while [[ $# > 0 ]]; do
+  case $1 in
+    --bootstrap)
+      bootstrap=yes
+      ;;
+    --if-needed)
+      if_needed=yes
+      ;;
+    --force-local-build)
+      force_local_build=yes
+      ;;
+    --print-revision)
+      if [[ -n ${LLVM_FORCE_HEAD_REVISION:-''} ]]; then
+        svn info "$LLVM_DIR" | grep 'Revision:' | awk '{ printf $2; }'
+      else
+        echo $PACKAGE_VERSION
+      fi
+      exit 0
+      ;;
+    --run-tests)
+      run_tests=yes
+      ;;
+    --without-android)
+      with_android=
+      ;;
+    --without-patches)
+      with_patches=
+      ;;
+    --with-chrome-tools)
+      shift
+      if [[ $# == 0 ]]; then
+        echo "--with-chrome-tools requires an argument."
+        exit 1
+      fi
+      chrome_tools=$1
+      ;;
+    --gcc-toolchain)
+      shift
+      if [[ $# == 0 ]]; then
+        echo "--gcc-toolchain requires an argument."
+        exit 1
+      fi
+      if [[ -x "$1/bin/gcc" ]]; then
+        gcc_toolchain=$1
+      else
+        echo "Invalid --gcc-toolchain: '$1'."
+        echo "'$1/bin/gcc' does not appear to be valid."
+        exit 1
+      fi
+      ;;
+
+    --help)
+      echo "usage: $0 [--force-local-build] [--if-needed] [--run-tests] "
+      echo "--bootstrap: First build clang with CC, then with itself."
+      echo "--force-local-build: Don't try to download prebuilt binaries."
+      echo "--if-needed: Download clang only if the script thinks it is needed."
+      echo "--run-tests: Run tests after building. Only for local builds."
+      echo "--print-revision: Print current clang revision and exit."
+      echo "--without-android: Don't build ASan Android runtime library."
+      echo "--with-chrome-tools: Select which chrome tools to build." \
+           "Defaults to plugins;blink_gc_plugin."
+      echo "    Example: --with-chrome-tools plugins;empty-string"
+      echo "--gcc-toolchain: Set the prefix for which GCC version should"
+      echo "    be used for building. For example, to use gcc in"
+      echo "    /opt/foo/bin/gcc, use '--gcc-toolchain '/opt/foo"
+      echo "--without-patches: Don't apply local patches."
+      echo
+      exit 1
+      ;;
+    *)
+      echo "Unknown argument: '$1'."
+      echo "Use --help for help."
+      exit 1
+      ;;
+  esac
+  shift
+done
+
+if [[ -n ${LLVM_FORCE_HEAD_REVISION:-''} ]]; then
+  force_local_build=yes
+
+  # Skip local patches when using HEAD: they probably don't apply anymore.
+  with_patches=
+
+  if ! [[ "$GYP_DEFINES" =~ .*OS=android.* ]]; then
+    # Only build the Android ASan rt when targetting Android.
+    with_android=
+  fi
+
+  LLVM_BUILD_TOOLS_DIR="${ABS_LLVM_DIR}/../llvm-build-tools"
+
+  if [[ "${OS}" == "Linux" ]] && [[ -z "${gcc_toolchain}" ]]; then
+    if [[ $(gcc -dumpversion) < "4.7.0" ]]; then
+      # We need a newer GCC version.
+      if [[ ! -e "${LLVM_BUILD_TOOLS_DIR}/gcc482" ]]; then
+        echo "Downloading pre-built GCC 4.8.2..."
+        mkdir -p "${LLVM_BUILD_TOOLS_DIR}"
+        curl --fail -L "${CDS_URL}/tools/gcc482.tgz" | \
+          tar zxf - -C "${LLVM_BUILD_TOOLS_DIR}"
+        echo Done
+      fi
+      gcc_toolchain="${LLVM_BUILD_TOOLS_DIR}/gcc482"
+    else
+      # Always set gcc_toolchain; llvm-symbolizer needs the bundled libstdc++.
+      gcc_toolchain="$(dirname $(dirname $(which gcc)))"
+    fi
+  fi
+
+  if [[ "${OS}" == "Linux" || "${OS}" == "Darwin" ]]; then
+    if [[ $(cmake --version | grep -Eo '[0-9.]+') < "3.0" ]]; then
+      # We need a newer CMake version.
+      if [[ ! -e "${LLVM_BUILD_TOOLS_DIR}/cmake310" ]]; then
+        echo "Downloading pre-built CMake 3.10..."
+        mkdir -p "${LLVM_BUILD_TOOLS_DIR}"
+        curl --fail -L "${CDS_URL}/tools/cmake310_${OS}.tgz" | \
+          tar zxf - -C "${LLVM_BUILD_TOOLS_DIR}"
+        echo Done
+      fi
+      export PATH="${LLVM_BUILD_TOOLS_DIR}/cmake310/bin:${PATH}"
+    fi
+  fi
+
+  echo "LLVM_FORCE_HEAD_REVISION was set; using r${CLANG_REVISION}"
+fi
+
+if [[ -n "$if_needed" ]]; then
+  if [[ "${OS}" == "Darwin" ]]; then
+    # clang is always used on Mac.
+    true
+  elif [[ "${OS}" == "Linux" ]]; then
+    # clang is also aways used on Linux.
+    true
+  elif [[ "$GYP_DEFINES" =~ .*(clang|tsan|asan|lsan|msan)=1.* ]]; then
+    # clang requested via $GYP_DEFINES.
+    true
+  elif [[ -d "${LLVM_BUILD_DIR}" ]]; then
+    # clang previously downloaded, keep it up-to-date.
+    # If you don't want this, delete third_party/llvm-build on your machine.
+    true
+  else
+    # clang wasn't needed, not doing anything.
+    exit 0
+  fi
+fi
+
+
+# Check if there's anything to be done, exit early if not.
+if [[ -f "${STAMP_FILE}" ]]; then
+  PREVIOUSLY_BUILT_REVISON=$(cat "${STAMP_FILE}")
+  if [[ -z "$force_local_build" ]] && \
+       [[ "${PREVIOUSLY_BUILT_REVISON}" = \
+          "${PACKAGE_VERSION}" ]]; then
+    echo "Clang already at ${PACKAGE_VERSION}"
+    exit 0
+  fi
+fi
+# To always force a new build if someone interrupts their build half way.
+rm -f "${STAMP_FILE}"
+
+
+if [[ -z "$force_local_build" ]]; then
+  # Check if there's a prebuilt binary and if so just fetch that. That's faster,
+  # and goma relies on having matching binary hashes on client and server too.
+  CDS_FILE="clang-${PACKAGE_VERSION}.tgz"
+  CDS_OUT_DIR=$(mktemp -d -t clang_download.XXXXXX)
+  CDS_OUTPUT="${CDS_OUT_DIR}/${CDS_FILE}"
+  if [ "${OS}" = "Linux" ]; then
+    CDS_FULL_URL="${CDS_URL}/Linux_x64/${CDS_FILE}"
+  elif [ "${OS}" = "Darwin" ]; then
+    CDS_FULL_URL="${CDS_URL}/Mac/${CDS_FILE}"
+  fi
+  echo Trying to download prebuilt clang
+  if which curl > /dev/null; then
+    curl -L --fail "${CDS_FULL_URL}" -o "${CDS_OUTPUT}" || \
+        rm -rf "${CDS_OUT_DIR}"
+  elif which wget > /dev/null; then
+    wget "${CDS_FULL_URL}" -O "${CDS_OUTPUT}" || rm -rf "${CDS_OUT_DIR}"
+  else
+    echo "Neither curl nor wget found. Please install one of these."
+    exit 1
+  fi
+  if [ -f "${CDS_OUTPUT}" ]; then
+    rm -rf "${LLVM_BUILD_DIR}"
+    mkdir -p "${LLVM_BUILD_DIR}"
+    tar -xzf "${CDS_OUTPUT}" -C "${LLVM_BUILD_DIR}"
+    echo clang "${PACKAGE_VERSION}" unpacked
+    echo "${PACKAGE_VERSION}" > "${STAMP_FILE}"
+    rm -rf "${CDS_OUT_DIR}"
+    # Download the gold plugin if requested to by an environment variable.
+    # This is used by the CFI ClusterFuzz bot.
+    if [[ -n "${LLVM_DOWNLOAD_GOLD_PLUGIN}" ]]; then
+      ${THIS_DIR}/../../../build/download_gold_plugin.py
+    fi
+    exit 0
+  else
+    echo Did not find prebuilt clang "${PACKAGE_VERSION}", building
+  fi
+fi
+
+if [[ -n "${with_android}" ]] && ! [[ -d "${ANDROID_NDK_DIR}" ]]; then
+  echo "Android NDK not found at ${ANDROID_NDK_DIR}"
+  echo "The Android NDK is needed to build a Clang whose -fsanitize=address"
+  echo "works on Android. See "
+  echo "http://code.google.com/p/chromium/wiki/AndroidBuildInstructions for how"
+  echo "to install the NDK, or pass --without-android."
+  exit 1
+fi
+
+# Check that cmake and ninja are available.
+if ! which cmake > /dev/null; then
+  echo "CMake needed to build clang; please install"
+  exit 1
+fi
+if ! which ninja > /dev/null; then
+  echo "ninja needed to build clang, please install"
+  exit 1
+fi
+
+echo Reverting previously patched files
+for i in \
+      "${CLANG_DIR}/test/Index/crash-recovery-modules.m" \
+      "${CLANG_DIR}/unittests/libclang/LibclangTest.cpp" \
+      "${COMPILER_RT_DIR}/lib/asan/asan_rtl.cc" \
+      "${COMPILER_RT_DIR}/test/asan/TestCases/Linux/new_array_cookie_test.cc" \
+      "${LLVM_DIR}/test/DebugInfo/gmlt.ll" \
+      "${LLVM_DIR}/lib/CodeGen/SpillPlacement.cpp" \
+      "${LLVM_DIR}/lib/CodeGen/SpillPlacement.h" \
+      "${LLVM_DIR}/lib/Transforms/Instrumentation/MemorySanitizer.cpp" \
+      "${CLANG_DIR}/test/Driver/env.c" \
+      "${CLANG_DIR}/lib/Frontend/InitPreprocessor.cpp" \
+      "${CLANG_DIR}/test/Frontend/exceptions.c" \
+      "${CLANG_DIR}/test/Preprocessor/predefined-exceptions.m" \
+      "${LLVM_DIR}/test/Bindings/Go/go.test" \
+      "${CLANG_DIR}/lib/Parse/ParseExpr.cpp" \
+      "${CLANG_DIR}/lib/Parse/ParseTemplate.cpp" \
+      "${CLANG_DIR}/lib/Sema/SemaDeclCXX.cpp" \
+      "${CLANG_DIR}/lib/Sema/SemaExprCXX.cpp" \
+      "${CLANG_DIR}/test/SemaCXX/default2.cpp" \
+      "${CLANG_DIR}/test/SemaCXX/typo-correction-delayed.cpp" \
+      "${COMPILER_RT_DIR}/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc" \
+      "${COMPILER_RT_DIR}/test/tsan/signal_segv_handler.cc" \
+      "${COMPILER_RT_DIR}/lib/sanitizer_common/sanitizer_coverage_libcdep.cc" \
+      "${COMPILER_RT_DIR}/cmake/config-ix.cmake" \
+      "${COMPILER_RT_DIR}/CMakeLists.txt" \
+      "${COMPILER_RT_DIR}/lib/ubsan/ubsan_platform.h" \
+      ; do
+  if [[ -e "${i}" ]]; then
+    rm -f "${i}"  # For unversioned files.
+    svn revert "${i}"
+  fi;
+done
+
+echo Remove the Clang tools shim dir
+CHROME_TOOLS_SHIM_DIR=${ABS_LLVM_DIR}/tools/chrometools
+rm -rfv ${CHROME_TOOLS_SHIM_DIR}
+
+echo Getting LLVM r"${CLANG_REVISION}" in "${LLVM_DIR}"
+if ! svn co --force "${LLVM_REPO_URL}/llvm/trunk@${CLANG_REVISION}" \
+                    "${LLVM_DIR}"; then
+  echo Checkout failed, retrying
+  rm -rf "${LLVM_DIR}"
+  svn co --force "${LLVM_REPO_URL}/llvm/trunk@${CLANG_REVISION}" "${LLVM_DIR}"
+fi
+
+echo Getting clang r"${CLANG_REVISION}" in "${CLANG_DIR}"
+svn co --force "${LLVM_REPO_URL}/cfe/trunk@${CLANG_REVISION}" "${CLANG_DIR}"
+
+# We have moved from building compiler-rt in the LLVM tree, to a separate
+# directory. Nuke any previous checkout to avoid building it.
+rm -rf "${LLVM_DIR}/projects/compiler-rt"
+
+echo Getting compiler-rt r"${CLANG_REVISION}" in "${COMPILER_RT_DIR}"
+svn co --force "${LLVM_REPO_URL}/compiler-rt/trunk@${CLANG_REVISION}" \
+               "${COMPILER_RT_DIR}"
+
+# clang needs a libc++ checkout, else -stdlib=libc++ won't find includes
+# (i.e. this is needed for bootstrap builds).
+if [ "${OS}" = "Darwin" ]; then
+  echo Getting libc++ r"${CLANG_REVISION}" in "${LIBCXX_DIR}"
+  svn co --force "${LLVM_REPO_URL}/libcxx/trunk@${CLANG_REVISION}" \
+                 "${LIBCXX_DIR}"
+fi
+
+# While we're bundling our own libc++ on OS X, we need to compile libc++abi
+# into it too (since OS X 10.6 doesn't have libc++abi.dylib either).
+if [ "${OS}" = "Darwin" ]; then
+  echo Getting libc++abi r"${CLANG_REVISION}" in "${LIBCXXABI_DIR}"
+  svn co --force "${LLVM_REPO_URL}/libcxxabi/trunk@${CLANG_REVISION}" \
+                 "${LIBCXXABI_DIR}"
+fi
+
+if [[ -n "$with_patches" ]]; then
+
+  # Apply patch for tests failing with --disable-pthreads (llvm.org/PR11974)
+  pushd "${CLANG_DIR}"
+  cat << 'EOF' |
+--- test/Index/crash-recovery-modules.m	(revision 202554)
++++ test/Index/crash-recovery-modules.m	(working copy)
+@@ -12,6 +12,8 @@
+ 
+ // REQUIRES: crash-recovery
+ // REQUIRES: shell
++// XFAIL: *
++//    (PR11974)
+ 
+ @import Crash;
+EOF
+patch -p0
+popd
+
+pushd "${CLANG_DIR}"
+cat << 'EOF' |
+--- unittests/libclang/LibclangTest.cpp (revision 215949)
++++ unittests/libclang/LibclangTest.cpp (working copy)
+@@ -431,7 +431,7 @@
+   EXPECT_EQ(0U, clang_getNumDiagnostics(ClangTU));
+ }
+
+-TEST_F(LibclangReparseTest, ReparseWithModule) {
++TEST_F(LibclangReparseTest, DISABLED_ReparseWithModule) {
+   const char *HeaderTop = "#ifndef H\n#define H\nstruct Foo { int bar;";
+   const char *HeaderBottom = "\n};\n#endif\n";
+   const char *MFile = "#include \"HeaderFile.h\"\nint main() {"
+EOF
+  patch -p0
+  popd
+
+  # This Go bindings test doesn't work after the bootstrap build on Linux. (PR21552)
+  pushd "${LLVM_DIR}"
+  cat << 'EOF' |
+--- test/Bindings/Go/go.test    (revision 223109)
++++ test/Bindings/Go/go.test    (working copy)
+@@ -1,3 +1,3 @@
+-; RUN: llvm-go test llvm.org/llvm/bindings/go/llvm
++; RUN: true
+ 
+ ; REQUIRES: shell
+EOF
+  patch -p0
+  popd
+
+  # The UBSan run-time, which is now bundled with the ASan run-time, doesn't work
+  # on Mac OS X 10.8 (PR23539).
+  pushd "${COMPILER_RT_DIR}"
+  cat << 'EOF' |
+Index: CMakeLists.txt
+===================================================================
+--- CMakeLists.txt	(revision 241602)
++++ CMakeLists.txt	(working copy)
+@@ -305,6 +305,7 @@
+       list(APPEND SANITIZER_COMMON_SUPPORTED_OS iossim)
+     endif()
+   endif()
++  set(SANITIZER_MIN_OSX_VERSION "10.7")
+   if(SANITIZER_MIN_OSX_VERSION VERSION_LESS "10.7")
+     message(FATAL_ERROR "Too old OS X version: ${SANITIZER_MIN_OSX_VERSION}")
+   endif()
+EOF
+  patch -p0
+  popd
+
+fi
+
+# Echo all commands.
+set -x
+
+# Set default values for CC and CXX if they're not set in the environment.
+CC=${CC:-cc}
+CXX=${CXX:-c++}
+
+if [[ -n "${gcc_toolchain}" ]]; then
+  # Use the specified gcc installation for building.
+  CC="$gcc_toolchain/bin/gcc"
+  CXX="$gcc_toolchain/bin/g++"
+  # Set LD_LIBRARY_PATH to make auxiliary targets (tablegen, bootstrap compiler,
+  # etc.) find the .so.
+  export LD_LIBRARY_PATH="$(dirname $(${CXX} -print-file-name=libstdc++.so.6))"
+fi
+
+CFLAGS=""
+CXXFLAGS=""
+LDFLAGS=""
+
+# LLVM uses C++11 starting in llvm 3.5. On Linux, this means libstdc++4.7+ is
+# needed, on OS X it requires libc++. clang only automatically links to libc++
+# when targeting OS X 10.9+, so add stdlib=libc++ explicitly so clang can run on
+# OS X versions as old as 10.7.
+# TODO(thakis): Some bots are still on 10.6 (nacl...), so for now bundle
+# libc++.dylib.  Remove this once all bots are on 10.7+, then use
+# -DLLVM_ENABLE_LIBCXX=ON and change deployment_target to 10.7.
+deployment_target=""
+
+if [ "${OS}" = "Darwin" ]; then
+  # When building on 10.9, /usr/include usually doesn't exist, and while
+  # Xcode's clang automatically sets a sysroot, self-built clangs don't.
+  CFLAGS="-isysroot $(xcrun --show-sdk-path)"
+  CXXFLAGS="-stdlib=libc++ -nostdinc++ -I${ABS_LIBCXX_DIR}/include ${CFLAGS}"
+
+  if [[ -n "${bootstrap}" ]]; then
+    deployment_target=10.6
+  fi
+fi
+
+# Build bootstrap clang if requested.
+if [[ -n "${bootstrap}" ]]; then
+  ABS_INSTALL_DIR="${PWD}/${LLVM_BOOTSTRAP_INSTALL_DIR}"
+  echo "Building bootstrap compiler"
+  mkdir -p "${LLVM_BOOTSTRAP_DIR}"
+  pushd "${LLVM_BOOTSTRAP_DIR}"
+
+  cmake -GNinja \
+      -DCMAKE_BUILD_TYPE=Release \
+      -DLLVM_ENABLE_ASSERTIONS=ON \
+      -DLLVM_TARGETS_TO_BUILD=host \
+      -DLLVM_ENABLE_THREADS=OFF \
+      -DCMAKE_INSTALL_PREFIX="${ABS_INSTALL_DIR}" \
+      -DCMAKE_C_COMPILER="${CC}" \
+      -DCMAKE_CXX_COMPILER="${CXX}" \
+      -DCMAKE_C_FLAGS="${CFLAGS}" \
+      -DCMAKE_CXX_FLAGS="${CXXFLAGS}" \
+      ../llvm
+
+  ninja
+  if [[ -n "${run_tests}" ]]; then
+    ninja check-all
+  fi
+
+  ninja install
+  if [[ -n "${gcc_toolchain}" ]]; then
+    # Copy that gcc's stdlibc++.so.6 to the build dir, so the bootstrap
+    # compiler can start.
+    cp -v "$(${CXX} -print-file-name=libstdc++.so.6)" \
+      "${ABS_INSTALL_DIR}/lib/"
+  fi
+
+  popd
+  CC="${ABS_INSTALL_DIR}/bin/clang"
+  CXX="${ABS_INSTALL_DIR}/bin/clang++"
+
+  if [[ -n "${gcc_toolchain}" ]]; then
+    # Tell the bootstrap compiler to use a specific gcc prefix to search
+    # for standard library headers and shared object file.
+    CFLAGS="--gcc-toolchain=${gcc_toolchain}"
+    CXXFLAGS="--gcc-toolchain=${gcc_toolchain}"
+  fi
+
+  echo "Building final compiler"
+fi
+
+# Build clang (in a separate directory).
+# The clang bots have this path hardcoded in built/scripts/slave/compile.py,
+# so if you change it you also need to change these links.
+mkdir -p "${LLVM_BUILD_DIR}"
+pushd "${LLVM_BUILD_DIR}"
+
+# Build libc++.dylib while some bots are still on OS X 10.6.
+if [ "${OS}" = "Darwin" ]; then
+  rm -rf libcxxbuild
+  LIBCXXFLAGS="-O3 -std=c++11 -fstrict-aliasing"
+
+  # libcxx and libcxxabi both have a file stdexcept.cpp, so put their .o files
+  # into different subdirectories.
+  mkdir -p libcxxbuild/libcxx
+  pushd libcxxbuild/libcxx
+  ${CXX:-c++} -c ${CXXFLAGS} ${LIBCXXFLAGS} "${ABS_LIBCXX_DIR}"/src/*.cpp
+  popd
+
+  mkdir -p libcxxbuild/libcxxabi
+  pushd libcxxbuild/libcxxabi
+  ${CXX:-c++} -c ${CXXFLAGS} ${LIBCXXFLAGS} "${ABS_LIBCXXABI_DIR}"/src/*.cpp -I"${ABS_LIBCXXABI_DIR}/include"
+  popd
+
+  pushd libcxxbuild
+  ${CC:-cc} libcxx/*.o libcxxabi/*.o -o libc++.1.dylib -dynamiclib \
+    -nodefaultlibs -current_version 1 -compatibility_version 1 \
+    -lSystem -install_name @executable_path/libc++.dylib \
+    -Wl,-unexported_symbols_list,${ABS_LIBCXX_DIR}/lib/libc++unexp.exp \
+    -Wl,-force_symbols_not_weak_list,${ABS_LIBCXX_DIR}/lib/notweak.exp \
+    -Wl,-force_symbols_weak_list,${ABS_LIBCXX_DIR}/lib/weak.exp
+  ln -sf libc++.1.dylib libc++.dylib
+  popd
+  LDFLAGS+="-stdlib=libc++ -L${PWD}/libcxxbuild"
+
+  if [[ -n "${bootstrap}" ]]; then
+    # Now that the libc++ headers have been installed and libc++.dylib is built,
+    # delete the libc++ checkout again so that it's not part of the main
+    # build below -- the libc++(abi) tests don't pass on OS X in bootstrap
+    # builds (http://llvm.org/PR24068)
+    rm -rf "${ABS_LIBCXX_DIR}"
+    rm -rf "${ABS_LIBCXXABI_DIR}"
+    CXXFLAGS="-stdlib=libc++ -nostdinc++ -I${ABS_INSTALL_DIR}/include/c++/v1 ${CFLAGS}"
+  fi
+fi
+
+# Find the binutils include dir for the gold plugin.
+BINUTILS_INCDIR=""
+if [ "${OS}" = "Linux" ]; then
+  BINUTILS_INCDIR="${ABS_BINUTILS_DIR}/Linux_x64/Release/include"
+fi
+
+
+# If building at head, define a macro that plugins can use for #ifdefing
+# out code that builds at head, but not at CLANG_REVISION or vice versa.
+if [[ -n ${LLVM_FORCE_HEAD_REVISION:-''} ]]; then
+  CFLAGS="${CFLAGS} -DLLVM_FORCE_HEAD_REVISION"
+  CXXFLAGS="${CXXFLAGS} -DLLVM_FORCE_HEAD_REVISION"
+fi
+
+# Hook the Chromium tools into the LLVM build. Several Chromium tools have
+# dependencies on LLVM/Clang libraries. The LLVM build detects implicit tools
+# in the tools subdirectory, so install a shim CMakeLists.txt that forwards to
+# the real directory for the Chromium tools.
+# Note that the shim directory name intentionally has no _ or _. The implicit
+# tool detection logic munges them in a weird way.
+mkdir -v ${CHROME_TOOLS_SHIM_DIR}
+cat > ${CHROME_TOOLS_SHIM_DIR}/CMakeLists.txt << EOF
+# Since tools/clang isn't actually a subdirectory, use the two argument version
+# to specify where build artifacts go. CMake doesn't allow reusing the same
+# binary dir for multiple source dirs, so the build artifacts have to go into a
+# subdirectory...
+add_subdirectory(\${CHROMIUM_TOOLS_SRC} \${CMAKE_CURRENT_BINARY_DIR}/a)
+EOF
+rm -fv CMakeCache.txt
+MACOSX_DEPLOYMENT_TARGET=${deployment_target} cmake -GNinja \
+    -DCMAKE_BUILD_TYPE=Release \
+    -DLLVM_ENABLE_ASSERTIONS=ON \
+    -DLLVM_ENABLE_THREADS=OFF \
+    -DLLVM_BINUTILS_INCDIR="${BINUTILS_INCDIR}" \
+    -DCMAKE_C_COMPILER="${CC}" \
+    -DCMAKE_CXX_COMPILER="${CXX}" \
+    -DCMAKE_C_FLAGS="${CFLAGS}" \
+    -DCMAKE_CXX_FLAGS="${CXXFLAGS}" \
+    -DCMAKE_EXE_LINKER_FLAGS="${LDFLAGS}" \
+    -DCMAKE_SHARED_LINKER_FLAGS="${LDFLAGS}" \
+    -DCMAKE_MODULE_LINKER_FLAGS="${LDFLAGS}" \
+    -DCMAKE_INSTALL_PREFIX="${ABS_LLVM_BUILD_DIR}" \
+    -DCHROMIUM_TOOLS_SRC="${ABS_CHROMIUM_TOOLS_DIR}" \
+    -DCHROMIUM_TOOLS="${chrome_tools}" \
+    "${ABS_LLVM_DIR}"
+env
+
+if [[ -n "${gcc_toolchain}" ]]; then
+  # Copy in the right stdlibc++.so.6 so clang can start.
+  mkdir -p lib
+  cp -v "$(${CXX} ${CXXFLAGS} -print-file-name=libstdc++.so.6)" lib/
+fi
+
+ninja
+# If any Chromium tools were built, install those now.
+if [[ -n "${chrome_tools}" ]]; then
+  ninja cr-install
+fi
+
+STRIP_FLAGS=
+if [ "${OS}" = "Darwin" ]; then
+  # See http://crbug.com/256342
+  STRIP_FLAGS=-x
+
+  cp libcxxbuild/libc++.1.dylib bin/
+fi
+strip ${STRIP_FLAGS} bin/clang
+popd
+
+# Build compiler-rt out-of-tree.
+mkdir -p "${COMPILER_RT_BUILD_DIR}"
+pushd "${COMPILER_RT_BUILD_DIR}"
+
+rm -fv CMakeCache.txt
+MACOSX_DEPLOYMENT_TARGET=${deployment_target} cmake -GNinja \
+    -DCMAKE_BUILD_TYPE=Release \
+    -DLLVM_ENABLE_ASSERTIONS=ON \
+    -DLLVM_ENABLE_THREADS=OFF \
+    -DCMAKE_C_COMPILER="${CC}" \
+    -DCMAKE_CXX_COMPILER="${CXX}" \
+    -DLLVM_CONFIG_PATH="${ABS_LLVM_BUILD_DIR}/bin/llvm-config" \
+    "${ABS_COMPILER_RT_DIR}"
+
+ninja
+
+# Copy selected output to the main tree.
+# Darwin doesn't support cp --parents, so pipe through tar instead.
+CLANG_VERSION=$("${ABS_LLVM_BUILD_DIR}/bin/clang" --version | \
+     sed -ne 's/clang version \([0-9]\.[0-9]\.[0-9]\).*/\1/p')
+ABS_LLVM_CLANG_LIB_DIR="${ABS_LLVM_BUILD_DIR}/lib/clang/${CLANG_VERSION}"
+tar -c *blacklist.txt | tar -C ${ABS_LLVM_CLANG_LIB_DIR} -xv
+tar -c include/sanitizer | tar -C ${ABS_LLVM_CLANG_LIB_DIR} -xv
+if [[ "${OS}" = "Darwin" ]]; then
+  tar -c lib/darwin | tar -C ${ABS_LLVM_CLANG_LIB_DIR} -xv
+else
+  tar -c lib/linux | tar -C ${ABS_LLVM_CLANG_LIB_DIR} -xv
+fi
+
+popd
+
+if [[ -n "${with_android}" ]]; then
+  # Make a standalone Android toolchain.
+  ${ANDROID_NDK_DIR}/build/tools/make-standalone-toolchain.sh \
+      --platform=android-19 \
+      --install-dir="${LLVM_BUILD_DIR}/android-toolchain" \
+      --system=linux-x86_64 \
+      --stl=stlport \
+      --toolchain=arm-linux-androideabi-4.9
+
+  # Android NDK r9d copies a broken unwind.h into the toolchain, see
+  # http://crbug.com/357890
+  rm -v "${LLVM_BUILD_DIR}"/android-toolchain/include/c++/*/unwind.h
+
+  # Build ASan runtime for Android in a separate build tree.
+  mkdir -p ${LLVM_BUILD_DIR}/android
+  pushd ${LLVM_BUILD_DIR}/android
+  rm -fv CMakeCache.txt
+  MACOSX_DEPLOYMENT_TARGET=${deployment_target} cmake -GNinja \
+      -DCMAKE_BUILD_TYPE=Release \
+      -DLLVM_ENABLE_ASSERTIONS=ON \
+      -DLLVM_ENABLE_THREADS=OFF \
+      -DCMAKE_C_COMPILER=${PWD}/../bin/clang \
+      -DCMAKE_CXX_COMPILER=${PWD}/../bin/clang++ \
+      -DLLVM_CONFIG_PATH=${PWD}/../bin/llvm-config \
+      -DCMAKE_C_FLAGS="--target=arm-linux-androideabi --sysroot=${PWD}/../android-toolchain/sysroot -B${PWD}/../android-toolchain" \
+      -DCMAKE_CXX_FLAGS="--target=arm-linux-androideabi --sysroot=${PWD}/../android-toolchain/sysroot -B${PWD}/../android-toolchain" \
+      -DANDROID=1 \
+      "${ABS_COMPILER_RT_DIR}"
+  ninja libclang_rt.asan-arm-android.so
+
+  # And copy it into the main build tree.
+  cp "$(find -name libclang_rt.asan-arm-android.so)" "${ABS_LLVM_CLANG_LIB_DIR}/lib/linux/"
+  popd
+fi
+
+if [[ -n "$run_tests" || -n "${LLVM_FORCE_HEAD_REVISION:-''}" ]]; then
+  # Run Chrome tool tests.
+  ninja -C "${LLVM_BUILD_DIR}" cr-check-all
+fi
+if [[ -n "$run_tests" ]]; then
+  # Run the LLVM and Clang tests.
+  ninja -C "${LLVM_BUILD_DIR}" check-all
+fi
+
+# After everything is done, log success for this revision.
+echo "${PACKAGE_VERSION}" > "${STAMP_FILE}"
diff --git a/tools/dartium/buildbot_annotated_steps.py b/tools/dartium/buildbot_annotated_steps.py
index f8eeb23..aeaed2f 100755
--- a/tools/dartium/buildbot_annotated_steps.py
+++ b/tools/dartium/buildbot_annotated_steps.py
@@ -53,6 +53,10 @@
     print '@@@STEP_FAILURE@@@'
   return status
 
+def ClearTemp():
+  if platform.system() == 'Windows':
+    shutil.rmtree('C:\\Users\\chrome-bot\\AppData\\Local\\Temp',
+                  ignore_errors=True)
 
 def Test(info, component, suite, checked, test_filter=None):
   """Test a particular component (e.g., dartium or content_shell(drt)).
@@ -70,6 +74,7 @@
                                         info.name,
                                         info.version,
                                         component, checked)
+  ClearTemp()
   return status
 
 
@@ -97,11 +102,10 @@
   if info.mode == 'Release' or platform.system() != 'Darwin':
     result = Test(info, 'drt', 'layout', 'unchecked') or result
     result = Test(info, 'drt', 'layout', 'checked') or result
-
   # Run dartium tests
   result = Test(info, 'dartium', 'core', 'unchecked') or result
   result = Test(info, 'dartium', 'core', 'checked') or result
-
+  
   # Run ContentShell tests
   # NOTE: We don't run ContentShell tests on dartium-*-inc builders to keep
   # cycle times down.
diff --git a/tools/deps/dartium.deps/DEPS b/tools/deps/dartium.deps/DEPS
index 43d002d..2083c3a 100644
--- a/tools/deps/dartium.deps/DEPS
+++ b/tools/deps/dartium.deps/DEPS
@@ -9,7 +9,7 @@
 
 vars.update({
   "dartium_chromium_commit": "a8ead7ec922730667be7112de7ec40abbfd5f5aa",
-  "dartium_webkit_commit": "1a294dcc3d47ae5e5ce58777df2e1b701b2b2b60",
+  "dartium_webkit_commit": "b32a113c16f0a46b0dd747f80f0ec78e8db3512b",
   "chromium_base_revision": "338390",
 
   # We use mirrors of all github repos to guarantee reproducibility and
@@ -40,7 +40,7 @@
   "http_parser_rev" : "@8b179e36aba985208e4c5fb15cfddd386b6370a4",
   "http_throttle_rev" : "@a81f08be942cdd608883c7b67795c12226abc235",
   "json_rpc_2_rev": "@a38eefd116d910199de205f962af92fed87c164c",
-  "kernel_rev": "@9677d68402ea15d0eca6430d64f631bb3e505499",
+  "kernel_rev": "@449803b82e850a41148e636db1a6e4a848284aed",
   "logging_rev": "@85d83e002670545e9039ad3985f0018ab640e597",
   "matcher_tag": "@0.12.0",
   "mime_rev": "@75890811d4af5af080351ba8a2853ad4c8df98dd",
diff --git a/tools/gn.py b/tools/gn.py
new file mode 100755
index 0000000..22f3530
--- /dev/null
+++ b/tools/gn.py
@@ -0,0 +1,161 @@
+#!/usr/bin/env python
+# Copyright 2016 The Dart project authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import subprocess
+import sys
+import os
+import utils
+
+HOST_OS = utils.GuessOS()
+HOST_ARCH = utils.GuessArchitecture()
+HOST_CPUS = utils.GuessCpus()
+SCRIPT_DIR = os.path.dirname(sys.argv[0])
+DART_ROOT = os.path.realpath(os.path.join(SCRIPT_DIR, '..'))
+
+def get_out_dir(args):
+  return utils.GetBuildRoot(HOST_OS, args.mode, args.arch, args.os)
+
+def to_command_line(gn_args):
+  def merge(key, value):
+    if type(value) is bool:
+      return '%s=%s' % (key, 'true' if value else 'false')
+    return '%s="%s"' % (key, value)
+  return [merge(x, y) for x, y in gn_args.iteritems()]
+
+def host_cpu_for_arch(arch):
+  if arch in ['ia32', 'arm', 'armv6', 'armv5te', 'mips',
+              'simarm', 'simarmv6', 'simarmv5te', 'simmips', 'simdbc']:
+    return 'x86'
+  if arch in ['x64', 'arm64', 'simarm64', 'simdbc64']:
+    return 'x64'
+
+def target_cpu_for_arch(arch, os):
+  if arch in ['ia32', 'simarm', 'simarmv6', 'simarmv5te', 'simmips']:
+    return 'x86'
+  if arch in ['simarm64']:
+    return 'x64'
+  if arch == 'mips':
+    return 'mipsel'
+  if arch == 'simdbc':
+    return 'arm' if os == 'android' else 'x86'
+  if arch == 'simdbc64':
+    return 'arm64' if os == 'android' else 'x64'
+  return arch
+
+def to_gn_args(args):
+  gn_args = {}
+
+  if args.os == 'host':
+    gn_args['target_os'] = HOST_OS
+  else:
+    gn_args['target_os'] = args.os
+
+  gn_args['dart_target_arch'] = args.arch
+  gn_args['target_cpu'] = target_cpu_for_arch(args.arch, args.os)
+  gn_args['host_cpu'] = host_cpu_for_arch(args.arch)
+
+  # TODO(zra): This is for the observatory, which currently builds using the
+  # checked-in sdk. If/when the observatory no longer builds with the
+  # checked-in sdk, this can be removed.
+  gn_args['dart_host_pub_exe'] = os.path.join(
+      DART_ROOT, 'tools', 'sdks', HOST_OS, 'dart-sdk', 'bin', 'pub')
+
+  # For Fuchsia support, the default is to not compile in the root
+  # certificates.
+  gn_args['dart_use_fallback_root_certificates'] = True
+
+  gn_args['dart_zlib_path'] = "//runtime/bin/zlib"
+
+  gn_args['dart_use_tcmalloc'] = gn_args['target_os'] == 'linux'
+
+  gn_args['is_debug'] = args.mode == 'debug'
+  gn_args['is_release'] = args.mode == 'release'
+  gn_args['is_product'] = args.mode == 'product'
+  gn_args['dart_debug'] = args.mode == 'debug'
+
+  # This setting is only meaningful for Flutter. Standalone builds of the VM
+  # should leave this set to 'develop', which causes the build to defer to
+  # 'is_debug', 'is_release' and 'is_product'.
+  gn_args['dart_runtime_mode'] = 'develop'
+
+  gn_args['is_clang'] = args.clang and args.os not in ['android']
+
+  if args.target_sysroot:
+    gn_args['target_sysroot'] = args.target_sysroot
+
+  if args.toolchain_prefix:
+    gn_args['toolchain_prefix'] = args.toolchain_prefix
+
+  goma_dir = os.environ.get('GOMA_DIR')
+  goma_home_dir = os.path.join(os.getenv('HOME', ''), 'goma')
+  if args.goma and goma_dir:
+    gn_args['use_goma'] = True
+    gn_args['goma_dir'] = goma_dir
+  elif args.goma and os.path.exists(goma_home_dir):
+    gn_args['use_goma'] = True
+    gn_args['goma_dir'] = goma_home_dir
+  else:
+    gn_args['use_goma'] = False
+    gn_args['goma_dir'] = None
+
+  return gn_args
+
+def parse_args(args):
+  args = args[1:]
+  parser = argparse.ArgumentParser(description='A script run` gn gen`.')
+
+  parser.add_argument('--mode', '-m',
+      type=str,
+      choices=['debug', 'release', 'product'],
+      default='debug')
+  parser.add_argument('--os',
+      type=str,
+      choices=['host', 'android'],
+      default='host')
+  parser.add_argument('--arch', '-a',
+      type=str,
+      choices=['ia32', 'x64', 'simarm', 'arm', 'simarmv6', 'armv6',
+               'simarmv5te', 'armv5te', 'simmips', 'mips', 'simarm64', 'arm64',
+               'simdbc', 'simdbc64'],
+      default='x64')
+
+  parser.add_argument('--goma', default=True, action='store_true')
+  parser.add_argument('--no-goma', dest='goma', action='store_false')
+
+  parser.add_argument('--clang', default=True, action='store_true')
+  parser.add_argument('--no-clang', dest='clang', action='store_false')
+
+  parser.add_argument('--target-sysroot', '-s', type=str)
+  parser.add_argument('--toolchain-prefix', '-t', type=str)
+
+  return parser.parse_args(args)
+
+def main(argv):
+  args = parse_args(argv)
+
+  if sys.platform.startswith(('cygwin', 'win')):
+    subdir = 'win'
+  elif sys.platform == 'darwin':
+    subdir = 'mac'
+  elif sys.platform.startswith('linux'):
+     subdir = 'linux64'
+  else:
+    raise Error('Unknown platform: ' + sys.platform)
+
+  command = [
+    '%s/buildtools/%s/gn' % (DART_ROOT, subdir),
+    'gen',
+    '--check'
+  ]
+  gn_args = to_command_line(to_gn_args(args))
+  out_dir = get_out_dir(args)
+  print "gn gen --check in %s" % out_dir
+  command.append(out_dir)
+  command.append('--args=%s' % ' '.join(gn_args))
+  return subprocess.call(command, cwd=DART_ROOT)
+
+if __name__ == '__main__':
+    sys.exit(main(sys.argv))
diff --git a/tools/test.dart b/tools/test.dart
index 76e4928..c66489e 100755
--- a/tools/test.dart
+++ b/tools/test.dart
@@ -56,7 +56,7 @@
 }
 
 void main(List<String> arguments) {
-  // This script is in [dart]/tools.
+  // This script is in [sdk]/tools.
   TestUtils.setDartDirUri(Platform.script.resolve('..'));
   _deleteTemporaryDartDirectories().then((_) {
     var optionsParser = new TestOptionsParser();
diff --git a/tools/testing/dart/test_options.dart b/tools/testing/dart/test_options.dart
index 917e236..936bb39 100644
--- a/tools/testing/dart/test_options.dart
+++ b/tools/testing/dart/test_options.dart
@@ -808,6 +808,40 @@
       configuration['selectors'] = selectorMap;
     }
 
+    // Put observatory_ui in a configuration with its own packages override.
+    // Only one value in the configuration map is mutable:
+    selectors = configuration['selectors'];
+    if (selectors.containsKey('observatory_ui')) {
+      if (selectors.length == 1) {
+        configuration['packages'] = TestUtils.dartDirUri
+          .resolve('runtime/observatory/.packages').toFilePath();
+      } else {
+        // Make a new configuration whose selectors map only contains
+        // observatory_ui, and remove the key from the original selectors.
+        // The only mutable value in the map is the selectors, so a
+        // shallow copy is safe.
+        var observatoryConfiguration = new Map.from(configuration);
+        observatoryConfiguration['selectors'] =
+          {'observatory_ui': selectors['observatory_ui']};
+        selectors.remove('observatory_ui');
+
+        // Set the packages flag.
+        observatoryConfiguration['packages'] = TestUtils.dartDirUri
+          .resolve('runtime/observatory/.packages').toFilePath();
+
+        // Return the expansions of both configurations. Neither will reach
+        // this line in the recursive call to _expandConfigurations.
+        return _expandConfigurations(configuration)
+          ..addAll(_expandConfigurations(observatoryConfiguration));
+      }
+    }
+    // Set the default package spec explicitly.
+    if (configuration['package_root'] == null &&
+        configuration['packages'] == null) {
+      configuration['packages'] =
+        TestUtils.dartDirUri.resolve('.packages').toFilePath();     
+    }
+    
     // Expand the architectures.
     if (configuration['arch'].contains(',')) {
       return _expandHelper('arch', configuration);
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index f5707b8..cf6a1a0 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -302,7 +302,8 @@
 
     if (configuration['hot_reload'] || configuration['hot_reload_rollback']) {
       // Handle reload special cases.
-      if (expectations.contains(Expectation.COMPILETIME_ERROR)) {
+      if (expectations.contains(Expectation.COMPILETIME_ERROR) ||
+          testCase.hasCompileError || testCase.expectCompileError) {
         // Running a test that expects a compilation error with hot reloading
         // is redundant with a regular run of the test.
         return;
@@ -970,15 +971,17 @@
         }
       }
     }
-    if (configuration['package_root'] != null) {
-      packageRoot = new Path(configuration['package_root']);
-      optionsFromFile['packageRoot'] = packageRoot.toNativePath();
+    if (optionsFromFile['packageRoot'] == null &&
+        optionsFromFile['packages'] == null) {
+      if (configuration['package_root'] != null) {
+        packageRoot = new Path(configuration['package_root']);
+        optionsFromFile['packageRoot'] = packageRoot.toNativePath();
+      }
+      if (configuration['packages'] != null) {
+        Path packages = new Path(configuration['packages']);
+        optionsFromFile['packages'] = packages.toNativePath();
+      }
     }
-    if (configuration['packages'] != null) {
-      Path packages = new Path(configuration['packages']);
-      optionsFromFile['packages'] = packages.toNativePath();
-    }
-
     if (new CompilerConfiguration(configuration).hasCompiler &&
         expectCompileError(info)) {
       // If a compile-time error is expected, and we're testing a
@@ -1585,9 +1588,12 @@
 
   String packagesArgument(String packageRootFromFile,
                              String packagesFromFile) {
-    if (packagesFromFile != null) {
+    if (packageRootFromFile == 'none' ||
+        packagesFromFile == 'none') {
+      return null;
+    } else if (packagesFromFile != null) {
       return '--packages=$packagesFromFile';
-    } else if (packageRootFromFile != null && packageRootFromFile != 'none') {
+    } else if (packageRootFromFile != null) {
       return '--package-root=$packageRootFromFile';
     } else {
     return null;
@@ -1712,26 +1718,30 @@
 
     matches = packageRootRegExp.allMatches(contents);
     for (var match in matches) {
-      if (packageRoot != null) {
+      if (packageRoot != null || packages != null) {
         throw new Exception(
-            'More than one "// PackageRoot=" line in test $filePath');
+            'More than one "// Package... line in test $filePath');
       }
       packageRoot = match[1];
       if (packageRoot != 'none') {
-        // PackageRoot=none means that no package-root option should be given.
+        // PackageRoot=none means that no packages or package-root option
+        // should be given. Any other value overrides package-root and
+        // removes any packages option.  Don't use with // Packages=.
         packageRoot = '${filePath.directoryPath.join(new Path(packageRoot))}';
       }
     }
 
     matches = packagesRegExp.allMatches(contents);
     for (var match in matches) {
-      if (packages != null) {
+      if (packages != null || packageRoot != null) {
         throw new Exception(
-            'More than one "// Packages=" line in test $filePath');
+            'More than one "// Package..." line in test $filePath');
       }
       packages = match[1];
       if (packages != 'none') {
-        // Packages=none means that no packages option should be given.
+        // Packages=none means that no packages or package-root option
+        // should be given. Any other value overrides packages and removes
+        // any package-root option. Don't use with // PackageRoot=.
         packages = '${filePath.directoryPath.join(new Path(packages))}';
       }
     }
diff --git a/utils/analysis_server/analysis_server.gyp b/utils/analysis_server/analysis_server.gyp
index 8126e95..c238888 100644
--- a/utils/analysis_server/analysis_server.gyp
+++ b/utils/analysis_server/analysis_server.gyp
@@ -24,6 +24,7 @@
           ],
           'action': [
             '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)dart<(EXECUTABLE_SUFFIX)',
+            '--packages=../../.packages',
             '--snapshot=<(SHARED_INTERMEDIATE_DIR)/analysis_server.dart.snapshot',
             '../../pkg/analysis_server/bin/server.dart',
           ],
diff --git a/utils/compiler/compiler.gyp b/utils/compiler/compiler.gyp
index 201a4bb..63c4dae 100644
--- a/utils/compiler/compiler.gyp
+++ b/utils/compiler/compiler.gyp
@@ -31,6 +31,7 @@
           ],
           'action': [
             '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)dart<(EXECUTABLE_SUFFIX)',
+            '--packages=../../.packages',
             'create_snapshot.dart',
             '--output_dir=<(SHARED_INTERMEDIATE_DIR)',
             '--dart2js_main=pkg/compiler/lib/src/dart2js.dart',
diff --git a/utils/compiler/create_snapshot.dart b/utils/compiler/create_snapshot.dart
index 2b5b869..c2ca95e 100644
--- a/utils/compiler/create_snapshot.dart
+++ b/utils/compiler/create_snapshot.dart
@@ -63,7 +63,8 @@
 
 Future createSnapshot(var dart_file) {
   return Process.run(Platform.executable,
-                     ["--snapshot=$dart_file.snapshot",
+                     ["--packages=../../.packages",
+                      "--snapshot=$dart_file.snapshot",
                       dart_file])
       .then((result) {
         if (result.exitCode != 0) {
diff --git a/utils/dartanalyzer/dartanalyzer.gyp b/utils/dartanalyzer/dartanalyzer.gyp
index 3b65740..daf226c 100644
--- a/utils/dartanalyzer/dartanalyzer.gyp
+++ b/utils/dartanalyzer/dartanalyzer.gyp
@@ -24,6 +24,7 @@
           ],
           'action': [
             '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)dart<(EXECUTABLE_SUFFIX)',
+            '--packages=../../.packages',
             '--snapshot=<(SHARED_INTERMEDIATE_DIR)/dartanalyzer.dart.snapshot',
             '../../pkg/analyzer_cli/bin/analyzer.dart',
           ],
@@ -40,6 +41,7 @@
           ],
           'action': [
             '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)dart<(EXECUTABLE_SUFFIX)',
+            '--packages=../../.packages',
             '../../pkg/analyzer/tool/summary/build_sdk_summaries.dart',
             'build-spec',
             '<(SHARED_INTERMEDIATE_DIR)/spec.sum',
@@ -57,6 +59,7 @@
           ],
           'action': [
             '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)dart<(EXECUTABLE_SUFFIX)',
+            '--packages=../../.packages',
             '../../pkg/analyzer/tool/summary/build_sdk_summaries.dart',
             'build-strong',
             '<(SHARED_INTERMEDIATE_DIR)/strong.sum',
diff --git a/utils/dartdevc/dartdevc.gyp b/utils/dartdevc/dartdevc.gyp
index 4bf98f0..167327e 100644
--- a/utils/dartdevc/dartdevc.gyp
+++ b/utils/dartdevc/dartdevc.gyp
@@ -24,6 +24,7 @@
           ],
           'action': [
             '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)dart<(EXECUTABLE_SUFFIX)',
+            '--packages=../../.packages',
             '--snapshot=<(SHARED_INTERMEDIATE_DIR)/dartdevc.dart.snapshot',
             '../../pkg/dev_compiler/bin/dartdevc.dart'
           ],
diff --git a/utils/dartdoc/dartdoc.gyp b/utils/dartdoc/dartdoc.gyp
index d855cfe..dc5e414 100644
--- a/utils/dartdoc/dartdoc.gyp
+++ b/utils/dartdoc/dartdoc.gyp
@@ -23,6 +23,7 @@
           ],
           'action': [
             '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)dart<(EXECUTABLE_SUFFIX)',
+            '--packages=../../.packages',
             '--snapshot=<(SHARED_INTERMEDIATE_DIR)/dartdoc.dart.snapshot',
             '../../third_party/pkg/dartdoc/bin/dartdoc.dart',
           ],
diff --git a/utils/dartfmt/dartfmt.gyp b/utils/dartfmt/dartfmt.gyp
index 826d31a..a59ef9a 100644
--- a/utils/dartfmt/dartfmt.gyp
+++ b/utils/dartfmt/dartfmt.gyp
@@ -23,6 +23,7 @@
           ],
           'action': [
             '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)dart<(EXECUTABLE_SUFFIX)',
+            '--packages=../../.packages',
             '--snapshot=<(SHARED_INTERMEDIATE_DIR)/dartfmt.dart.snapshot',
             '../../third_party/pkg_tested/dart_style/bin/format.dart',
           ],
diff --git a/utils/pub/pub.gyp b/utils/pub/pub.gyp
index 13f2f5e..b568c0c 100644
--- a/utils/pub/pub.gyp
+++ b/utils/pub/pub.gyp
@@ -26,6 +26,7 @@
           ],
           'action': [
             '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)dart<(EXECUTABLE_SUFFIX)',
+            '--packages=../../.packages',
             '--snapshot=<(SHARED_INTERMEDIATE_DIR)/pub.dart.snapshot',
             '../../third_party/pkg/pub/bin/pub.dart',
           ]