Version 1.20.0-dev.10.0

Merge commit '9bd4406d4ba9db9cda26089136d5cc16415125b0' into dev
diff --git a/.travis.yml b/.travis.yml
index 1a877df..b8f5a00 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -35,10 +35,12 @@
   - export PATH=`pwd`/depot_tools:"$PATH"
 
   # Checkout everything if we're building the SDK
-  - 'gclient config --spec=''solutions = [ { "name": ".", "url": "git@github.com:dart-lang/sdk.git", "deps_file": "DEPS", "managed": False, "custom_vars": { "dart_root": "." } } ]'''
-  - if [ "$CXX" ]; then gclient sync ; fi
+  - cd ..
+  - 'gclient config --spec=''solutions = [ { "name": "sdk", "url": "git@github.com:dart-lang/sdk.git", "deps_file": "DEPS", "managed": False } ]'''
+  - gclient sync
+  - cd sdk
 
-  # If a C++ compiler is set, built the SDK - else keep the preinstalled.
+  # If a C++ compiler is set, build the SDK - else use the preinstalled SDK instead.
   - if [ "$CXX" ]; then ./tools/build.py -m release create_sdk ; fi
   - if [ "$CXX" ]; then export PATH=`pwd`/out/ReleaseX64/dart-sdk/bin:"$PATH" ; fi
   - dart --version
@@ -49,6 +51,8 @@
   - export CHROME_CANARY_BIN=`./tool/get_chrome_canary.sh`
   - export DISPLAY=:99.0
   - sh -e /etc/init.d/xvfb start
+install:
+  # Empty to suppress default pub get behavior
 before_script:
   # Node modules used by DDC
   - nvm install 5.5.0
@@ -69,7 +73,6 @@
   allow_failures:
     - env: TEST=node
     - env: ANALYZER=master DDC_BROWSERS=Firefox
-    - env: ANALYZER=master CXX=clang++
     - env: ANALYZER=master CXX=g++
 notifications:
   email:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4285fc9..7a38288 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,7 +7,7 @@
   [article on native extensions](https://www.dartlang.org/articles/dart-vm/native-extensions)
   to reflect the VM's improved behavior.
 
-* Linux builds of the VM will now use the tcmalloc library for memory
+* Linux builds of the VM will now use the `tcmalloc` library for memory
   allocation. This has the advantages of better debugging and profiling support
   and faster small allocations, with the cost of slightly larger initial memory
   footprint, and slightly slower large allocations.
@@ -15,13 +15,16 @@
 * We have improved the way the VM searches for trusted root certificates for
   secure socket connections on Linux. First, the VM will look for trusted root
   certificates in standard locations on the file system
-  (/etc/pki/tls/certs/ca-bundle.crt followed by /etc/ssl/certs), and only if
+  (`/etc/pki/tls/certs/ca-bundle.crt` followed by `/etc/ssl/certs`), and only if
   these do not exist will it fall back on the builtin trusted root certificates.
   This behavior can be overridden on Linux with the new flags
-  --root-certs-file and --root-certs-cache. The former is the path to a file
+  `--root-certs-file` and `--root-certs-cache`. The former is the path to a file
   containing the trusted root certificates, and the latter is the path to a
   directory containing root certificate files hashed using `c_rehash`.
 
+* The VM now throws a catchable `Error` when method compilation fails. This
+  allows easier debugging of syntax errors, especially when testing.
+
 ### Core library changes
 
 * `dart:core`: Remove deprecated `Resource` class.
@@ -29,7 +32,7 @@
 * `dart:async`
   * `Future.wait` now catches synchronous errors and returns them in the
     returned Future.
-  * More aggressively returns a Future on Stream.cancel operations.
+  * More aggressively returns a `Future` on `Stream.cancel` operations.
     Discourages to return `null` from `cancel`.
   * Fixes a few bugs where the cancel future wasn't passed through
     transformations.
@@ -115,6 +118,12 @@
     * Always split enum declarations if they end in a trailing comma.
     * Add `--set-exit-if-changed` to set the exit code on a change.
 
+* Pub
+  * Pub no longer generates a `packages/` directory by default.  Instead, it
+    generates a `.packages` file, called a package spec. To generate
+    a `packages/` directory in addition to the package spec, use the
+    `--packages-dir` flag with `pub get`, `pub upgrade`, and `pub downgrade`.
+
 ## 1.19.0
 
 ### Language changes
diff --git a/DEPS b/DEPS
index 0c56803..da4429b 100644
--- a/DEPS
+++ b/DEPS
@@ -31,7 +31,7 @@
   "co19_rev": "@d4767b4caea3c5828ad8e053cd051d44a59061af",
 
   # Revisions of GN related dependencies.
-  "buildtools_revision": "@565d04e8741429fb1b4f26d102f2c6c3b849edeb",
+  "buildtools_revision": "@3d2e47bf14e4e67816a53e304dea422fa18f9180",
 
   "gperftools_revision": "@7822b5b0b9fa7e016e1f6b46ea86f26f4691a457",
 
@@ -44,7 +44,7 @@
   "barback_tag" : "@0.15.2+9",
   "bazel_worker_tag": "@0.1.1",
   "boolean_selector_tag" : "@1.0.2",
-  "boringssl_gen_rev": "@1e8e5da213d0d5b1d50fcc1356c4783091bcc20d",
+  "boringssl_gen_rev": "@922830c0aad900dd3d143eef1ba06faa83fe263b",
   "boringssl_rev" : "@8d343b44bbab829d1a28fdef650ca95f7db4412e",
   "charcode_tag": "@1.1.0",
   "chrome_rev" : "@19997",
@@ -91,7 +91,7 @@
   "pool_tag": "@1.2.4",
   "protobuf_tag": "@0.5.3",
   "pub_cache_tag": "@v0.1.0",
-  "pub_rev": "@4ef3e3e8ad8089733d617505cc66fa3d8049b4ae",
+  "pub_rev": "@3dd04bd17ba269ccdd34502a253041dd96ded3be",
   "pub_semver_tag": "@1.3.0",
   "quiver_tag": "@0.22.0",
   "resource_rev":"@a49101ba2deb29c728acba6fb86000a8f730f4b1",
diff --git a/build/config/android/config.gni b/build/config/android/config.gni
index a16407b..35ffcccf 100644
--- a/build/config/android/config.gni
+++ b/build/config/android/config.gni
@@ -114,7 +114,7 @@
   arm_android_toolchain_root = "$android_ndk_root/toolchains/arm-linux-androideabi-${_android_toolchain_version}/prebuilt/${android_host_os}-${android_host_arch}"
   mips_android_toolchain_root = "$android_ndk_root/toolchains/mipsel-linux-android-${_android_toolchain_version}/prebuilt/${android_host_os}-${android_host_arch}"
   x86_64_android_toolchain_root = "$android_ndk_root/toolchains/x86_64-${_android_toolchain_version}/prebuilt/${android_host_os}-${android_host_arch}"
-  arm64_android_toolchain_root = "$android_ndk_root/toolchains/aarch64-${_android_toolchain_version}/prebuilt/${android_host_os}-${android_host_arch}"
+  arm64_android_toolchain_root = "$android_ndk_root/toolchains/aarch64-linux-android-${_android_toolchain_version}/prebuilt/${android_host_os}-${android_host_arch}"
   mips64_android_toolchain_root = "$android_ndk_root/toolchains/mips64el-${_android_toolchain_version}/prebuilt/${android_host_os}-${android_host_arch}"
 
   # Location of libgcc. This is only needed for the current GN toolchain, so we
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 5bc242f..7f7e423 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -53,6 +53,7 @@
 # where stuff should go. Put warning related stuff in the "warnings" config.
 
 config("compiler") {
+  asmflags = []
   cflags = []
   cflags_c = []
   cflags_cc = []
@@ -447,6 +448,14 @@
       }
     }
   }
+
+  # Assign any flags set for the C compiler to asmflags so that they are sent
+  # to the assembler. The Windows assembler takes different types of flags
+  # so only do so for posix platforms.
+  if (is_posix) {
+    asmflags += cflags
+    asmflags += cflags_c
+  }
 }
 
 config("compiler_arm_fpu") {
diff --git a/build/toolchain/android/BUILD.gn b/build/toolchain/android/BUILD.gn
index e543fc6..5e48473 100644
--- a/build/toolchain/android/BUILD.gn
+++ b/build/toolchain/android/BUILD.gn
@@ -142,7 +142,7 @@
   android_ndk_sysroot = "$android_ndk_root/$arm64_android_sysroot_subdir"
   android_ndk_lib_dir = "usr/lib"
 
-  tool_prefix = "$arm64_android_toolchain_root/bin/arm-linux-androideabi-"
+  tool_prefix = "$arm64_android_toolchain_root/bin/aarch64-linux-android-"
   toolchain_cpu = "aarch64"
 }
 
diff --git a/build/toolchain/gcc_toolchain.gni b/build/toolchain/gcc_toolchain.gni
index bb1d791..ecdad86 100644
--- a/build/toolchain/gcc_toolchain.gni
+++ b/build/toolchain/gcc_toolchain.gni
@@ -116,7 +116,7 @@
     tool("asm") {
       # For GCC we can just use the C compiler to compile assembly.
       depfile = "{{output}}.d"
-      command = "$cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}"
+      command = "$cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{asmflags}} -c {{source}} -o {{output}}"
       depsformat = "gcc"
       description = "ASM {{output}}"
       outputs = [
@@ -232,7 +232,7 @@
 
     # When invoking this toolchain not as the default one, these args will be
     # passed to the build. They are ignored when this is the default toolchain.
-    toolchain_args() {
+    toolchain_args = {
       current_cpu = invoker.toolchain_cpu
       current_os = invoker.toolchain_os
 
diff --git a/build/toolchain/mac/BUILD.gn b/build/toolchain/mac/BUILD.gn
index 8efdd5c..d77a921 100644
--- a/build/toolchain/mac/BUILD.gn
+++ b/build/toolchain/mac/BUILD.gn
@@ -85,7 +85,7 @@
     tool("asm") {
       # For GCC we can just use the C compiler to compile assembly.
       depfile = "{{output}}.d"
-      command = "$cc -MMD -MF $depfile {{defines}} {{include_dirs}} $sysroot_flags $toolchain_flags {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}"
+      command = "$cc -MMD -MF $depfile {{defines}} {{include_dirs}} $sysroot_flags $toolchain_flags {{asmflags}} -c {{source}} -o {{output}}"
       depsformat = "gcc"
       description = "ASM {{output}}"
       outputs = [
@@ -193,7 +193,7 @@
       description = "COPY {{source}} {{output}}"
     }
 
-    toolchain_args() {
+    toolchain_args = {
       current_cpu = invoker.toolchain_cpu
       current_os = invoker.toolchain_os
 
diff --git a/build/toolchain/win/BUILD.gn b/build/toolchain/win/BUILD.gn
index 454cdde..d71098f 100644
--- a/build/toolchain/win/BUILD.gn
+++ b/build/toolchain/win/BUILD.gn
@@ -121,7 +121,7 @@
     tool("asm") {
       # TODO(brettw): "/safeseh" assembler argument is hardcoded here. Extract
       # assembler flags to a variable like cflags. crbug.com/418613
-      command = "$python_path gyp-win-tool asm-wrapper $env ml.exe {{defines}} {{include_dirs}} /safeseh /c /Fo {{output}} {{source}}"
+      command = "$python_path gyp-win-tool asm-wrapper $env ml.exe {{defines}} {{include_dirs}} {{asmflags}} /safeseh /c /Fo {{output}} {{source}}"
       description = "ASM {{output}}"
       outputs = [
         "{{target_out_dir}}/{{target_output_name}}/{{source_name_part}}.obj",
diff --git a/docs/language/dartLangSpec.tex b/docs/language/dartLangSpec.tex
index cfd1536..e826260a 100644
--- a/docs/language/dartLangSpec.tex
+++ b/docs/language/dartLangSpec.tex
@@ -2083,10 +2083,9 @@
 }
 
 \LMHash{}
-The effect of a class definition of the form \code{\CLASS{} $C$ = $M$; } or the form
- \code{\CLASS{} $C<T_1, \ldots, T_n>$ = $M$; } in library $L$  is to introduce the name $C$ into the scope of $L$, bound to the class (\ref{classes}) defined by the mixin application $M$. The name of the class is also set to $C$. Iff the  class is prefixed by the built-in identifier \ABSTRACT{}, the class being defined is an abstract class.
+The effect of a class definition of the form \code{\CLASS{} $C$ = $M$; } or the form \code{\CLASS{} $C<T_1, \ldots, T_n>$ = $M$; } in library $L$  is to introduce the name $C$ into the scope of $L$, bound to the class (\ref{classes}) defined by the mixin application $M$. The name of the class is also set to $C$. Iff the  class is prefixed by the built-in identifier \ABSTRACT{}, the class being defined is an abstract class.
 
- Let $M_A$ be a mixin derived from a class $M$ with direct superclass $S_{static}$.
+Let $M_A$ be a mixin derived from a class $M$ with direct superclass $S_{static}$, e.g., as defined by the class declaration \code{class M extends S$_{static}$ \{ \ldots \}}.
 
 Let $A$ be an application of $M_A$. It is a static warning if the superclass of $A$ is not a subtype of $S_{static}$.
 
@@ -2469,8 +2468,8 @@
 }
 
 \begin{dartCode}
-\CONST{} x = 1/0;
-\FINAL{} y = 1/0;
+\CONST{} x = 1 ~/ 0;
+\FINAL{} y = 1 ~/ 0;
 
 \CLASS{} K \{
   m1() \{
@@ -2590,7 +2589,7 @@
  \end{grammar}
 
 \LMHash{}
-If a numeric literal begins with the prefix `0x' or `0X', it denotes the hexadecimal integer represented by the part of the literal following `0x' (respectively `0X'). Otherwise, if the numeric literal does not include a decimal point  it denotes a decimal integer.  Otherwise, the numeric literal  denotes a 64 bit double precision floating point number as specified by the IEEE 754 standard.
+If a numeric literal begins with the prefix `0x' or `0X', it denotes the hexadecimal integer represented by the part of the literal following `0x' (respectively `0X'). Otherwise, if the numeric literal contains only decimal digits, it denotes a decimal integer.  Otherwise, the numeric literal contains either a decimal point or an exponent part and it denotes a 64 bit double precision floating point number as specified by the IEEE 754 standard.
 
 \LMHash{}
 In principle, the range of integers supported by a Dart implementations is unlimited. In practice, it is limited by available memory. Implementations may also be limited by other considerations.
@@ -2872,7 +2871,7 @@
 A symbol literal \code{\#id} where \code{id} does not begin with an underscore ('\code{\_}')  is equivalent to the expression \code{\CONST{} Symbol('id')}.
 
 \LMHash{}
-A symbol literal \code{\#\_id} evaluates to the object that would be returned by the call \code{mirror.getPrivateSymbol('id')} where mirror is an instance of the class \code{LibraryMirror} defined in the library \code{dart:mirrors}, reflecting the current library.
+A symbol literal \code{\#\_id} evaluates to the object that would be returned by the call \code{MirrorSystem.getSymbol("\_id", libraryMirror)} where \code{libraryMirror} is an instance of the class \code{LibraryMirror} defined in the library \code{dart:mirrors}, reflecting the current library.
 
 \rationale{
 One may well ask what is the motivation for introducing literal symbols? In some languages, symbols are canonicalized whereas strings are not. However literal strings are already canonicalized in Dart.  Symbols are slightly easier to type compared to strings and their use can become strangely addictive, but this is not nearly sufficient justification for adding a literal form to the language. The primary motivation is related to the use of reflection and a web specific practice known as minification.
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index 7f926b4..a0b6d10 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -165,8 +165,12 @@
       'CREATE_NO_SUCH_METHOD', 51, "Create 'noSuchMethod' method");
   static const IMPORT_LIBRARY_PREFIX = const FixKind('IMPORT_LIBRARY_PREFIX',
       51, "Use imported library '{0}' with prefix '{1}'");
-  static const IMPORT_LIBRARY_PROJECT =
-      const FixKind('IMPORT_LIBRARY_PROJECT', 49, "Import library '{0}'");
+  static const IMPORT_LIBRARY_PROJECT1 =
+      const FixKind('IMPORT_LIBRARY_PROJECT1', 47, "Import library '{0}'");
+  static const IMPORT_LIBRARY_PROJECT2 =
+      const FixKind('IMPORT_LIBRARY_PROJECT2', 48, "Import library '{0}'");
+  static const IMPORT_LIBRARY_PROJECT3 =
+      const FixKind('IMPORT_LIBRARY_PROJECT3', 49, "Import library '{0}'");
   static const IMPORT_LIBRARY_SDK =
       const FixKind('IMPORT_LIBRARY_SDK', 49, "Import library '{0}'");
   static const IMPORT_LIBRARY_SHOW =
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 a894518..78939c5 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -1554,8 +1554,22 @@
         if (element.kind != kind) {
           continue;
         }
-        _addFix_importLibrary(
-            DartFixKind.IMPORT_LIBRARY_PROJECT, libraryElement);
+        // Compute the fix kind.
+        FixKind fixKind;
+        if (resourceProvider.pathContext
+            .split(librarySource.fullName)
+            .contains('src')) {
+          // Bad: non-API.
+          fixKind = DartFixKind.IMPORT_LIBRARY_PROJECT3;
+        } else if (element.library != libraryElement) {
+          // Ugly: exports.
+          fixKind = DartFixKind.IMPORT_LIBRARY_PROJECT2;
+        } else {
+          // Good: direct declaration.
+          fixKind = DartFixKind.IMPORT_LIBRARY_PROJECT1;
+        }
+        // Add the fix.
+        _addFix_importLibrary(fixKind, libraryElement);
       }
     }
   }
diff --git a/pkg/analysis_server/test/services/correction/fix_test.dart b/pkg/analysis_server/test/services/correction/fix_test.dart
index 9bc4a4f..c7ed0bb 100644
--- a/pkg/analysis_server/test/services/correction/fix_test.dart
+++ b/pkg/analysis_server/test/services/correction/fix_test.dart
@@ -152,8 +152,10 @@
    * Configures the [SourceFactory] to have the `my_pkg` package in
    * `/packages/my_pkg/lib` folder.
    */
-  void _configureMyPkg(String myLibCode) {
-    provider.newFile('/packages/my_pkg/lib/my_lib.dart', myLibCode);
+  void _configureMyPkg(Map<String, String> pathToCode) {
+    pathToCode.forEach((path, code) {
+      provider.newFile('/packages/my_pkg/lib/$path', code);
+    });
     // configure SourceFactory
     Folder myPkgFolder = provider.getResource('/packages/my_pkg/lib');
     UriResolver pkgResolver = new PackageMapUriResolver(provider, {
@@ -162,7 +164,11 @@
     context.sourceFactory = new SourceFactory(
         [AbstractContextTest.SDK_RESOLVER, pkgResolver, resourceResolver]);
     // force 'my_pkg' resolution
-    addSource('/tmp/other.dart', "import 'package:my_pkg/my_lib.dart';");
+    addSource(
+        '/tmp/other.dart',
+        pathToCode.keys
+            .map((path) => "import 'package:my_pkg/$path';")
+            .join('\n'));
   }
 
   AnalysisError _findErrorToFix() {
@@ -3082,12 +3088,8 @@
 ''');
   }
 
-  test_importLibraryPackage_withClass() async {
-    _configureMyPkg('''
-library my_lib;
-class Test {}
-''');
-    // try to find a fix
+  test_importLibraryPackage_preferDirectOverExport() async {
+    _configureMyPkg({'b.dart': 'class Test {}', 'a.dart': "export 'b.dart';"});
     resolveTestUnit('''
 main() {
   Test test = null;
@@ -3095,9 +3097,47 @@
 ''');
     performAllAnalysisTasks();
     await assertHasFix(
-        DartFixKind.IMPORT_LIBRARY_PROJECT,
+        DartFixKind.IMPORT_LIBRARY_PROJECT1,
         '''
-import 'package:my_pkg/my_lib.dart';
+import 'package:my_pkg/b.dart';
+
+main() {
+  Test test = null;
+}
+''');
+    await assertHasFix(
+        DartFixKind.IMPORT_LIBRARY_PROJECT2,
+        '''
+import 'package:my_pkg/a.dart';
+
+main() {
+  Test test = null;
+}
+''');
+  }
+
+  test_importLibraryPackage_preferPublicOverPrivate() async {
+    _configureMyPkg(
+        {'src/a.dart': 'class Test {}', 'b.dart': "export 'src/a.dart';"});
+    resolveTestUnit('''
+main() {
+  Test test = null;
+}
+''');
+    performAllAnalysisTasks();
+    await assertHasFix(
+        DartFixKind.IMPORT_LIBRARY_PROJECT2,
+        '''
+import 'package:my_pkg/b.dart';
+
+main() {
+  Test test = null;
+}
+''');
+    await assertHasFix(
+        DartFixKind.IMPORT_LIBRARY_PROJECT3,
+        '''
+import 'package:my_pkg/src/a.dart';
 
 main() {
   Test test = null;
@@ -3121,7 +3161,7 @@
 ''');
     performAllAnalysisTasks();
     await assertHasFix(
-        DartFixKind.IMPORT_LIBRARY_PROJECT,
+        DartFixKind.IMPORT_LIBRARY_PROJECT1,
         '''
 import 'lib.dart';
 
@@ -3155,7 +3195,7 @@
 ''');
     performAllAnalysisTasks();
     await assertHasFix(
-        DartFixKind.IMPORT_LIBRARY_PROJECT,
+        DartFixKind.IMPORT_LIBRARY_PROJECT1,
         '''
 import 'a.dart';
 import 'b.dart' show Two;
@@ -3181,7 +3221,7 @@
 ''');
     performAllAnalysisTasks();
     await assertHasFix(
-        DartFixKind.IMPORT_LIBRARY_PROJECT,
+        DartFixKind.IMPORT_LIBRARY_PROJECT1,
         '''
 import '../lib.dart';
 
@@ -3206,7 +3246,7 @@
 ''');
     performAllAnalysisTasks();
     await assertHasFix(
-        DartFixKind.IMPORT_LIBRARY_PROJECT,
+        DartFixKind.IMPORT_LIBRARY_PROJECT1,
         '''
 import '../lib/sub/folder/lib.dart';
 
@@ -3231,7 +3271,7 @@
 ''');
     performAllAnalysisTasks();
     await assertHasFix(
-        DartFixKind.IMPORT_LIBRARY_PROJECT,
+        DartFixKind.IMPORT_LIBRARY_PROJECT1,
         '''
 import 'lib.dart';
 
@@ -3255,7 +3295,7 @@
 ''');
     performAllAnalysisTasks();
     await assertHasFix(
-        DartFixKind.IMPORT_LIBRARY_PROJECT,
+        DartFixKind.IMPORT_LIBRARY_PROJECT1,
         '''
 import 'lib.dart';
 
@@ -3281,7 +3321,7 @@
 ''');
     performAllAnalysisTasks();
     await assertHasFix(
-        DartFixKind.IMPORT_LIBRARY_PROJECT,
+        DartFixKind.IMPORT_LIBRARY_PROJECT1,
         '''
 import 'lib.dart';
 
@@ -3308,7 +3348,7 @@
 ''');
     performAllAnalysisTasks();
     await assertHasFix(
-        DartFixKind.IMPORT_LIBRARY_PROJECT,
+        DartFixKind.IMPORT_LIBRARY_PROJECT1,
         '''
 import 'lib.dart';
 
@@ -3332,7 +3372,7 @@
 ''');
     performAllAnalysisTasks();
     await assertHasFix(
-        DartFixKind.IMPORT_LIBRARY_PROJECT,
+        DartFixKind.IMPORT_LIBRARY_PROJECT1,
         '''
 import 'lib.dart';
 
@@ -3538,7 +3578,7 @@
 }
 ''');
     performAllAnalysisTasks();
-    await assertNoFix(DartFixKind.IMPORT_LIBRARY_PROJECT);
+    await assertNoFix(DartFixKind.IMPORT_LIBRARY_PROJECT1);
     await assertHasFix(
         DartFixKind.IMPORT_LIBRARY_SHOW,
         '''
@@ -3924,7 +3964,7 @@
   }
 
   test_replaceImportUri_package() async {
-    _configureMyPkg('');
+    _configureMyPkg({'my_lib.dart': ''});
     resolveTestUnit('''
 import 'no/matter/my_lib.dart';
 ''');
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 53a6565..712e6ae 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -439,6 +439,7 @@
     CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER,
     CompileTimeErrorCode.YIELD_EACH_IN_NON_GENERATOR,
     CompileTimeErrorCode.YIELD_IN_NON_GENERATOR,
+    HintCode.ABSTRACT_SUPER_MEMBER_REFERENCE,
     HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE,
     HintCode.CAN_BE_NULL_AFTER_NULL_AWARE,
     HintCode.DEAD_CODE,
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index b61eb2b..d3fdd99 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -1847,12 +1847,13 @@
   // for `staticType` and `propagatedType` on Expression.
   DartType _propagatedInvokeTypeIfBetter(
       DartType propagatedType, DartType staticType) {
-    if (propagatedType != null &&
-        (staticType == null || propagatedType.isMoreSpecificThan(staticType))) {
-      return propagatedType;
-    } else {
+    if (_resolver.strongMode || propagatedType == null) {
       return null;
     }
+    if (staticType == null || propagatedType.isMoreSpecificThan(staticType)) {
+      return propagatedType;
+    }
+    return null;
   }
 
   /**
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 26b997d..3e1dc6b 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -6020,7 +6020,7 @@
   void recordPropagatedTypeIfBetter(Expression expression, DartType type,
       [bool hasOldPropagatedType = false]) {
     // Ensure that propagated type invalid.
-    if (type == null || type.isDynamic || type.isBottom) {
+    if (strongMode || type == null || type.isDynamic || type.isBottom) {
       if (!hasOldPropagatedType) {
         expression.propagatedType = null;
       }
@@ -7422,7 +7422,9 @@
       return;
     }
     // set propagated type for the closure
-    closure.propagatedType = expectedClosureType;
+    if (!strongMode) {
+      closure.propagatedType = expectedClosureType;
+    }
     // set inferred types for parameters
     NodeList<FormalParameter> parameters = closure.parameters.parameters;
     List<ParameterElement> expectedParameters = expectedClosureType.parameters;
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index 4ebd9b3..47e5599 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -2283,7 +2283,7 @@
    * @param type the propagated type of the node
    */
   void _recordPropagatedType(Expression expression, DartType type) {
-    if (type != null && !type.isDynamic && !type.isBottom) {
+    if (!_strongMode && type != null && !type.isDynamic && !type.isBottom) {
       expression.propagatedType = type;
     }
   }
@@ -2299,6 +2299,9 @@
    */
   void _recordPropagatedTypeOfFunction(
       ExecutableElement functionElement, FunctionBody body) {
+    if (_strongMode) {
+      return;
+    }
     DartType propagatedReturnType =
         _computePropagatedReturnTypeOfFunction(body);
     if (propagatedReturnType == null) {
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index 0488553..5574aed 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -848,15 +848,15 @@
 
   bool _isInterfaceSubtypeOf(
       InterfaceType i1, InterfaceType i2, Set<Element> visited) {
+    if (identical(i1, i2)) {
+      return true;
+    }
+    
     // Guard recursive calls
     _GuardedSubtypeChecker<InterfaceType> guardedInterfaceSubtype = _guard(
         (DartType i1, DartType i2, Set<Element> visited) =>
             _isInterfaceSubtypeOf(i1, i2, visited));
 
-    if (i1 == i2) {
-      return true;
-    }
-
     if (i1.element == i2.element) {
       List<DartType> tArgs1 = i1.typeArguments;
       List<DartType> tArgs2 = i2.typeArguments;
@@ -902,13 +902,14 @@
 
   bool _isSubtypeOf(DartType t1, DartType t2, Set<Element> visited,
       {bool dynamicIsBottom: false}) {
+    if (identical(t1, t2)) {
+      return true;
+    }
+
     // Guard recursive calls
     _GuardedSubtypeChecker<DartType> guardedSubtype = _guard(_isSubtypeOf);
     _GuardedSubtypeChecker<DartType> guardedInferTypeParameter =
         _guard(_inferTypeParameterSubtypeOf);
-    if (t1 == t2) {
-      return true;
-    }
 
     // The types are void, dynamic, bottom, interface types, function types,
     // and type parameters. We proceed by eliminating these different classes
@@ -928,10 +929,12 @@
 
     // S <: T where S is a type variable
     //  T is not dynamic or object (handled above)
-    //  S != T (handled above)
-    //  So only true if bound of S is S' and
-    //  S' <: T
+    //  True if T == S
+    //  Or true if bound of S is S' and S' <: T
     if (t1 is TypeParameterType) {
+      if (t1 == t2) {
+        return true;
+      }
       if (guardedInferTypeParameter(t1, t2, visited)) {
         return true;
       }
@@ -950,7 +953,7 @@
     // TODO(rnystrom): Determine how this can ever be reached. If it can't,
     // remove it.
     if (t1.isVoid || t2.isVoid) {
-      return false;
+      return t1.isVoid && t2.isVoid;
     }
 
     // We've eliminated void, dynamic, bottom, and type parameters.  The only
diff --git a/pkg/analyzer/lib/src/generated/utilities_dart.dart b/pkg/analyzer/lib/src/generated/utilities_dart.dart
index 8dd40df..b3f688a 100644
--- a/pkg/analyzer/lib/src/generated/utilities_dart.dart
+++ b/pkg/analyzer/lib/src/generated/utilities_dart.dart
@@ -27,12 +27,23 @@
   Uri origBaseUri = baseUri;
   try {
     String scheme = baseUri.scheme;
+    // dart:core => dart:core/core.dart
     if (scheme == DartUriResolver.DART_SCHEME) {
       String part = baseUri.path;
       if (part.indexOf('/') < 0) {
         baseUri = FastUri.parse('$scheme:$part/$part.dart');
       }
     }
+    // foo.dart + ../bar.dart = ../bar.dart
+    // TODO(scheglov) Remove this temporary workaround.
+    // Should be fixed as https://github.com/dart-lang/sdk/issues/27447
+    List<String> baseSegments = baseUri.pathSegments;
+    List<String> containedSegments = containedUri.pathSegments;
+    if (baseSegments.length == 1 &&
+        containedSegments.length > 0 &&
+        containedSegments[0] == '..') {
+      return containedUri;
+    }
     return baseUri.resolveUri(containedUri);
   } catch (exception, stackTrace) {
     throw new AnalysisException(
diff --git a/pkg/analyzer/lib/src/summary/bazel_summary.dart b/pkg/analyzer/lib/src/summary/bazel_summary.dart
new file mode 100644
index 0000000..f307395
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary/bazel_summary.dart
@@ -0,0 +1,191 @@
+// 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 'dart:convert';
+
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/utilities_collection.dart';
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:convert/convert.dart';
+import 'package:crypto/crypto.dart';
+import 'package:meta/meta.dart';
+
+/**
+ * Return the path of the directory where bundles for the given [uri] should be
+ * looked for.  This directory should contain corresponding pairs of `*.api.ds`
+ * and `*.full.ds` files, possibly more than one pair.  Return `null` if the
+ * given [uri] does not have the expected structure, so the output path cannot
+ * be computed.
+ */
+typedef String GetOutputPath(ResourceProvider provider, Uri uri);
+
+/**
+ * Information about a Dart package in Bazel.
+ */
+class Package {
+  final String bundlePath;
+  final PackageBundle bundle;
+  final Set<String> _unitUris = new Set<String>();
+
+  Package(this.bundlePath, this.bundle) {
+    _unitUris.addAll(bundle.unlinkedUnitUris);
+  }
+}
+
+/**
+ * Class that reads summaries of Bazel packages.
+ *
+ * When the client needs to produce a resolution result for a new [Source], it
+ * should call [getPackages] to checked whether there is the set of packages
+ * to resynthesize resolution results.
+ */
+class SummaryProvider {
+  final ResourceProvider provider;
+  final GetOutputPath getOutputPath;
+  final AnalysisContext context;
+
+  /**
+   * Mapping from bundle paths to corresponding [Package]s.  The packages in
+   * the map were consistent with their constituent sources at the moment when
+   * they were put into the map.
+   */
+  final Map<String, Package> bundlePathToPackageMap = <String, Package>{};
+
+  /**
+   * When we detected than some bundle is not consistent with its constituent
+   * sources (i.e. even its unlinked state is not consistent), we remember
+   * this fact to avoid loading and checking consistency next time.
+   */
+  final Set<String> knownInconsistentBundlePaths = new Set<String>();
+
+  SummaryProvider(this.provider, this.getOutputPath, this.context);
+
+  /**
+   * Return the [Package] that contains information about the source with
+   * the given [uri], or `null` if such package does not exist.
+   */
+  @visibleForTesting
+  Package getPackageForUri(Uri uri) {
+    String outputPath = getOutputPath(provider, uri);
+    if (outputPath != null) {
+      List<Package> packages = _getPackages(outputPath);
+      for (Package package in packages) {
+        String uriStr = uri.toString();
+        if (package._unitUris.contains(uriStr)) {
+          return package;
+        }
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Return the complete list of [Package]s that are required to provide all
+   * resolution results for the given [source].
+   *
+   * The same list of packages is returned for the same [Source], i.e. always
+   * the full list, not a difference with a previous request.  It is up to the
+   * client to decide whether some of the returned packages should be excluded
+   * as already mixed into a resynthesizer.
+   *
+   * If the full set of packages cannot be produced, for example because some
+   * bundles are not built, or out of date, etc, then `null` is returned.
+   */
+  List<PackageBundle> getPackages(Source source) {
+    // TODO(scheglov) implement
+    return null;
+  }
+
+  /**
+   * Return the hexadecimal string for the given [source] contents.
+   */
+  String _computeSourceHashHex(Source source) {
+    String text = context.getContents(source).data;
+    List<int> bytes = UTF8.encode(text);
+    List<int> hashBytes = md5.convert(bytes).bytes;
+    return hex.encode(hashBytes);
+  }
+
+  /**
+   * Return the [Package] from the file with the given [path], or `null` if the
+   * file does not exist, or it cannot be read, or is not consistent with the
+   * sources it contains, etc.
+   */
+  Package _getPackage(String path) {
+    // Check if the bundle know to be inconsistent, missing, etc.
+    if (knownInconsistentBundlePaths.contains(path)) {
+      return null;
+    }
+    // Attempt to get from the cache or read from the file system.
+    try {
+      Package package = bundlePathToPackageMap[path];
+      if (package == null) {
+        File file = provider.getFile(path);
+        List<int> bytes = file.readAsBytesSync();
+        PackageBundle bundle = new PackageBundle.fromBuffer(bytes);
+        // Check for consistency, and fail if it's not.
+        if (!_isUnlinkedBundleConsistent(bundle)) {
+          knownInconsistentBundlePaths.add(path);
+          return null;
+        }
+        // OK, put the package into the cache.
+        package = new Package(path, bundle);
+        bundlePathToPackageMap[path] = package;
+      }
+      return package;
+    } catch (_) {
+      return null;
+    }
+  }
+
+  /**
+   * Return all consistent [Package]s in the given [folderPath].
+   */
+  List<Package> _getPackages(String folderPath) {
+    List<Package> packages = <Package>[];
+    try {
+      Folder folder = provider.getFolder(folderPath);
+      List<Resource> children = folder.getChildren();
+      for (Resource child in children) {
+        if (child is File) {
+          String packagePath = child.path;
+          if (packagePath.toLowerCase().endsWith('.full.ds')) {
+            Package package = _getPackage(packagePath);
+            if (package != null) {
+              packages.add(package);
+            }
+          }
+        }
+      }
+    } on FileSystemException {}
+    return packages;
+  }
+
+  /**
+   * Return `true` if the unlinked information of the [bundle] is consistent
+   * with its constituent sources.
+   */
+  bool _isUnlinkedBundleConsistent(PackageBundle bundle) {
+    try {
+      // Compute hashes of the constituent sources.
+      List<String> actualHashes = <String>[];
+      for (String uri in bundle.unlinkedUnitUris) {
+        Source source = context.sourceFactory.resolveUri(null, uri);
+        if (source == null) {
+          return false;
+        }
+        String hash = _computeSourceHashHex(source);
+        actualHashes.add(hash);
+      }
+      // Compare sorted actual and bundle unit hashes.
+      List<String> bundleHashes = bundle.unlinkedUnitHashes.toList()..sort();
+      actualHashes.sort();
+      return listsEqual(actualHashes, bundleHashes);
+    } catch (_) {
+      return false;
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/summary/link.dart b/pkg/analyzer/lib/src/summary/link.dart
index c805aeb..41b01150 100644
--- a/pkg/analyzer/lib/src/summary/link.dart
+++ b/pkg/analyzer/lib/src/summary/link.dart
@@ -3141,7 +3141,7 @@
   TypeParameterizedElementMixin get enclosingTypeParameterContext => null;
 
   @override
-  CompilationUnitElementInBuildUnit get enclosingUnit => enclosingElement;
+  CompilationUnitElementImpl get enclosingUnit => enclosingElement;
 
   @override
   String get identifier => _unlinkedTypedef.name;
diff --git a/pkg/analyzer/lib/src/summary/pub_summary.dart b/pkg/analyzer/lib/src/summary/pub_summary.dart
index 93e6aec..0113564 100644
--- a/pkg/analyzer/lib/src/summary/pub_summary.dart
+++ b/pkg/analyzer/lib/src/summary/pub_summary.dart
@@ -206,22 +206,22 @@
     }
 
     // Create graph nodes for packages.
-    List<_LinkedNode> nodes = <_LinkedNode>[];
-    Map<String, _LinkedNode> packageToNode = <String, _LinkedNode>{};
+    List<_LinkNode> nodes = <_LinkNode>[];
+    Map<String, _LinkNode> packageToNode = <String, _LinkNode>{};
     unlinkedBundles.forEach((package, unlinked) {
-      _LinkedNode node = new _LinkedNode(sdkBundle, getDeclaredVariable,
+      _LinkNode node = new _LinkNode(sdkBundle, getDeclaredVariable,
           listedPackages, package, unlinked, packageToNode);
       nodes.add(node);
       packageToNode[package.name] = node;
     });
 
     // Compute transitive dependencies, mark some nodes as failed.
-    for (_LinkedNode node in nodes) {
+    for (_LinkNode node in nodes) {
       node.computeTransitiveDependencies();
     }
 
     // Attempt to read existing linked bundles.
-    for (_LinkedNode node in nodes) {
+    for (_LinkNode node in nodes) {
       _readLinked(node, strong);
     }
 
@@ -232,7 +232,7 @@
       // 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) {
+      for (_LinkNode node in nodes) {
         store.addBundle(null, node.unlinked);
         if (node.linked != null) {
           store.addBundle(null, node.linked);
@@ -240,22 +240,22 @@
       }
 
       // Link each package node.
-      for (_LinkedNode node in nodes) {
+      for (_LinkNode node in nodes) {
         if (!node.isEvaluated) {
-          new _LinkedWalker(getDeclaredVariable, listedPackages, store, strong)
+          new _LinkWalker(getDeclaredVariable, listedPackages, store, strong)
               .walk(node);
         }
       }
 
       // Write newly linked bundles.
-      for (_LinkedNode node in nodes) {
+      for (_LinkNode node in nodes) {
         _writeLinked(node, strong);
       }
     }
 
     // Create successfully linked packages.
     List<LinkedPubPackage> linkedPackages = <LinkedPubPackage>[];
-    for (_LinkedNode node in nodes) {
+    for (_LinkNode node in nodes) {
       if (node.linked != null) {
         linkedPackages.add(new LinkedPubPackage(
             node.package, node.unlinked, node.linked, node.linkedHash));
@@ -512,9 +512,9 @@
 
   /**
    * Attempt to find the linked bundle that corresponds to the given [node]
-   * with all its transitive dependencies and put it into [_LinkedNode.linked].
+   * with all its transitive dependencies and put it into [_LinkNode.linked].
    */
-  void _readLinked(_LinkedNode node, bool strong) {
+  void _readLinked(_LinkNode node, bool strong) {
     String hash = node.linkedHash;
     if (hash != null) {
       String fileName = _getLinkedName(hash, strong);
@@ -573,7 +573,7 @@
    * If a new linked bundle was linked for the given [node], write the bundle
    * into the memory cache and the file system.
    */
-  void _writeLinked(_LinkedNode node, bool strong) {
+  void _writeLinked(_LinkNode node, bool strong) {
     String hash = node.linkedHash;
     if (hash != null && node.linkedNewBytes != null) {
       String fileName = _getLinkedName(hash, strong);
@@ -620,22 +620,22 @@
 /**
  * Specialization of [Node] for linking packages in proper dependency order.
  */
-class _LinkedNode extends Node<_LinkedNode> {
+class _LinkNode extends Node<_LinkNode> {
   final PackageBundle sdkBundle;
   final _GetDeclaredVariable getDeclaredVariable;
   final _ListedPackages listedPackages;
   final PubPackage package;
   final PackageBundle unlinked;
-  final Map<String, _LinkedNode> packageToNode;
+  final Map<String, _LinkNode> packageToNode;
 
   bool failed = false;
-  Set<_LinkedNode> transitiveDependencies;
+  Set<_LinkNode> transitiveDependencies;
   String _linkedHash;
 
   List<int> linkedNewBytes;
   PackageBundle linked;
 
-  _LinkedNode(this.sdkBundle, this.getDeclaredVariable, this.listedPackages,
+  _LinkNode(this.sdkBundle, this.getDeclaredVariable, this.listedPackages,
       this.package, this.unlinked, this.packageToNode);
 
   @override
@@ -666,8 +666,8 @@
   }
 
   @override
-  List<_LinkedNode> computeDependencies() {
-    Set<_LinkedNode> dependencies = new Set<_LinkedNode>();
+  List<_LinkNode> computeDependencies() {
+    Set<_LinkNode> dependencies = new Set<_LinkNode>();
 
     void appendDependency(String uriStr) {
       Uri uri = FastUri.parse(uriStr);
@@ -678,7 +678,7 @@
         // The SDK linked bundle is precomputed before linking packages.
       } else if (uriStr.startsWith('package:')) {
         String package = PubSummaryManager.getPackageName(uriStr);
-        _LinkedNode packageNode = packageToNode[package];
+        _LinkNode packageNode = packageToNode[package];
         if (packageNode == null && listedPackages.isListed(uriStr)) {
           failed = true;
         }
@@ -712,9 +712,9 @@
    */
   void computeTransitiveDependencies() {
     if (transitiveDependencies == null) {
-      transitiveDependencies = new Set<_LinkedNode>();
+      transitiveDependencies = new Set<_LinkNode>();
 
-      void appendDependencies(_LinkedNode node) {
+      void appendDependencies(_LinkNode node) {
         if (transitiveDependencies.add(node)) {
           node.dependencies.forEach(appendDependencies);
         }
@@ -736,7 +736,7 @@
    */
   void _appendDeclaredVariables(ApiSignature signature) {
     Set<String> nameSet = new Set<String>();
-    for (_LinkedNode node in transitiveDependencies) {
+    for (_LinkNode node in transitiveDependencies) {
       for (UnlinkedUnit unit in node.unlinked.unlinkedUnits) {
         for (UnlinkedImport import in unit.imports) {
           for (UnlinkedConfiguration configuration in import.configurations) {
@@ -762,24 +762,24 @@
 /**
  * Specialization of [DependencyWalker] for linking packages.
  */
-class _LinkedWalker extends DependencyWalker<_LinkedNode> {
+class _LinkWalker extends DependencyWalker<_LinkNode> {
   final _GetDeclaredVariable getDeclaredVariable;
   final _ListedPackages listedPackages;
   final SummaryDataStore store;
   final bool strong;
 
-  _LinkedWalker(
+  _LinkWalker(
       this.getDeclaredVariable, this.listedPackages, this.store, this.strong);
 
   @override
-  void evaluate(_LinkedNode node) {
+  void evaluate(_LinkNode node) {
     evaluateScc([node]);
   }
 
   @override
-  void evaluateScc(List<_LinkedNode> scc) {
-    Map<String, _LinkedNode> uriToNode = <String, _LinkedNode>{};
-    for (_LinkedNode node in scc) {
+  void evaluateScc(List<_LinkNode> scc) {
+    Map<String, _LinkNode> uriToNode = <String, _LinkNode>{};
+    for (_LinkNode node in scc) {
       for (String uri in node.unlinked.unlinkedUnitUris) {
         uriToNode[uri] = node;
       }
@@ -793,7 +793,7 @@
       return store.unlinkedMap[uri];
     }, getDeclaredVariable, strong);
     // Assemble linked bundles and put them into the store.
-    for (_LinkedNode node in scc) {
+    for (_LinkNode node in scc) {
       PackageBundleAssembler assembler = new PackageBundleAssembler();
       linkedLibraries.forEach((uri, linkedLibrary) {
         if (identical(uriToNode[uri], node)) {
diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart
index a16ee2e..ec467c7 100644
--- a/pkg/analyzer/test/generated/strong_mode_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -2178,10 +2178,8 @@
     v; // marker
   }
 }''';
-    assertPropagatedIterationType(
-        code, typeProvider.dynamicType, typeProvider.intType);
-    assertTypeOfMarkedExpression(
-        code, typeProvider.dynamicType, typeProvider.intType);
+    assertPropagatedIterationType(code, typeProvider.dynamicType, null);
+    assertTypeOfMarkedExpression(code, typeProvider.dynamicType, null);
   }
 
   void test_foreachInference_reusedVar_disabled() {
@@ -2193,10 +2191,8 @@
     v; // marker
   }
 }''';
-    assertPropagatedIterationType(
-        code, typeProvider.dynamicType, typeProvider.intType);
-    assertTypeOfMarkedExpression(
-        code, typeProvider.dynamicType, typeProvider.intType);
+    assertPropagatedIterationType(code, typeProvider.dynamicType, null);
+    assertTypeOfMarkedExpression(code, typeProvider.dynamicType, null);
   }
 
   void test_foreachInference_var() {
@@ -2262,10 +2258,8 @@
   dynamic v = 3;
   v; // marker
 }''';
-    assertPropagatedAssignedType(
-        code, typeProvider.dynamicType, typeProvider.intType);
-    assertTypeOfMarkedExpression(
-        code, typeProvider.dynamicType, typeProvider.intType);
+    assertPropagatedAssignedType(code, typeProvider.dynamicType, null);
+    assertTypeOfMarkedExpression(code, typeProvider.dynamicType, null);
   }
 
   void test_localVariableInference_noInitializer_disabled() {
@@ -2275,10 +2269,8 @@
   v = 3;
   v; // marker
 }''';
-    assertPropagatedAssignedType(
-        code, typeProvider.dynamicType, typeProvider.intType);
-    assertTypeOfMarkedExpression(
-        code, typeProvider.dynamicType, typeProvider.intType);
+    assertPropagatedAssignedType(code, typeProvider.dynamicType, null);
+    assertTypeOfMarkedExpression(code, typeProvider.dynamicType, null);
   }
 
   void test_localVariableInference_transitive_field_inferred_lexical() {
diff --git a/pkg/analyzer/test/generated/test_all.dart b/pkg/analyzer/test/generated/test_all.dart
index 8aead2a..63b357d 100644
--- a/pkg/analyzer/test/generated/test_all.dart
+++ b/pkg/analyzer/test/generated/test_all.dart
@@ -35,6 +35,7 @@
 import 'static_warning_code_test.dart' as static_warning_code_test;
 import 'strong_mode_test.dart' as strong_mode_test;
 import 'type_system_test.dart' as type_system_test;
+import 'utilities_dart_test.dart' as utilities_dart_test;
 import 'utilities_test.dart' as utilities_test;
 
 /// Utility for manually running all tests.
@@ -68,6 +69,7 @@
     static_warning_code_test.main();
     strong_mode_test.main();
     type_system_test.main();
+    utilities_dart_test.main();
     utilities_test.main();
   });
 }
diff --git a/pkg/analyzer/test/generated/utilities_dart_test.dart b/pkg/analyzer/test/generated/utilities_dart_test.dart
new file mode 100644
index 0000000..c300c21
--- /dev/null
+++ b/pkg/analyzer/test/generated/utilities_dart_test.dart
@@ -0,0 +1,51 @@
+// 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.test.generated.utilities_dart_test;
+
+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';
+
+main() {
+  initializeTestEnvironment();
+  defineReflectiveTests(ResolveRelativeUriTest);
+}
+
+@reflectiveTest
+class ResolveRelativeUriTest {
+  void test_absolute() {
+    _validate('dart:core', 'dart:async', 'dart:async');
+    _validate('package:foo/foo.dart', 'dart:async', 'dart:async');
+    _validate('package:a/a.dart', 'package:b/b.dart', 'package:b/b.dart');
+    _validate('foo.dart', 'dart:async', 'dart:async');
+  }
+
+  void test_absoluteDart_relative() {
+    _validate('dart:core', 'int.dart', 'dart:core/int.dart');
+  }
+
+  void test_absolutePackage_relative() {
+    _validate('package:a/b.dart', 'c.dart', 'package:a/c.dart');
+    _validate('package:a/b/c.dart', 'd.dart', 'package:a/b/d.dart');
+    _validate('package:a/b/c.dart', '../d.dart', 'package:a/d.dart');
+  }
+
+  void test_relative_relative() {
+    _validate('a/b.dart', 'c.dart', 'a/c.dart');
+    _validate('a/b.dart', '../c.dart', 'c.dart');
+    _validate('a.dart', '../b.dart', '../b.dart');
+    _validate('a.dart', '../../b.dart', '../../b.dart');
+    // TODO(scheglov) After https://github.com/dart-lang/sdk/issues/27447
+    // TODO(scheglov) include also this, currently failing test.
+//    _validate('a/b.dart', '../../c.dart', '../c.dart');
+  }
+
+  void _validate(String base, String contained, String expected) {
+    Uri actual = resolveRelativeUri(Uri.parse(base), Uri.parse(contained));
+    expect(actual.toString(), expected);
+  }
+}
diff --git a/pkg/analyzer/test/src/summary/bazel_summary_test.dart b/pkg/analyzer/test/src/summary/bazel_summary_test.dart
new file mode 100644
index 0000000..afa2265
--- /dev/null
+++ b/pkg/analyzer/test/src/summary/bazel_summary_test.dart
@@ -0,0 +1,219 @@
+// 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:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/parser.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/summary/bazel_summary.dart';
+import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/summarize_ast.dart';
+import 'package:analyzer/src/summary/summarize_elements.dart';
+import 'package:analyzer/src/util/fast_uri.dart';
+import 'package:path/path.dart' as pathos;
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+import 'package:unittest/unittest.dart';
+
+import '../../utils.dart';
+import '../context/abstract_context.dart';
+
+main() {
+  initializeTestEnvironment();
+  defineReflectiveTests(SummaryProviderTest);
+}
+
+const OUT_ROOT = '$SRC_ROOT/bazel-bin';
+const SRC_ROOT = '/company/src/user/project/root';
+
+@reflectiveTest
+class SummaryProviderTest extends AbstractContextTest {
+  SummaryProvider manager;
+
+  @override
+  void setUp() {
+    super.setUp();
+    // Include a 'package' URI resolver.
+    sourceFactory = new SourceFactory(<UriResolver>[
+      sdkResolver,
+      resourceResolver,
+      new _TestPackageResolver(resourceProvider)
+    ], null, resourceProvider);
+    context.sourceFactory = sourceFactory;
+    // Create a new SummaryProvider instance.
+    manager = new SummaryProvider(resourceProvider, _getOutputPath, context);
+  }
+
+  test_getPackageForUri() {
+    String pathA = '$SRC_ROOT/components/aaa/lib';
+    resourceProvider.newFile(
+        '$pathA/a1.dart',
+        r'''
+class A1 {}
+''');
+    resourceProvider.newFile(
+        '$pathA/a2.dart',
+        r'''
+class A2 {}
+''');
+    _writeUnlinkedBundle('components.aaa');
+    // Ask the package for the URI.
+    Source source1 = _resolveUri('package:components.aaa/a1.dart');
+    Source source2 = _resolveUri('package:components.aaa/a2.dart');
+    Package package = manager.getPackageForUri(source1.uri);
+    expect(package, isNotNull);
+    // The same instance is returned to another URI in the same package.
+    expect(manager.getPackageForUri(source2.uri), same(package));
+  }
+
+  test_getPackageForUri_inconsistent() {
+    String pathA = '$SRC_ROOT/components/aaa/lib';
+    File fileA1 = resourceProvider.newFile(
+        '$pathA/a1.dart',
+        r'''
+class A1 {}
+''');
+    resourceProvider.newFile(
+        '$pathA/a2.dart',
+        r'''
+class A2 {}
+''');
+    _writeUnlinkedBundle('components.aaa');
+    // Update one of the files file, so the bundle is not consistent.
+    fileA1.writeAsStringSync('// different');
+    Source source1 = _resolveUri('package:components.aaa/a1.dart');
+    Source source2 = _resolveUri('package:components.aaa/a2.dart');
+    expect(manager.getPackageForUri(source1.uri), isNull);
+    expect(manager.getPackageForUri(source2.uri), isNull);
+  }
+
+  Source _resolveUri(String uri) {
+    return context.sourceFactory.resolveUri(null, uri);
+  }
+
+  void _writeUnlinkedBundle(String packageName) {
+    String packagePath = packageName.replaceAll('.', '/');
+    var unlinkedBundle = _computeUnlinkedBundle(
+        resourceProvider,
+        packageName,
+        resourceProvider.getFolder(SRC_ROOT + '/' + packagePath + '/lib'),
+        true);
+    String shortName = packageName.substring(packageName.lastIndexOf('.') + 1);
+    resourceProvider.newFileWithBytes(
+        '$OUT_ROOT/$packagePath/$shortName.full.ds', unlinkedBundle.toBuffer());
+  }
+
+  static PackageBundleBuilder _computeUnlinkedBundle(ResourceProvider provider,
+      String packageName, Folder libFolder, bool strong) {
+    var pathContext = provider.pathContext;
+    String libPath = libFolder.path + pathContext.separator;
+    PackageBundleAssembler assembler = new PackageBundleAssembler();
+
+    /**
+     * Return the `package` [Uri] for the given [path] in the `lib` folder
+     * of the current package.
+     */
+    Uri getUri(String path) {
+      String pathInLib = path.substring(libPath.length);
+      String uriPath = pathos.posix.joinAll(pathContext.split(pathInLib));
+      String uriStr = 'package:$packageName/$uriPath';
+      return FastUri.parse(uriStr);
+    }
+
+    /**
+     * If the given [file] is a Dart file, add its unlinked unit.
+     */
+    void addDartFile(File file) {
+      String path = file.path;
+      if (AnalysisEngine.isDartFileName(path)) {
+        Uri uri = getUri(path);
+        Source source = file.createSource(uri);
+        CompilationUnit unit = _parse(source, strong);
+        UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(unit);
+        assembler.addUnlinkedUnit(source, unlinkedUnit);
+      }
+    }
+
+    /**
+     * Visit the [folder] recursively.
+     */
+    void addDartFiles(Folder folder) {
+      List<Resource> children = folder.getChildren();
+      for (Resource child in children) {
+        if (child is File) {
+          addDartFile(child);
+        }
+      }
+      for (Resource child in children) {
+        if (child is Folder) {
+          addDartFiles(child);
+        }
+      }
+    }
+
+    addDartFiles(libFolder);
+    return assembler.assemble();
+  }
+
+  static String _getOutputPath(ResourceProvider provider, Uri uri) {
+    if (uri.scheme == 'package') {
+      List<String> segments = uri.pathSegments;
+      if (segments.isNotEmpty) {
+        String packageName = segments.first;
+        return OUT_ROOT + '/' + packageName.replaceAll('.', '/');
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Parse the given [source] into AST.
+   */
+  static CompilationUnit _parse(Source source, bool strong) {
+    String code = source.contents.data;
+    AnalysisErrorListener errorListener = AnalysisErrorListener.NULL_LISTENER;
+    CharSequenceReader reader = new CharSequenceReader(code);
+    Scanner scanner = new Scanner(source, reader, errorListener);
+    scanner.scanGenericMethodComments = strong;
+    Token token = scanner.tokenize();
+    LineInfo lineInfo = new LineInfo(scanner.lineStarts);
+    Parser parser = new Parser(source, errorListener);
+    parser.parseGenericMethodComments = strong;
+    CompilationUnit unit = parser.parseCompilationUnit(token);
+    unit.lineInfo = lineInfo;
+    return unit;
+  }
+}
+
+class _TestPackageResolver implements UriResolver {
+  final ResourceProvider resourceProvider;
+
+  _TestPackageResolver(this.resourceProvider);
+
+  @override
+  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
+    if (uri.scheme == 'package') {
+      List<String> segments = uri.pathSegments;
+      if (segments.isNotEmpty) {
+        pathos.Context pathContext = resourceProvider.pathContext;
+        String packageName = segments.first;
+        String folderPath = pathContext.join(
+            SRC_ROOT, packageName.replaceAll('.', pathContext.separator));
+        String path = pathContext.join(
+            folderPath, 'lib', pathContext.joinAll(segments.skip(1)));
+        return resourceProvider.getFile(path).createSource(uri);
+      }
+    }
+    return null;
+  }
+
+  @override
+  Uri restoreAbsolute(Source source) {
+    throw new UnimplementedError();
+  }
+}
diff --git a/pkg/analyzer/test/src/summary/test_all.dart b/pkg/analyzer/test/src/summary/test_all.dart
index ba099c7..2c9966b 100644
--- a/pkg/analyzer/test/src/summary/test_all.dart
+++ b/pkg/analyzer/test/src/summary/test_all.dart
@@ -8,6 +8,7 @@
 
 import '../../utils.dart';
 import 'api_signature_test.dart' as api_signature_test;
+import 'bazel_summary_test.dart' as bazel_summary_test;
 import 'flat_buffers_test.dart' as flat_buffers_test;
 import 'in_summary_source_test.dart' as in_summary_source_test;
 import 'linker_test.dart' as linker_test;
@@ -24,6 +25,7 @@
   initializeTestEnvironment();
   group('summary tests', () {
     api_signature_test.main();
+    bazel_summary_test.main();
     flat_buffers_test.main();
     in_summary_source_test.main();
     linker_test.main();
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart
index ef9b1eb..9013f21 100644
--- a/pkg/analyzer/test/src/task/strong/checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -497,7 +497,7 @@
   (/*info:DYNAMIC_INVOKE*/b2("hello"));
 
   dynamic a1 = new B();
-  (/*info:DYNAMIC_INVOKE*/a1./*info:UNDEFINED_GETTER*/x);
+  (/*info:DYNAMIC_INVOKE*/a1.x);
   a1.toString();
   (/*info:DYNAMIC_INVOKE*/a1.toString(42));
   var toStringClosure = a1.toString;
@@ -659,13 +659,13 @@
     int x;
     double y;
     x = /*info:DYNAMIC_CAST, info:DYNAMIC_INVOKE*/f(3);
-    x = /*info:DYNAMIC_CAST, info:DYNAMIC_INVOKE, info:INVALID_ASSIGNMENT*/f.col(3.0);
+    x = /*info:DYNAMIC_CAST, info:DYNAMIC_INVOKE*/f.col(3.0);
     y = /*info:DYNAMIC_CAST, info:DYNAMIC_INVOKE*/f(3);
     y = /*info:DYNAMIC_CAST, info:DYNAMIC_INVOKE*/f.col(3.0);
     /*info:DYNAMIC_INVOKE*/f(3.0);
     // Through type propagation, we know f is actually a B, hence the
     // hint.
-    /*info:DYNAMIC_INVOKE*/f.col(/*info:ARGUMENT_TYPE_NOT_ASSIGNABLE*/3);
+    /*info:DYNAMIC_INVOKE*/f.col(3);
   }
   {
     A f = new B();
@@ -677,10 +677,10 @@
   }
   {
     dynamic g = new B();
-    /*info:DYNAMIC_INVOKE*/g.call(/*info:ARGUMENT_TYPE_NOT_ASSIGNABLE*/32.0);
+    /*info:DYNAMIC_INVOKE*/g.call(32.0);
     /*info:DYNAMIC_INVOKE*/g.col(42.0);
     /*info:DYNAMIC_INVOKE*/g.foo(42.0);
-    /*info:DYNAMIC_INVOKE*/g./*info:UNDEFINED_GETTER*/x;
+    /*info:DYNAMIC_INVOKE*/g.x;
     A f = new B();
     /*info:DYNAMIC_INVOKE*/f.col(42.0);
     /*info:DYNAMIC_INVOKE*/f.foo(42.0);
@@ -1404,9 +1404,9 @@
     left = /*error:INVALID_ASSIGNMENT*/right;
     left = bot;
 
-    right = /*info:INVALID_ASSIGNMENT,warning:DOWN_CAST_COMPOSITE*/top;
+    right = /*warning:DOWN_CAST_COMPOSITE*/top;
     right = /*error:INVALID_ASSIGNMENT*/left;
-    right = /*info:INVALID_ASSIGNMENT*/right;
+    right = right;
     right = bot;
 
     bot = /*warning:DOWN_CAST_COMPOSITE*/top;
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 4928bd5..5a0bc4d 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -3613,9 +3613,7 @@
   }
 
   for (dynamic x in list) {
-    // The INVALID_ASSIGNMENT hint is because type propagation knows x is
-    // a Foo.
-    String y = /*info:DYNAMIC_CAST,info:INVALID_ASSIGNMENT*/x;
+    String y = /*info:DYNAMIC_CAST*/x;
   }
 
   for (String x in /*error:FOR_IN_OF_INVALID_ELEMENT_TYPE*/list) {
@@ -3624,7 +3622,7 @@
 
   var z;
   for(z in list) {
-    String y = /*info:DYNAMIC_CAST,info:INVALID_ASSIGNMENT*/z;
+    String y = /*info:DYNAMIC_CAST*/z;
   }
 
   Iterable iter = list;
@@ -3793,6 +3791,27 @@
     expect(unit.topLevelVariables[0].type.toString(), 'B<A>');
   }
 
+  void test_lambdaDoesNotHavePropagatedTypeHint() {
+    checkFile(r'''
+List<String> getListOfString() => const <String>[];
+
+void foo() {
+  List myList = getListOfString();
+  myList.map((type) => 42);
+}
+
+void bar() {
+  var list;
+  try {
+    list = <String>[];
+  } catch (_) {
+    return;
+  }
+  /*info:DYNAMIC_INVOKE*/list.map((value) => '$value');
+}
+    ''');
+  }
+
   void test_listLiterals() {
     checkFile(r'''
 test1() {
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index 0c3a507..9ee75e9 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -365,6 +365,7 @@
     new OptionHandler(Flags.analyzeSignaturesOnly, setAnalyzeOnly),
     new OptionHandler(Flags.disableNativeLiveTypeAnalysis, passThrough),
     new OptionHandler('--categories=.*', setCategories),
+    new OptionHandler(Flags.disableInlining, implyCompilation),
     new OptionHandler(Flags.disableTypeInference, implyCompilation),
     new OptionHandler(Flags.terse, passThrough),
     new OptionHandler('--deferred-map=.+', implyCompilation),
diff --git a/pkg/compiler/lib/src/kernel/kernel_visitor.dart b/pkg/compiler/lib/src/kernel/kernel_visitor.dart
index 37ab7d2..ef34ee9 100644
--- a/pkg/compiler/lib/src/kernel/kernel_visitor.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_visitor.dart
@@ -435,7 +435,9 @@
     JumpTarget jumpTarget = elements.getTargetDefinition(node);
     body = buildContinueTarget(body, node, jumpTarget);
     return buildBreakTarget(
-        new ir.ForInStatement(variable, iterable, body, isAsync: isAsync),
+        associateNode(
+            new ir.ForInStatement(variable, iterable, body, isAsync: isAsync),
+            node),
         node,
         jumpTarget);
   }
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index a39f87c..fd89518 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -48,23 +48,6 @@
 import 'ssa_branch_builder.dart';
 import 'types.dart';
 
-/// A synthetic local variable only used with the SSA graph.
-///
-/// For instance used for holding return value of function or the exception of a
-/// try-catch statement.
-class SyntheticLocal extends Local {
-  final String name;
-  final ExecutableElement executableContext;
-
-  // Avoid slow Object.hashCode.
-  final int hashCode = _nextHashCode = (_nextHashCode + 1).toUnsigned(30);
-  static int _nextHashCode = 0;
-
-  SyntheticLocal(this.name, this.executableContext);
-
-  toString() => 'SyntheticLocal($name)';
-}
-
 class SsaBuilderTask extends CompilerTask {
   final CodeEmitterTask emitter;
   final JavaScriptBackend backend;
@@ -930,14 +913,14 @@
    * Invariant: [constructors] must contain only implementation elements.
    */
   void inlineSuperOrRedirect(
-      ResolvedAst constructorRecolvedAst,
+      ResolvedAst constructorResolvedAst,
       List<HInstruction> compiledArguments,
       List<ResolvedAst> constructorResolvedAsts,
       Map<Element, HInstruction> fieldValues,
       FunctionElement caller) {
-    ConstructorElement callee = constructorRecolvedAst.element.implementation;
+    ConstructorElement callee = constructorResolvedAst.element.implementation;
     reporter.withCurrentElement(callee, () {
-      constructorResolvedAsts.add(constructorRecolvedAst);
+      constructorResolvedAsts.add(constructorResolvedAst);
       ClassElement enclosingClass = callee.enclosingClass;
       if (backend.classNeedsRti(enclosingClass)) {
         // If [enclosingClass] needs RTI, we have to give a value to its
@@ -975,7 +958,7 @@
       // For redirecting constructors, the fields will be initialized later
       // by the effective target.
       if (!callee.isRedirectingGenerative) {
-        inlinedFrom(constructorRecolvedAst, () {
+        inlinedFrom(constructorResolvedAst, () {
           buildFieldInitializers(
               callee.enclosingClass.implementation, fieldValues);
         });
@@ -2325,12 +2308,6 @@
   }
 
   @override
-  pushCheckNull(HInstruction expression) {
-    push(new HIdentity(
-        expression, graph.addConstantNull(compiler), null, backend.boolType));
-  }
-
-  @override
   void visitLocalVariableGet(ast.Send node, LocalVariableElement variable, _) {
     handleLocalGet(node, variable);
   }
@@ -5652,7 +5629,7 @@
 
     // This scheme recognizes for-in on direct lists.  It does not recognize all
     // uses of ArrayIterator.  They still occur when the receiver is an Iterable
-    // with a `get iterator` method that delegate to another Iterable and the
+    // with a `get iterator` method that delegates to another Iterable and the
     // method is inlined.  We would require full scalar replacement in that
     // case.
 
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 2d4726d..a309e39 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -6,6 +6,7 @@
 
 import '../common.dart';
 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
+import '../common/names.dart';
 import '../common/tasks.dart' show CompilerTask;
 import '../compiler.dart';
 import '../dart_types.dart';
@@ -17,7 +18,6 @@
 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';
@@ -53,8 +53,10 @@
   final ResolvedAst resolvedAst;
   final CodegenRegistry registry;
 
+  @override
   JavaScriptBackend get backend => compiler.backend;
 
+  @override
   TreeElements get elements => resolvedAst.elements;
 
   SourceInformationBuilder sourceInformationBuilder;
@@ -98,13 +100,7 @@
     } else if (target is ir.Field) {
       buildField(target);
     } else if (target is ir.Constructor) {
-      // TODO(het): Actually handle this correctly
-      HBasicBlock block = graph.addNewBlock();
-      open(graph.entry);
-      close(new HGoto()).addSuccessor(block);
-      open(block);
-      closeAndGotoExit(new HGoto());
-      graph.finalize();
+      buildConstructor(target);
     }
     assert(graph.isValid());
     return graph;
@@ -127,12 +123,14 @@
     return result;
   }
 
-  // TODO(het): This implementation is shared with [SsaBuilder]. Should we just
-  // allow [GraphBuilder] to access `compiler`?
-  @override
-  pushCheckNull(HInstruction expression) {
-    push(new HIdentity(
-        expression, graph.addConstantNull(compiler), null, backend.boolType));
+  void buildConstructor(ir.Constructor constructor) {
+    // TODO(het): Actually handle this correctly
+    HBasicBlock block = graph.addNewBlock();
+    open(graph.entry);
+    close(new HGoto()).addSuccessor(block);
+    open(block);
+    closeAndGotoExit(new HGoto());
+    graph.finalize();
   }
 
   /// Builds a SSA graph for [procedure].
@@ -242,6 +240,164 @@
   }
 
   @override
+  void visitForInStatement(ir.ForInStatement forInStatement) {
+    if (forInStatement.isAsync) {
+      compiler.reporter.internalError(astAdapter.getNode(forInStatement),
+          "Cannot compile async for-in using kernel.");
+    }
+    // If the expression being iterated over is a JS indexable type, we can
+    // generate an optimized version of for-in that uses indexing.
+    if (astAdapter.isJsIndexableIterator(forInStatement)) {
+      _buildForInIndexable(forInStatement);
+    } else {
+      _buildForInIterator(forInStatement);
+    }
+  }
+
+  /// Builds the graph for a for-in node with an indexable expression.
+  ///
+  /// In this case we build:
+  ///
+  ///    int end = a.length;
+  ///    for (int i = 0;
+  ///         i < a.length;
+  ///         checkConcurrentModificationError(a.length == end, a), ++i) {
+  ///      <declaredIdentifier> = a[i];
+  ///      <body>
+  ///    }
+  _buildForInIndexable(ir.ForInStatement forInStatement) {
+    SyntheticLocal indexVariable = new SyntheticLocal('_i', targetElement);
+
+    // These variables are shared by initializer, condition, body and update.
+    HInstruction array; // Set in buildInitializer.
+    bool isFixed; // Set in buildInitializer.
+    HInstruction originalLength = null; // Set for growable lists.
+
+    HInstruction buildGetLength() {
+      HFieldGet result = new HFieldGet(
+          astAdapter.jsIndexableLength, array, backend.positiveIntType,
+          isAssignable: !isFixed);
+      add(result);
+      return result;
+    }
+
+    void buildConcurrentModificationErrorCheck() {
+      if (originalLength == null) return;
+      // The static call checkConcurrentModificationError() is expanded in
+      // codegen to:
+      //
+      //     array.length == _end || throwConcurrentModificationError(array)
+      //
+      HInstruction length = buildGetLength();
+      push(new HIdentity(length, originalLength, null, backend.boolType));
+      _pushStaticInvocation(
+          astAdapter.checkConcurrentModificationError,
+          [pop(), array],
+          astAdapter.checkConcurrentModificationErrorReturnType);
+      pop();
+    }
+
+    void buildInitializer() {
+      forInStatement.iterable.accept(this);
+      array = pop();
+      isFixed = astAdapter.isFixedLength(array.instructionType);
+      localsHandler.updateLocal(
+          indexVariable, graph.addConstantInt(0, compiler));
+      originalLength = buildGetLength();
+    }
+
+    HInstruction buildCondition() {
+      HInstruction index = localsHandler.readLocal(indexVariable);
+      HInstruction length = buildGetLength();
+      HInstruction compare = new HLess(index, length, null, backend.boolType);
+      add(compare);
+      return compare;
+    }
+
+    void buildBody() {
+      // If we had mechanically inlined ArrayIterator.moveNext(), it would have
+      // inserted the ConcurrentModificationError check as part of the
+      // condition.  It is not necessary on the first iteration since there is
+      // no code between calls to `get iterator` and `moveNext`, so the test is
+      // moved to the loop update.
+
+      // Find a type for the element. Use the element type of the indexer of the
+      // array, as this is stronger than the iterator's `get current` type, for
+      // example, `get current` includes null.
+      // TODO(sra): The element type of a container type mask might be better.
+      TypeMask type = astAdapter.inferredIndexType(forInStatement);
+
+      HInstruction index = localsHandler.readLocal(indexVariable);
+      HInstruction value = new HIndex(array, index, null, type);
+      add(value);
+
+      localsHandler.updateLocal(
+          astAdapter.getLocal(forInStatement.variable), value);
+
+      forInStatement.body.accept(this);
+    }
+
+    void buildUpdate() {
+      // See buildBody as to why we check here.
+      buildConcurrentModificationErrorCheck();
+
+      // TODO(sra): It would be slightly shorter to generate `a[i++]` in the
+      // body (and that more closely follows what an inlined iterator would do)
+      // but the code is horrible as `i+1` is carried around the loop in an
+      // additional variable.
+      HInstruction index = localsHandler.readLocal(indexVariable);
+      HInstruction one = graph.addConstantInt(1, compiler);
+      HInstruction addInstruction =
+          new HAdd(index, one, null, backend.positiveIntType);
+      add(addInstruction);
+      localsHandler.updateLocal(indexVariable, addInstruction);
+    }
+
+    loopHandler.handleLoop(forInStatement, buildInitializer, buildCondition,
+        buildUpdate, buildBody);
+  }
+
+  _buildForInIterator(ir.ForInStatement forInStatement) {
+    // Generate a structure equivalent to:
+    //   Iterator<E> $iter = <iterable>.iterator;
+    //   while ($iter.moveNext()) {
+    //     <declaredIdentifier> = $iter.current;
+    //     <body>
+    //   }
+
+    // The iterator is shared between initializer, condition and body.
+    HInstruction iterator;
+
+    void buildInitializer() {
+      TypeMask mask = astAdapter.typeOfIterator(forInStatement);
+      forInStatement.iterable.accept(this);
+      HInstruction receiver = pop();
+      _pushDynamicInvocation(forInStatement, mask, <HInstruction>[receiver],
+          selector: Selectors.iterator);
+      iterator = pop();
+    }
+
+    HInstruction buildCondition() {
+      TypeMask mask = astAdapter.typeOfIteratorMoveNext(forInStatement);
+      _pushDynamicInvocation(forInStatement, mask, <HInstruction>[iterator],
+          selector: Selectors.moveNext);
+      return popBoolified();
+    }
+
+    void buildBody() {
+      TypeMask mask = astAdapter.typeOfIteratorCurrent(forInStatement);
+      _pushDynamicInvocation(forInStatement, mask, [iterator],
+          selector: Selectors.current);
+      localsHandler.updateLocal(
+          astAdapter.getLocal(forInStatement.variable), pop());
+      forInStatement.body.accept(this);
+    }
+
+    loopHandler.handleLoop(
+        forInStatement, buildInitializer, buildCondition, () {}, buildBody);
+  }
+
+  @override
   void visitWhileStatement(ir.WhileStatement whileStatement) {
     assert(isReachable);
     HInstruction buildCondition() {
@@ -330,7 +486,10 @@
       // TODO(het): set runtime type info
     }
 
-    // TODO(het): Set the instruction type to the list type given by inference
+    TypeMask type = astAdapter.typeOfNewList(targetElement, listLiteral);
+    if (!type.containsAll(compiler.closedWorld)) {
+      listInstruction.instructionType = type;
+    }
     stack.add(listInstruction);
   }
 
@@ -412,23 +571,13 @@
     propertyGet.receiver.accept(this);
     HInstruction receiver = pop();
 
-    List<HInstruction> inputs = <HInstruction>[];
-    bool isIntercepted = astAdapter.isIntercepted(propertyGet);
-    if (isIntercepted) {
-      HInterceptor interceptor = _interceptorFor(receiver);
-      inputs.add(interceptor);
-    }
-    inputs.add(receiver);
-
-    TypeMask type = astAdapter.selectorGetterTypeOf(propertyGet);
-
-    push(new HInvokeDynamicGetter(astAdapter.getGetterSelector(propertyGet),
-        astAdapter.typeOfGet(propertyGet), null, inputs, type));
+    _pushDynamicInvocation(propertyGet, astAdapter.typeOfGet(propertyGet),
+        <HInstruction>[receiver]);
   }
 
   @override
   void visitVariableGet(ir.VariableGet variableGet) {
-    LocalElement local = astAdapter.getElement(variableGet.variable);
+    Local local = astAdapter.getLocal(variableGet.variable);
     stack.add(localsHandler.readLocal(local));
   }
 
@@ -441,7 +590,7 @@
 
   @override
   void visitVariableDeclaration(ir.VariableDeclaration declaration) {
-    LocalElement local = astAdapter.getElement(declaration);
+    Local local = astAdapter.getLocal(declaration);
     if (declaration.initializer == null) {
       HInstruction initialValue = graph.addConstantNull(compiler);
       localsHandler.updateLocal(local, initialValue);
@@ -508,28 +657,43 @@
     push(instruction);
   }
 
-  // TODO(het): Decide when to inline
-  @override
-  void visitMethodInvocation(ir.MethodInvocation invocation) {
-    invocation.receiver.accept(this);
-    HInstruction receiver = pop();
-
-    List<HInstruction> arguments = <HInstruction>[receiver]
-      ..addAll(_visitArguments(invocation.arguments));
-
+  void _pushDynamicInvocation(
+      ir.Node node, TypeMask mask, List<HInstruction> arguments,
+      {Selector selector}) {
+    HInstruction receiver = arguments.first;
     List<HInstruction> inputs = <HInstruction>[];
 
-    bool isIntercepted = astAdapter.isIntercepted(invocation);
+    selector ??= astAdapter.getSelector(node);
+    bool isIntercepted = astAdapter.isInterceptedSelector(selector);
+
     if (isIntercepted) {
       HInterceptor interceptor = _interceptorFor(receiver);
       inputs.add(interceptor);
     }
     inputs.addAll(arguments);
 
-    TypeMask type = astAdapter.selectorTypeOf(invocation);
+    TypeMask type = astAdapter.selectorTypeOf(selector, mask);
+    if (selector.isGetter) {
+      push(new HInvokeDynamicGetter(selector, mask, null, inputs, type));
+    } else if (selector.isSetter) {
+      push(new HInvokeDynamicSetter(selector, mask, null, inputs, type));
+    } else {
+      push(new HInvokeDynamicMethod(
+          selector, mask, inputs, type, isIntercepted));
+    }
+  }
 
-    push(new HInvokeDynamicMethod(astAdapter.getSelector(invocation),
-        astAdapter.typeOfInvocation(invocation), inputs, type, isIntercepted));
+  // TODO(het): Decide when to inline
+  @override
+  void visitMethodInvocation(ir.MethodInvocation invocation) {
+    invocation.receiver.accept(this);
+    HInstruction receiver = pop();
+
+    _pushDynamicInvocation(
+        invocation,
+        astAdapter.typeOfInvocation(invocation),
+        <HInstruction>[receiver]
+          ..addAll(_visitArguments(invocation.arguments)));
   }
 
   HInterceptor _interceptorFor(HInstruction intercepted) {
diff --git a/pkg/compiler/lib/src/ssa/graph_builder.dart b/pkg/compiler/lib/src/ssa/graph_builder.dart
index 9898c6a..a6ef442 100644
--- a/pkg/compiler/lib/src/ssa/graph_builder.dart
+++ b/pkg/compiler/lib/src/ssa/graph_builder.dart
@@ -4,9 +4,9 @@
 
 import '../compiler.dart';
 import '../elements/elements.dart';
+import '../js_backend/js_backend.dart';
 import '../resolution/tree_elements.dart';
 import '../types/types.dart';
-
 import 'jump_handler.dart';
 import 'locals_handler.dart';
 import 'nodes.dart';
@@ -23,6 +23,9 @@
   /// A reference to the compiler.
   Compiler compiler;
 
+  /// The JavaScript backend we are targeting in this compilation.
+  JavaScriptBackend get backend;
+
   /// The tree elements for the element being built into an SSA graph.
   TreeElements get elements;
 
@@ -58,7 +61,10 @@
   HInstruction popBoolified();
 
   /// Pushes a boolean checking [expression] against null.
-  pushCheckNull(HInstruction expression);
+  pushCheckNull(HInstruction expression) {
+    push(new HIdentity(
+        expression, graph.addConstantNull(compiler), null, backend.boolType));
+  }
 
   void dup() {
     stack.add(stack.last);
diff --git a/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart b/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart
index 7f5b6f0..86aee00 100644
--- a/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart
+++ b/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart
@@ -15,9 +15,12 @@
 import '../resolution/tree_elements.dart';
 import '../tree/tree.dart' as ast;
 import '../types/masks.dart';
+import '../types/types.dart';
 import '../universe/call_structure.dart';
 import '../universe/selector.dart';
 import '../universe/side_effects.dart';
+import '../world.dart';
+import 'locals_handler.dart';
 import 'types.dart';
 
 /// A helper class that abstracts all accesses of the AST from Kernel nodes.
@@ -29,6 +32,8 @@
   final ResolvedAst _resolvedAst;
   final Map<ir.Node, ast.Node> _nodeToAst;
   final Map<ir.Node, Element> _nodeToElement;
+  final Map<ir.VariableDeclaration, SyntheticLocal> _syntheticLocals =
+      <ir.VariableDeclaration, SyntheticLocal>{};
   DartTypeConverter _typeConverter;
 
   KernelAstAdapter(this.kernel, this._backend, this._resolvedAst,
@@ -54,6 +59,8 @@
 
   Compiler get _compiler => _backend.compiler;
   TreeElements get elements => _resolvedAst.elements;
+  GlobalTypeInferenceResults get _inferenceResults =>
+      _compiler.globalInference.results;
 
   ConstantValue getConstantForSymbol(ir.SymbolLiteral node) {
     ast.Node astNode = getNode(node);
@@ -76,6 +83,15 @@
     return result;
   }
 
+  Local getLocal(ir.VariableDeclaration variable) {
+    // If this is a synthetic local, return the synthetic local
+    if (variable.name == null) {
+      return _syntheticLocals.putIfAbsent(
+          variable, () => new SyntheticLocal("x", null));
+    }
+    return getElement(variable) as LocalElement;
+  }
+
   bool getCanThrow(ir.Node procedure) {
     FunctionElement function = getElement(procedure);
     return !_compiler.closedWorld.getCannotThrow(function);
@@ -101,8 +117,15 @@
         name.name, name.isPrivate ? getElement(name.library) : null);
   }
 
-  // TODO(het): Create the selector directly from the invocation
-  Selector getSelector(ir.InvocationExpression invocation) {
+  Selector getSelector(ir.Expression node) {
+    if (node is ir.PropertyGet) return getGetterSelector(node);
+    if (node is ir.InvocationExpression) return getInvocationSelector(node);
+    _compiler.reporter.internalError(getNode(node),
+        "Can only get the selector for a property get or an invocation.");
+    return null;
+  }
+
+  Selector getInvocationSelector(ir.InvocationExpression invocation) {
     Name name = getName(invocation.name);
     SelectorKind kind;
     if (Elements.isOperatorName(invocation.name.name)) {
@@ -126,28 +149,75 @@
     return new Selector.getter(name);
   }
 
-  TypeMask typeOfInvocation(ir.MethodInvocation invocation) {
-    return _compiler.globalInference.results
-        .typeOfSend(getNode(invocation), elements);
+  TypeMask typeOfInvocation(ir.Expression send) {
+    return _inferenceResults.typeOfSend(getNode(send), elements);
   }
 
   TypeMask typeOfGet(ir.PropertyGet getter) {
-    return _compiler.globalInference.results
-        .typeOfSend(getNode(getter), elements);
+    return _inferenceResults.typeOfSend(getNode(getter), elements);
+  }
+
+  TypeMask typeOfSend(ir.Expression send) {
+    assert(send is ir.InvocationExpression || send is ir.PropertyGet);
+    return _inferenceResults.typeOfSend(getNode(send), elements);
+  }
+
+  TypeMask typeOfNewList(Element owner, ir.ListLiteral listLiteral) {
+    return _inferenceResults.typeOfNewList(owner, getNode(listLiteral)) ??
+        _compiler.commonMasks.dynamicType;
+  }
+
+  TypeMask typeOfIterator(ir.ForInStatement forInStatement) {
+    return _inferenceResults.typeOfIterator(getNode(forInStatement), elements);
+  }
+
+  TypeMask typeOfIteratorCurrent(ir.ForInStatement forInStatement) {
+    return _inferenceResults.typeOfIteratorCurrent(
+        getNode(forInStatement), elements);
+  }
+
+  TypeMask typeOfIteratorMoveNext(ir.ForInStatement forInStatement) {
+    return _inferenceResults.typeOfIteratorMoveNext(
+        getNode(forInStatement), elements);
+  }
+
+  bool isJsIndexableIterator(ir.ForInStatement forInStatement) {
+    TypeMask mask = typeOfIterator(forInStatement);
+    ClosedWorld closedWorld = _compiler.closedWorld;
+    return mask != null &&
+        mask.satisfies(_backend.helpers.jsIndexableClass, closedWorld) &&
+        // String is indexable but not iterable.
+        !mask.satisfies(_backend.helpers.jsStringClass, closedWorld);
+  }
+
+  bool isFixedLength(TypeMask mask) {
+    ClosedWorld closedWorld = _compiler.closedWorld;
+    JavaScriptBackend backend = _compiler.backend;
+    if (mask.isContainer && (mask as ContainerTypeMask).length != null) {
+      // A container on which we have inferred the length.
+      return true;
+    }
+    // TODO(sra): Recognize any combination of fixed length indexables.
+    if (mask.containsOnly(backend.helpers.jsFixedArrayClass) ||
+        mask.containsOnly(backend.helpers.jsUnmodifiableArrayClass) ||
+        mask.containsOnlyString(closedWorld) ||
+        backend.isTypedArray(mask)) {
+      return true;
+    }
+    return false;
+  }
+
+  TypeMask inferredIndexType(ir.ForInStatement forInStatement) {
+    return TypeMaskFactory.inferredTypeForSelector(
+        new Selector.index(), typeOfIterator(forInStatement), _compiler);
   }
 
   TypeMask inferredTypeOf(ir.Member node) {
     return TypeMaskFactory.inferredTypeForElement(getElement(node), _compiler);
   }
 
-  TypeMask selectorTypeOf(ir.MethodInvocation invocation) {
-    return TypeMaskFactory.inferredTypeForSelector(
-        getSelector(invocation), typeOfInvocation(invocation), _compiler);
-  }
-
-  TypeMask selectorGetterTypeOf(ir.PropertyGet getter) {
-    return TypeMaskFactory.inferredTypeForSelector(
-        getGetterSelector(getter), typeOfGet(getter), _compiler);
+  TypeMask selectorTypeOf(Selector selector, TypeMask mask) {
+    return TypeMaskFactory.inferredTypeForSelector(selector, mask, _compiler);
   }
 
   ConstantValue getConstantFor(ir.Node node) {
@@ -159,12 +229,11 @@
   }
 
   bool isIntercepted(ir.Node node) {
-    Selector selector;
-    if (node is ir.PropertyGet) {
-      selector = getGetterSelector(node);
-    } else {
-      selector = getSelector(node);
-    }
+    Selector selector = getSelector(node);
+    return _backend.isInterceptedSelector(selector);
+  }
+
+  bool isInterceptedSelector(Selector selector) {
     return _backend.isInterceptedSelector(selector);
   }
 
@@ -177,6 +246,15 @@
   ir.Procedure get mapLiteralConstructorEmpty =>
       kernel.functions[_backend.helpers.mapLiteralConstructorEmpty];
 
+  Element get jsIndexableLength => _backend.helpers.jsIndexableLength;
+
+  ir.Procedure get checkConcurrentModificationError =>
+      kernel.functions[_backend.helpers.checkConcurrentModificationError];
+
+  TypeMask get checkConcurrentModificationErrorReturnType =>
+      TypeMaskFactory.inferredReturnTypeForElement(
+          _backend.helpers.checkConcurrentModificationError, _compiler);
+
   DartType getDartType(ir.DartType type) {
     return type.accept(_typeConverter);
   }
diff --git a/pkg/compiler/lib/src/ssa/locals_handler.dart b/pkg/compiler/lib/src/ssa/locals_handler.dart
index 2aa766c..dc2babe 100644
--- a/pkg/compiler/lib/src/ssa/locals_handler.dart
+++ b/pkg/compiler/lib/src/ssa/locals_handler.dart
@@ -14,7 +14,7 @@
 import '../tree/tree.dart' as ast;
 import '../types/types.dart';
 import '../world.dart' show ClosedWorld;
-import 'builder.dart' show SyntheticLocal;
+
 import 'graph_builder.dart';
 import 'nodes.dart';
 import 'types.dart';
@@ -657,3 +657,20 @@
   /// accessed indirectly through [HLocalGet] and [HLocalSet].
   Map<Local, HLocalValue> activationVariables = <Local, HLocalValue>{};
 }
+
+/// A synthetic local variable only used with the SSA graph.
+///
+/// For instance used for holding return value of function or the exception of a
+/// try-catch statement.
+class SyntheticLocal extends Local {
+  final String name;
+  final ExecutableElement executableContext;
+
+  // Avoid slow Object.hashCode.
+  final int hashCode = _nextHashCode = (_nextHashCode + 1).toUnsigned(30);
+  static int _nextHashCode = 0;
+
+  SyntheticLocal(this.name, this.executableContext);
+
+  toString() => 'SyntheticLocal($name)';
+}
diff --git a/pkg/dev_compiler/lib/src/analyzer/context.dart b/pkg/dev_compiler/lib/src/analyzer/context.dart
index 3545bca..bc47716 100644
--- a/pkg/dev_compiler/lib/src/analyzer/context.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/context.dart
@@ -51,7 +51,7 @@
       String dartSdkPath,
       this.dartSdkSummaryPath,
       this.customUrlMappings: const {},
-      this.packageRoot: 'packages/',
+      this.packageRoot: null,
       this.packagePaths: const []})
       : dartSdkPath = dartSdkPath ?? getSdkDir().path;
 
@@ -74,9 +74,7 @@
       ..addOption('dart-sdk-summary',
           help: 'Dart SDK Summary Path', defaultsTo: null)
       ..addOption('package-root',
-          abbr: 'p',
-          help: 'Package root to resolve "package:" imports',
-          defaultsTo: 'packages/')
+          abbr: 'p', help: 'Package root to resolve "package:" imports')
       ..addOption('url-mapping',
           help: '--url-mapping=libraryUri,/path/to/library.dart uses\n'
               'library.dart as the source for an import of of "libraryUri".',
@@ -142,7 +140,9 @@
   resourceProvider ??= PhysicalResourceProvider.INSTANCE;
   UriResolver packageResolver() {
     ContextBuilder builder = new ContextBuilder(resourceProvider, null, null);
-    builder.defaultPackagesDirectoryPath = options.packageRoot;
+    if (options.packageRoot != null) {
+      builder.defaultPackagesDirectoryPath = options.packageRoot;
+    }
     return new PackageMapUriResolver(resourceProvider,
         builder.convertPackagesToMap(builder.createPackageMap('')));
   }
diff --git a/pkg/dev_compiler/lib/src/compiler/js_typeref_codegen.dart b/pkg/dev_compiler/lib/src/compiler/js_typeref_codegen.dart
index b43692d..28bb626 100644
--- a/pkg/dev_compiler/lib/src/compiler/js_typeref_codegen.dart
+++ b/pkg/dev_compiler/lib/src/compiler/js_typeref_codegen.dart
@@ -52,8 +52,10 @@
           for (var param in type.parameters) {
             if (param.parameterKind == ParameterKind.NAMED) break;
             var type = emitTypeRef(param.type);
-            args[new JS.Identifier(param.name)] = param.parameterKind ==
-                ParameterKind.POSITIONAL ? type.toOptional() : type;
+            args[new JS.Identifier(param.name)] =
+                param.parameterKind == ParameterKind.POSITIONAL
+                    ? type.toOptional()
+                    : type;
           }
           var namedParamType = emitNamedParamsArgType(type.parameters);
           if (namedParamType != null) {
diff --git a/pkg/dev_compiler/lib/src/compiler/nullable_type_inference.dart b/pkg/dev_compiler/lib/src/compiler/nullable_type_inference.dart
index e1821e0..39f0130 100644
--- a/pkg/dev_compiler/lib/src/compiler/nullable_type_inference.dart
+++ b/pkg/dev_compiler/lib/src/compiler/nullable_type_inference.dart
@@ -235,6 +235,7 @@
       // they are nullable too.
       _assignments.remove(e)?.forEach(visitNullableLocal);
     }
+
     _nullableLocals.forEach(visitNullableLocal);
 
     // Any remaining locals are non-null.
diff --git a/pkg/dev_compiler/lib/src/compiler/type_utilities.dart b/pkg/dev_compiler/lib/src/compiler/type_utilities.dart
index 260c200..27abedd3 100644
--- a/pkg/dev_compiler/lib/src/compiler/type_utilities.dart
+++ b/pkg/dev_compiler/lib/src/compiler/type_utilities.dart
@@ -25,6 +25,7 @@
       t.typeArguments.forEach(find);
     }
   }
+
   find(t);
   return result;
 }
@@ -196,6 +197,7 @@
       if (types == null) _scopeDependencies[i] = types = [];
       types.add(type);
     }
+
     fvs.forEach(addScope);
     return false;
   }
diff --git a/pkg/dev_compiler/pubspec.yaml b/pkg/dev_compiler/pubspec.yaml
deleted file mode 100644
index 7abbb62..0000000
--- a/pkg/dev_compiler/pubspec.yaml
+++ /dev/null
@@ -1,40 +0,0 @@
-name: dev_compiler
-version: 0.2.0
-description: >
-  Experimental Dart to JavaScript compiler designed to create idiomatic,
-  readable JavaScript output.
-
-author: Dart Dev Compiler team <dev-compiler@dartlang.org>
-homepage: https://github.com/dart-lang/dev_compiler
-
-dependencies:
-  analyzer: ^0.29.0-alpha.0
-  args: ^0.13.0
-  bazel_worker: ^0.1.0
-  browser: ^0.10.0
-  cli_util: ^0.0.1
-  func: ^0.1.0
-  html: ^0.12.0
-  js: ^0.6.0
-  meta: ^1.0.3
-  path: ^1.3.0
-  pub_semver: ^1.1.0
-  source_maps: ^0.10.0
-  source_span: ^1.0.2
-
-dev_dependencies:
-  # We pin a specific version to ensure everyone is formatting the code exactly
-  # the same way. This is because any change in dart_style, even non-breaking
-  # changes, may change the output format.
-  dart_style: 0.2.4
-  test: ^0.12.0
-  unittest: ^0.11.6
-  webdriver: ^1.1.0
-
-dependency_overrides:
-  # Depend directly on packages in the same repositiory
-  analyzer: { path: ../analyzer }
-  meta: { path: ../meta }
-
-environment:
-  sdk: ">=1.12.0 <2.0.0"
diff --git a/pkg/dev_compiler/test/browser/language_tests.js b/pkg/dev_compiler/test/browser/language_tests.js
index 70b7586..5922544 100644
--- a/pkg/dev_compiler/test/browser/language_tests.js
+++ b/pkg/dev_compiler/test/browser/language_tests.js
@@ -570,6 +570,20 @@
       'js_typed_interop_default_arg_test_default_value_multi': ['unittest', 'skip', 'fail']
     },
 
+    'lib/html/custom': {
+      'attribute_changed_callback_test': ['unittest', 'skip', 'fail'],
+      'constructor_calls_created_synchronously_test':
+        ['unittest', 'skip', 'fail'],
+      'created_callback_test': ['unittest', 'skip', 'fail'],
+      'document_register_basic_test': ['unittest', 'skip', 'fail'],
+      'document_register_type_extensions_test': ['unittest', 'skip', 'fail'],
+      'element_upgrade_test': ['unittest', 'skip', 'fail'],
+      'entered_left_view_test': ['unittest', 'skip', 'fail'],
+      'js_custom_test': ['unittest', 'skip', 'fail'],
+      'mirrors_test': ['unittest', 'skip', 'fail'],
+      'regress_194523002_test': ['unittest', 'skip', 'fail'],
+    },
+
     'lib/math': {
       // TODO(het): triage
       'double_pow_test': skip_fail,
diff --git a/pkg/dev_compiler/test/codegen_test.dart b/pkg/dev_compiler/test/codegen_test.dart
index c6695bf..1f171f0 100644
--- a/pkg/dev_compiler/test/codegen_test.dart
+++ b/pkg/dev_compiler/test/codegen_test.dart
@@ -83,8 +83,12 @@
   var testDirs = [
     'language',
     'corelib',
+    path.join('corelib', 'regexp'),
     path.join('lib', 'convert'),
     path.join('lib', 'html'),
+    // TODO(vsm): Fix these - they import files from a different directory
+    // - this triggers an invalid library root build error.
+    // path.join('lib', 'html', 'custom'),
     path.join('lib', 'math'),
     path.join('lib', 'mirrors'),
     path.join('lib', 'typed_data'),
@@ -218,7 +222,7 @@
 
   for (var testDir in testDirs) {
     for (var file
-        in _listFiles(path.join(codegenDir, testDir), recursive: true)) {
+        in _listFiles(path.join(codegenDir, testDir), recursive: false)) {
       var relativePath = path.relative(file, from: codegenDir);
       var outputPath = path.join(codegenTestDir, relativePath);
 
diff --git a/pkg/dev_compiler/test/multitest.dart b/pkg/dev_compiler/test/multitest.dart
index c5fcf99..6d9acd7 100644
--- a/pkg/dev_compiler/test/multitest.dart
+++ b/pkg/dev_compiler/test/multitest.dart
@@ -73,8 +73,10 @@
 void extractTestsFromMultitest(String filePath, String contents,
     Map<String, String> tests, Map<String, Set<String>> outcomes) {
   int first_newline = contents.indexOf('\n');
-  final String line_separator = (first_newline == 0 ||
-      contents[first_newline - 1] != '\r') ? '\n' : '\r\n';
+  final String line_separator =
+      (first_newline == 0 || contents[first_newline - 1] != '\r')
+          ? '\n'
+          : '\r\n';
   List<String> lines = contents.split(line_separator);
   if (lines.last == '') lines.removeLast();
   contents = null;
diff --git a/pkg/dev_compiler/test/not_yet_strong_tests.dart b/pkg/dev_compiler/test/not_yet_strong_tests.dart
index f0d4c34..013db81 100644
--- a/pkg/dev_compiler/test/not_yet_strong_tests.dart
+++ b/pkg/dev_compiler/test/not_yet_strong_tests.dart
@@ -517,6 +517,7 @@
   'language/cyclic_class_member_test_01_multi',
   'language/cyclic_constructor_test_01_multi',
   'language/cyclic_default_values_test',
+  'language/cyclic_import_test',
   'language/cyclic_type_variable_test_01_multi',
   'language/cyclic_type_variable_test_02_multi',
   'language/cyclic_type_variable_test_03_multi',
@@ -2427,22 +2428,13 @@
   'lib/convert/line_splitter_test',
   'lib/html/cross_frame_test',
   'lib/html/css_rule_list_test',
-  'lib/html/cssstyledeclaration_test',
-  'lib/html/custom/attribute_changed_callback_test',
   'lib/html/custom/constructor_calls_created_synchronously_test',
   'lib/html/custom/created_callback_test',
   'lib/html/custom/document_register_basic_test',
   'lib/html/custom/document_register_type_extensions_test',
   'lib/html/custom/element_upgrade_test',
-  'lib/html/custom/entered_left_view_test',
-  'lib/html/custom/js_custom_test',
-  'lib/html/custom/mirrors_test',
-  'lib/html/custom/regress_194523002_test',
-  'lib/html/custom_element_method_clash_test',
-  'lib/html/custom_element_name_clash_test',
   'lib/html/custom_elements_23127_test',
   'lib/html/custom_elements_test',
-  'lib/html/custom_tags_test',
   'lib/html/datalistelement_test',
   'lib/html/documentfragment_test',
   'lib/html/element_add_test',
@@ -2456,7 +2448,6 @@
   'lib/html/htmlelement_test',
   'lib/html/htmloptionscollection_test',
   'lib/html/indexeddb_2_test',
-  'lib/html/interactive_test',
   'lib/html/js_function_getter_trust_types_test',
   'lib/html/js_test',
   'lib/html/js_util_test',
@@ -2471,10 +2462,8 @@
   'lib/html/queryall_test',
   'lib/html/resource_http_test',
   'lib/html/selectelement_test',
-  'lib/html/serialized_script_value_test',
   'lib/html/track_element_constructor_test',
   'lib/html/transferables_test',
-  'lib/html/trusted_html_tree_sanitizer_test',
   'lib/html/typed_arrays_range_checks_test',
   'lib/html/typing_test',
   'lib/html/unknownelement_test',
diff --git a/pkg/dev_compiler/tool/build_test_pkgs.sh b/pkg/dev_compiler/tool/build_test_pkgs.sh
index b58855c..5b348e2 100755
--- a/pkg/dev_compiler/tool/build_test_pkgs.sh
+++ b/pkg/dev_compiler/tool/build_test_pkgs.sh
@@ -28,7 +28,8 @@
     -s gen/codegen_output/pkg/path.sum \
     package:stack_trace/stack_trace.dart
 
-./bin/dartdevc.dart $SDK -o gen/codegen_output/pkg/unittest.js \
+./bin/dartdevc.dart $SDK --unsafe-force-compile \
+    -o gen/codegen_output/pkg/unittest.js \
     -s gen/codegen_output/pkg/matcher.sum \
     -s gen/codegen_output/pkg/path.sum \
     -s gen/codegen_output/pkg/stack_trace.sum \
diff --git a/pkg/dev_compiler/tool/format.sh b/pkg/dev_compiler/tool/format.sh
index b4cfc55..01f7e3b 100755
--- a/pkg/dev_compiler/tool/format.sh
+++ b/pkg/dev_compiler/tool/format.sh
@@ -13,4 +13,5 @@
 (files=`git ls-files 'bin/*.dart' 'lib/*.dart' test/*.dart test/checker/*.dart \
   tool/*.dart | grep -v lib/src/js_ast/`; git status -s $files | grep -q . \
   && echo "Did not run the formatter, please commit edited files first." \
-  || (echo "Running dart formatter" ; pub run dart_style:format -w $files))
+  || (echo "Running dart formatter" ; \
+  dart ../../third_party/pkg_tested/dart_style/bin/format.dart -w $files))
diff --git a/pkg/dev_compiler/tool/test.sh b/pkg/dev_compiler/tool/test.sh
index f23dd2f..f32a6ad 100755
--- a/pkg/dev_compiler/tool/test.sh
+++ b/pkg/dev_compiler/tool/test.sh
@@ -36,7 +36,7 @@
 # all_tests twice. Finally self_host_test is not currently being tracked by
 # code coverage.
 unset COVERALLS_TOKEN
-pub run test:test test/all_tests.dart || fail
+dart test/all_tests.dart || fail
 
 {
   fc=`find test -name "*.dart" |\
diff --git a/runtime/observatory/tests/service/debugger_location_second_test.dart b/runtime/observatory/tests/service/debugger_location_second_test.dart
new file mode 100644
index 0000000..b2463ab
--- /dev/null
+++ b/runtime/observatory/tests/service/debugger_location_second_test.dart
@@ -0,0 +1,209 @@
+// 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
+
+import 'package:observatory/service_io.dart';
+import 'package:observatory/debugger.dart';
+import 'package:unittest/unittest.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+import 'dart:async';
+import 'dart:developer';
+
+const int LINE_A = 22;
+const int LINE_B = 110;
+const int LINE_C = 12;
+
+void testFunction() {
+  int i = 0;
+  while (i == 0) {
+    debugger();
+    print('loop');  // Line A.
+    print('loop');
+  }
+}
+
+class TestDebugger extends Debugger {
+  TestDebugger(this.isolate, this.stack);
+
+  VM get vm => isolate.vm;
+  Isolate isolate;
+  ServiceMap stack;
+  int currentFrame = 0;
+}
+
+void debugger_location_dummy_function() {
+}
+
+class DebuggerLocationTestFoo {
+  DebuggerLocationTestFoo(this.field);
+  DebuggerLocationTestFoo.named();
+
+  void method() {}
+  void madness() {}
+
+  int field;
+}
+
+class DebuggerLocationTestBar {
+}
+
+Future<Debugger> initDebugger(Isolate isolate) {
+  return isolate.getStack().then((stack) {
+    return new TestDebugger(isolate, stack);
+  });
+}
+
+var tests = [
+
+hasStoppedAtBreakpoint,
+
+// Load the isolate's libraries
+(Isolate isolate) async {
+  for (var lib in isolate.libraries) {
+    await lib.load();
+  }
+},
+
+// Parse method
+(Isolate isolate) async {
+  var debugger = await initDebugger(isolate);
+  var loc =
+      await DebuggerLocation.parse(debugger, 'DebuggerLocationTestFoo.method');
+  expect(loc.valid, isTrue);
+  expect(loc.toString(), equals('DebuggerLocationTestFoo.method'));
+},
+
+// Parse method
+(Isolate isolate) async {
+  var debugger = await initDebugger(isolate);
+  var loc =
+      await DebuggerLocation.parse(debugger, 'DebuggerLocationTestFoo.field=');
+  expect(loc.valid, isTrue);
+  expect(loc.toString(), equals('DebuggerLocationTestFoo.field='));
+},
+
+// Parse bad method
+(Isolate isolate) async {
+  var debugger = await initDebugger(isolate);
+  var loc =
+    await DebuggerLocation.parse(debugger, 'DebuggerLocationTestFoo.missing');
+  expect(loc.valid, isFalse);
+  expect(loc.toString(), equals(
+      'invalid source location '
+      '(Function \'DebuggerLocationTestFoo.missing\' not found)'));
+},
+
+// Complete function + script
+(Isolate isolate) async {
+  var debugger = await initDebugger(isolate);
+  var completions = await DebuggerLocation.complete(debugger, 'debugger_loc');
+  expect(completions.toString(), equals(
+      '[debugger_location_dummy_function,'
+      ' debugger_location.dart:,'
+      ' debugger_location_second_test.dart:]'));
+},
+
+// Complete class
+(Isolate isolate) async {
+  var debugger = await initDebugger(isolate);
+  var completions =
+      await DebuggerLocation.complete(debugger, 'DebuggerLocationTe');
+  expect(completions.toString(), equals(
+      '[DebuggerLocationTestBar,'
+      ' DebuggerLocationTestFoo]'));
+},
+
+// No completions: unqualified name
+(Isolate isolate) async {
+  var debugger = await initDebugger(isolate);
+  var completions =
+      await DebuggerLocation.complete(debugger, 'debugger_locXYZZY');
+  expect(completions.toString(), equals('[]'));
+},
+
+// Complete method
+(Isolate isolate) async {
+  var debugger = await initDebugger(isolate);
+  var completions =
+      await DebuggerLocation.complete(debugger, 'DebuggerLocationTestFoo.m');
+  expect(completions.toString(), equals(
+      '[DebuggerLocationTestFoo.madness,'
+      ' DebuggerLocationTestFoo.method]'));
+},
+
+// No completions: qualified name
+(Isolate isolate) async {
+  var debugger = await initDebugger(isolate);
+  var completions =
+      await DebuggerLocation.complete(debugger, 'DebuggerLocationTestFoo.q');
+  expect(completions.toString(), equals('[]'));
+},
+
+// Complete script
+(Isolate isolate) async {
+  var debugger = await initDebugger(isolate);
+  var completions =
+      await DebuggerLocation.complete(debugger, 'debugger_location_second_te');
+  expect(completions.toString(), equals(
+      '[debugger_location_second_test.dart:]'));
+},
+
+// Complete script:line
+(Isolate isolate) async {
+  var debugger = await initDebugger(isolate);
+  var completions =
+      await DebuggerLocation.complete(debugger,
+                                      'debugger_location_second_test.dart:11');
+  expect(completions.toString(), equals(
+      '[debugger_location_second_test.dart:${LINE_B + 0} ,'
+      ' debugger_location_second_test.dart:${LINE_B + 0}:,'
+      ' debugger_location_second_test.dart:${LINE_B + 1} ,'
+      ' debugger_location_second_test.dart:${LINE_B + 1}:,'
+      ' debugger_location_second_test.dart:${LINE_B + 2} ,'
+      ' debugger_location_second_test.dart:${LINE_B + 2}:,'
+      ' debugger_location_second_test.dart:${LINE_B + 3} ,'
+      ' debugger_location_second_test.dart:${LINE_B + 3}:,'
+      ' debugger_location_second_test.dart:${LINE_B + 4} ,'
+      ' debugger_location_second_test.dart:${LINE_B + 4}:,'
+      ' debugger_location_second_test.dart:${LINE_B + 5} ,'
+      ' debugger_location_second_test.dart:${LINE_B + 5}:,'
+      ' debugger_location_second_test.dart:${LINE_B + 6} ,'
+      ' debugger_location_second_test.dart:${LINE_B + 6}:,'
+      ' debugger_location_second_test.dart:${LINE_B + 9} ,'
+      ' debugger_location_second_test.dart:${LINE_B + 9}:]'));
+},
+
+// Complete script:line:col
+(Isolate isolate) async {
+  var debugger = await initDebugger(isolate);
+  var completions =
+      await DebuggerLocation.complete(
+          debugger,
+          'debugger_location_second_test.dart:$LINE_C:2');
+  expect(completions.toString(), equals(
+      '[debugger_location_second_test.dart:$LINE_C:2 ,'
+      ' debugger_location_second_test.dart:$LINE_C:20 ,'
+      ' debugger_location_second_test.dart:$LINE_C:21 ,'
+      ' debugger_location_second_test.dart:$LINE_C:22 ,'
+      ' debugger_location_second_test.dart:$LINE_C:23 ,'
+      ' debugger_location_second_test.dart:$LINE_C:24 ]'));
+},
+
+// Complete without the script name.
+(Isolate isolate) async {
+  var debugger = await initDebugger(isolate);
+  var completions = await DebuggerLocation.complete(debugger, '$LINE_C:2');
+  expect(completions.toString(), equals(
+      '[debugger_location_second_test.dart:$LINE_C:2 ,'
+      ' debugger_location_second_test.dart:$LINE_C:20 ,'
+      ' debugger_location_second_test.dart:$LINE_C:21 ,'
+      ' debugger_location_second_test.dart:$LINE_C:22 ,'
+      ' debugger_location_second_test.dart:$LINE_C:23 ,'
+      ' debugger_location_second_test.dart:$LINE_C:24 ]'));
+},
+
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
diff --git a/runtime/observatory/tests/service/debugger_location_test.dart b/runtime/observatory/tests/service/debugger_location_test.dart
index 53ed4fb..a637a83 100644
--- a/runtime/observatory/tests/service/debugger_location_test.dart
+++ b/runtime/observatory/tests/service/debugger_location_test.dart
@@ -150,139 +150,6 @@
       'DebuggerLocationTestFoo.DebuggerLocationTestFoo.named'));
 },
 
-// Parse method
-(Isolate isolate) async {
-  var debugger = await initDebugger(isolate);
-  var loc =
-      await DebuggerLocation.parse(debugger, 'DebuggerLocationTestFoo.method');
-  expect(loc.valid, isTrue);
-  expect(loc.toString(), equals('DebuggerLocationTestFoo.method'));
-},
-
-// Parse method
-(Isolate isolate) async {
-  var debugger = await initDebugger(isolate);
-  var loc =
-      await DebuggerLocation.parse(debugger, 'DebuggerLocationTestFoo.field=');
-  expect(loc.valid, isTrue);
-  expect(loc.toString(), equals('DebuggerLocationTestFoo.field='));
-},
-
-// Parse bad method
-(Isolate isolate) async {
-  var debugger = await initDebugger(isolate);
-  var loc =
-    await DebuggerLocation.parse(debugger, 'DebuggerLocationTestFoo.missing');
-  expect(loc.valid, isFalse);
-  expect(loc.toString(), equals(
-      'invalid source location '
-      '(Function \'DebuggerLocationTestFoo.missing\' not found)'));
-},
-
-// Complete function + script
-(Isolate isolate) async {
-  var debugger = await initDebugger(isolate);
-  var completions = await DebuggerLocation.complete(debugger, 'debugger_loc');
-  expect(completions.toString(), equals(
-      '[debugger_location_dummy_function,'
-      ' debugger_location.dart:,'
-      ' debugger_location_test.dart:]'));
-},
-
-// Complete class
-(Isolate isolate) async {
-  var debugger = await initDebugger(isolate);
-  var completions =
-      await DebuggerLocation.complete(debugger, 'DebuggerLocationTe');
-  expect(completions.toString(), equals(
-      '[DebuggerLocationTestBar,'
-      ' DebuggerLocationTestFoo]'));
-},
-
-// No completions: unqualified name
-(Isolate isolate) async {
-  var debugger = await initDebugger(isolate);
-  var completions =
-      await DebuggerLocation.complete(debugger, 'debugger_locXYZZY');
-  expect(completions.toString(), equals('[]'));
-},
-
-// Complete method
-(Isolate isolate) async {
-  var debugger = await initDebugger(isolate);
-  var completions =
-      await DebuggerLocation.complete(debugger, 'DebuggerLocationTestFoo.m');
-  expect(completions.toString(), equals(
-      '[DebuggerLocationTestFoo.madness,'
-      ' DebuggerLocationTestFoo.method]'));
-},
-
-// No completions: qualified name
-(Isolate isolate) async {
-  var debugger = await initDebugger(isolate);
-  var completions =
-      await DebuggerLocation.complete(debugger, 'DebuggerLocationTestFoo.q');
-  expect(completions.toString(), equals('[]'));
-},
-
-// Complete script
-(Isolate isolate) async {
-  var debugger = await initDebugger(isolate);
-  var completions =
-      await DebuggerLocation.complete(debugger, 'debugger_location_te');
-  expect(completions.toString(), equals(
-      '[debugger_location_test.dart:]'));
-},
-
-// Complete script:line
-(Isolate isolate) async {
-  var debugger = await initDebugger(isolate);
-  var completions =
-      await DebuggerLocation.complete(debugger,
-                                      'debugger_location_test.dart:11');
-  expect(completions.toString(), equals(
-      '[debugger_location_test.dart:${LINE_B + 0} ,'
-      ' debugger_location_test.dart:${LINE_B + 0}:,'
-      ' debugger_location_test.dart:${LINE_B + 1} ,'
-      ' debugger_location_test.dart:${LINE_B + 1}:,'
-      ' debugger_location_test.dart:${LINE_B + 2} ,'
-      ' debugger_location_test.dart:${LINE_B + 2}:,'
-      ' debugger_location_test.dart:${LINE_B + 3} ,'
-      ' debugger_location_test.dart:${LINE_B + 3}:,'
-      ' debugger_location_test.dart:${LINE_B + 4} ,'
-      ' debugger_location_test.dart:${LINE_B + 4}:,'
-      ' debugger_location_test.dart:${LINE_B + 5} ,'
-      ' debugger_location_test.dart:${LINE_B + 5}:]'));
-},
-
-// Complete script:line:col
-(Isolate isolate) async {
-  var debugger = await initDebugger(isolate);
-  var completions =
-      await DebuggerLocation.complete(debugger,
-                                      'debugger_location_test.dart:$LINE_C:2');
-  expect(completions.toString(), equals(
-      '[debugger_location_test.dart:$LINE_C:2 ,'
-      ' debugger_location_test.dart:$LINE_C:20 ,'
-      ' debugger_location_test.dart:$LINE_C:21 ,'
-      ' debugger_location_test.dart:$LINE_C:22 ,'
-      ' debugger_location_test.dart:$LINE_C:23 ,'
-      ' debugger_location_test.dart:$LINE_C:24 ]'));
-},
-
-// Complete without the script name.
-(Isolate isolate) async {
-  var debugger = await initDebugger(isolate);
-  var completions = await DebuggerLocation.complete(debugger, '$LINE_C:2');
-  expect(completions.toString(), equals(
-      '[debugger_location_test.dart:$LINE_C:2 ,'
-      ' debugger_location_test.dart:$LINE_C:20 ,'
-      ' debugger_location_test.dart:$LINE_C:21 ,'
-      ' debugger_location_test.dart:$LINE_C:22 ,'
-      ' debugger_location_test.dart:$LINE_C:23 ,'
-      ' debugger_location_test.dart:$LINE_C:24 ]'));
-},
-
 ];
 
 main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
diff --git a/runtime/observatory/tests/service/get_allocation_profile_rpc_test.dart b/runtime/observatory/tests/service/get_allocation_profile_rpc_test.dart
index 2af7ffe..6d7b8fd 100644
--- a/runtime/observatory/tests/service/get_allocation_profile_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_allocation_profile_rpc_test.dart
@@ -46,7 +46,7 @@
     expect(result['members'].length, isPositive);
     expect(result['members'][0]['type'], equals('ClassHeapStats'));
 
-    await sleep(10);
+    await sleep(1000);
 
     result = await isolate.invokeRpcNoUpgrade('_getAllocationProfile', params);
     var secondReset = result['dateLastAccumulatorReset'];
@@ -67,7 +67,7 @@
     expect(result['members'].length, isPositive);
     expect(result['members'][0]['type'], equals('ClassHeapStats'));
 
-    await sleep(10);
+    await sleep(1000);
 
     result = await isolate.invokeRpcNoUpgrade('_getAllocationProfile', params);
     var secondGC = result['dateLastAccumulatorReset'];
diff --git a/runtime/observatory/tests/service/service.status b/runtime/observatory/tests/service/service.status
index e3cc4de..0c6e7dc 100644
--- a/runtime/observatory/tests/service/service.status
+++ b/runtime/observatory/tests/service/service.status
@@ -7,13 +7,17 @@
 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
 evaluate_activation_test/scope: RuntimeError # http://dartbug.com/20047
 isolate_lifecycle_test: Pass, RuntimeError # Issue 24174
 
+# Debugger location tests are slow in debug mode.
+[ $mode == debug ]
+debugger_location_second_test: Pass, Slow
+debugger_location_test: Pass, Slow
+
 # Disable on simulators.
 [ $arch == simarm || $arch == simmips || $arch == simarm64 ]
 *: SkipSlow
diff --git a/runtime/observatory/tests/service/test_helper.dart b/runtime/observatory/tests/service/test_helper.dart
index 858a233..63b8fc2 100644
--- a/runtime/observatory/tests/service/test_helper.dart
+++ b/runtime/observatory/tests/service/test_helper.dart
@@ -226,11 +226,11 @@
           first = false;
           print('** Signaled to run test queries on $portNumber');
         }
-        print(line);
+        print('>testee>out> $line');
       });
       process.stderr.transform(UTF8.decoder)
                     .transform(new LineSplitter()).listen((line) {
-        print(line);
+        print('>testee>err> $line');
       });
       process.exitCode.then((exitCode) {
         if ((exitCode != 0) && !killedByTester) {
diff --git a/runtime/vm/BUILD.gn b/runtime/vm/BUILD.gn
index 225afdf..2f0a5ed 100644
--- a/runtime/vm/BUILD.gn
+++ b/runtime/vm/BUILD.gn
@@ -202,6 +202,7 @@
         output = "$target_gen_dir/${filename}_patch_gen.cc"
       }
     }
+    lib_sources_gypi = {}
     lib_sources_gypi =
         exec_script("../../tools/gypi_to_gn.py",
                     [rebase_path("../lib/${filename}_sources.gypi")],
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 7fce179..3b1f79e 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -1598,7 +1598,8 @@
 #endif
       code->ptr()->state_bits_ = d->Read<int32_t>();
 #if !defined(DART_PRECOMPILED_RUNTIME)
-      code->ptr()->lazy_deopt_pc_offset_ = -1;
+      code->ptr()->lazy_deopt_return_pc_offset_ = -1;
+      code->ptr()->lazy_deopt_throw_pc_offset_ = -1;
 #endif
     }
   }
@@ -4312,7 +4313,7 @@
   return NULL;
 #else
   Zone* Z = zone_;
-  if ((cid > kNumPredefinedCids) ||
+  if ((cid >= kNumPredefinedCids) ||
       (cid == kInstanceCid) ||
       RawObject::IsTypedDataViewClassId(cid)) {
     Push(isolate()->class_table()->At(cid));
@@ -4636,7 +4637,7 @@
   intptr_t cid = ReadCid();
 
   Zone* Z = zone_;
-  if ((cid > kNumPredefinedCids) ||
+  if ((cid >= kNumPredefinedCids) ||
       (cid == kInstanceCid) ||
       RawObject::IsTypedDataViewClassId(cid)) {
     return new (Z) InstanceDeserializationCluster(cid);
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index ee94ebf..6bfbdb8 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -2020,20 +2020,22 @@
   }
   // Patch call site (lazy deoptimization is quite rare, patching it twice
   // is not a performance issue).
-  uword lazy_deopt_jump = optimized_code.GetLazyDeoptPc();
+  uword lazy_deopt_jump_return = optimized_code.GetLazyDeoptReturnPc();
+  uword lazy_deopt_jump_throw = optimized_code.GetLazyDeoptThrowPc();
 #if !defined(TARGET_ARCH_DBC)
-  ASSERT(lazy_deopt_jump != 0);
+  ASSERT(lazy_deopt_jump_return != 0);
+  ASSERT(lazy_deopt_jump_throw != 0);
 #endif
   const Instructions& instrs =
       Instructions::Handle(zone, optimized_code.instructions());
   {
     WritableInstructionsScope writable(instrs.PayloadStart(), instrs.size());
-    CodePatcher::InsertDeoptimizationCallAt(pc, lazy_deopt_jump);
+    CodePatcher::InsertDeoptimizationCallAt(pc, lazy_deopt_jump_return);
     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());
+          pc, lazy_deopt_jump_return, name.ToCString());
     }
     const ExceptionHandlers& handlers =
         ExceptionHandlers::Handle(zone, optimized_code.exception_handlers());
@@ -2041,7 +2043,7 @@
     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);
+      CodePatcher::InsertDeoptimizationCallAt(patch_pc, lazy_deopt_jump_throw);
       if (FLAG_trace_patching) {
         OS::PrintErr("  at handler 0x%" Px "\n", patch_pc);
       }
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index 25fad98..3972b33 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -1341,14 +1341,10 @@
     }
 
     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);
     }
 
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index c1a2f36..f6f3ab8 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -616,7 +616,7 @@
   RawObject* raw_obj = arguments->NativeArg0();
   if (raw_obj->IsHeapObject()) {
     intptr_t cid = raw_obj->GetClassId();
-    if (cid > kNumPredefinedCids) {
+    if (cid >= kNumPredefinedCids) {
       ASSERT(Instance::Cast(Object::Handle(raw_obj)).IsValidNativeIndex(0));
       RawTypedData* native_fields = *reinterpret_cast<RawTypedData**>(
           RawObject::ToAddr(raw_obj) + sizeof(RawObject));
@@ -701,7 +701,7 @@
   RawObject* raw_obj = arguments->NativeArgAt(arg_index);
   if (raw_obj->IsHeapObject()) {
     intptr_t cid = raw_obj->GetClassId();
-    if (cid > kNumPredefinedCids) {
+    if (cid >= kNumPredefinedCids) {
       RawTypedData* native_fields = *reinterpret_cast<RawTypedData**>(
           RawObject::ToAddr(raw_obj) + sizeof(RawObject));
       if (native_fields == TypedData::null()) {
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index c9e7769..f78dc3c 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -243,6 +243,10 @@
   allocation_args.SetAt(3, Bool::False());  // Not a super invocation.
   const Object& invocation_mirror = Object::Handle(
       InvokeFunction(allocation_function, allocation_args));
+  if (invocation_mirror.IsError()) {
+    Exceptions::PropagateError(Error::Cast(invocation_mirror));
+    UNREACHABLE();
+  }
 
   // Now use the invocation mirror object and invoke NoSuchMethod.
   const int kNumArguments = 2;
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index e658740..18aa1a1 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -697,7 +697,7 @@
     function ^= deopt_context->ObjectAt(object_table_index_);
     if (function.IsNull()) {
       *reinterpret_cast<RawObject**>(dest_addr) = deopt_context->is_lazy_deopt()
-          ? StubCode::DeoptimizeLazy_entry()->code()
+          ? StubCode::DeoptimizeLazyFromReturn_entry()->code()
           : StubCode::Deoptimize_entry()->code();
       return;
     }
diff --git a/runtime/vm/disassembler.cc b/runtime/vm/disassembler.cc
index abf9c84..1b62540 100644
--- a/runtime/vm/disassembler.cc
+++ b/runtime/vm/disassembler.cc
@@ -165,6 +165,10 @@
 
 void Disassembler::DisassembleCodeHelper(
     const char* function_fullname, const Code& code, bool optimized) {
+  LocalVarDescriptors& var_descriptors = LocalVarDescriptors::Handle();
+  if (FLAG_print_variable_descriptors) {
+    var_descriptors = code.GetLocalVarDescriptors();
+  }
   THR_Print("Code for %sfunction '%s' {\n",
             optimized ? "optimized " : "",
             function_fullname);
@@ -232,8 +236,6 @@
   if (FLAG_print_variable_descriptors) {
     THR_Print("Variable Descriptors for function '%s' {\n",
               function_fullname);
-    const LocalVarDescriptors& var_descriptors =
-        LocalVarDescriptors::Handle(code.GetLocalVarDescriptors());
     intptr_t var_desc_length =
         var_descriptors.IsNull() ? 0 : var_descriptors.Length();
     String& var_name = String::Handle();
@@ -283,10 +285,9 @@
         Class& cls = Class::Handle();
         cls ^= code.owner();
         if (cls.IsNull()) {
-          const String& code_name = String::Handle(code.Name());
           THR_Print("  0x%" Px ": %s, %p\n",
               start + offset.Value(),
-              code_name.ToCString(),
+              code.Name(),
               code.raw());
         } else {
           THR_Print("  0x%" Px ": allocation stub for %s, %p\n",
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index 4e0d2c7..46a54562 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -225,7 +225,8 @@
                 LookupClass(Symbols::List()))),
         parallel_move_resolver_(this),
         pending_deoptimization_env_(NULL),
-        lazy_deopt_pc_offset_(Code::kInvalidPc),
+        lazy_deopt_return_pc_offset_(Code::kInvalidPc),
+        lazy_deopt_throw_pc_offset_(Code::kInvalidPc),
         deopt_id_to_ic_data_(NULL),
         edge_counters_array_(Array::ZoneHandle()),
         inlined_code_intervals_(Array::ZoneHandle(Object::empty_array().raw())),
@@ -1030,7 +1031,8 @@
       pc_descriptors_list_->FinalizePcDescriptors(code.PayloadStart()));
   if (!is_optimizing_) descriptors.Verify(parsed_function_.function());
   code.set_pc_descriptors(descriptors);
-  code.set_lazy_deopt_pc_offset(lazy_deopt_pc_offset_);
+  code.set_lazy_deopt_return_pc_offset(lazy_deopt_return_pc_offset_);
+  code.set_lazy_deopt_throw_pc_offset(lazy_deopt_throw_pc_offset_);
 }
 
 
@@ -1174,9 +1176,10 @@
 
   EnterIntrinsicMode();
 
-  Intrinsifier::Intrinsify(parsed_function(), this);
+  bool complete = Intrinsifier::Intrinsify(parsed_function(), this);
 
   ExitIntrinsicMode();
+
   // "Deoptimization" from intrinsic continues here. All deoptimization
   // branches from intrinsic code redirect to here where the slow-path
   // (normal function body) starts.
@@ -1184,7 +1187,7 @@
   // before any deoptimization point.
   ASSERT(!intrinsic_slow_path_label_.IsBound());
   assembler()->Bind(&intrinsic_slow_path_label_);
-  return false;
+  return complete;
 }
 
 
diff --git a/runtime/vm/flow_graph_compiler.h b/runtime/vm/flow_graph_compiler.h
index 31a627a..796c1f2 100644
--- a/runtime/vm/flow_graph_compiler.h
+++ b/runtime/vm/flow_graph_compiler.h
@@ -819,7 +819,8 @@
   // In future AddDeoptStub should be moved out of the instruction template.
   Environment* pending_deoptimization_env_;
 
-  intptr_t lazy_deopt_pc_offset_;
+  intptr_t lazy_deopt_return_pc_offset_;
+  intptr_t lazy_deopt_throw_pc_offset_;
 
   ZoneGrowableArray<const ICData*>* deopt_id_to_ic_data_;
 
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index 38db33b..0b7fd3d 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -1127,15 +1127,16 @@
 
   BeginCodeSourceRange();
   if (is_optimizing() && !FLAG_precompiled_mode) {
-    // Leave enough space for patching in case of lazy deoptimization from
-    // deferred code.
+    // Leave enough space for patching in case of lazy deoptimization.
     for (intptr_t i = 0;
          i < CallPattern::DeoptCallPatternLengthInInstructions();
          ++i) {
       __ nop();
     }
-    lazy_deopt_pc_offset_ = assembler()->CodeSize();
-    __ Branch(*StubCode::DeoptimizeLazy_entry());
+    lazy_deopt_return_pc_offset_ = assembler()->CodeSize();
+    __ Branch(*StubCode::DeoptimizeLazyFromReturn_entry());
+    lazy_deopt_throw_pc_offset_ = assembler()->CodeSize();
+    __ Branch(*StubCode::DeoptimizeLazyFromThrow_entry());
   }
   EndCodeSourceRange(TokenPosition::kDartCodeEpilogue);
 }
diff --git a/runtime/vm/flow_graph_compiler_arm64.cc b/runtime/vm/flow_graph_compiler_arm64.cc
index 2634ae2b..10ff57f 100644
--- a/runtime/vm/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/flow_graph_compiler_arm64.cc
@@ -1121,15 +1121,16 @@
 
   BeginCodeSourceRange();
   if (is_optimizing() && !FLAG_precompiled_mode) {
-    // Leave enough space for patching in case of lazy deoptimization from
-    // deferred code.
+    // Leave enough space for patching in case of lazy deoptimization.
     for (intptr_t i = 0;
       i < CallPattern::kDeoptCallLengthInInstructions;
       ++i) {
       __ orr(R0, ZR, Operand(R0));  // nop
     }
-    lazy_deopt_pc_offset_ = assembler()->CodeSize();
-    __ BranchPatchable(*StubCode::DeoptimizeLazy_entry());
+    lazy_deopt_return_pc_offset_ = assembler()->CodeSize();
+    __ BranchPatchable(*StubCode::DeoptimizeLazyFromReturn_entry());
+    lazy_deopt_throw_pc_offset_ = assembler()->CodeSize();
+    __ BranchPatchable(*StubCode::DeoptimizeLazyFromThrow_entry());
   }
   EndCodeSourceRange(TokenPosition::kDartCodeEpilogue);
 }
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index 90ec1f2..6d823d1 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -1138,11 +1138,12 @@
 
   BeginCodeSourceRange();
   if (is_optimizing() && !FLAG_precompiled_mode) {
-    // Leave enough space for patching in case of lazy deoptimization from
-    // deferred code.
+    // Leave enough space for patching in case of lazy deoptimization.
     __ nop(CallPattern::pattern_length_in_bytes());
-    lazy_deopt_pc_offset_ = assembler()->CodeSize();
-    __ Jmp(*StubCode::DeoptimizeLazy_entry());
+    lazy_deopt_return_pc_offset_ = assembler()->CodeSize();
+    __ Jmp(*StubCode::DeoptimizeLazyFromReturn_entry());
+    lazy_deopt_throw_pc_offset_ = assembler()->CodeSize();
+    __ Jmp(*StubCode::DeoptimizeLazyFromThrow_entry());
   }
   EndCodeSourceRange(TokenPosition::kDartCodeEpilogue);
 }
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index fb3eadb..07117a2 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -1141,15 +1141,16 @@
 
   BeginCodeSourceRange();
   if (is_optimizing() && !FLAG_precompiled_mode) {
-    // Leave enough space for patching in case of lazy deoptimization from
-    // deferred code.
+    // Leave enough space for patching in case of lazy deoptimization.
     for (intptr_t i = 0;
       i < CallPattern::kDeoptCallLengthInInstructions;
       ++i) {
       __ nop();
     }
-    lazy_deopt_pc_offset_ = assembler()->CodeSize();
-    __ Branch(*StubCode::DeoptimizeLazy_entry());
+    lazy_deopt_return_pc_offset_ = assembler()->CodeSize();
+    __ Branch(*StubCode::DeoptimizeLazyFromReturn_entry());
+    lazy_deopt_throw_pc_offset_ = assembler()->CodeSize();
+    __ Branch(*StubCode::DeoptimizeLazyFromThrow_entry());
   }
   EndCodeSourceRange(TokenPosition::kDartCodeEpilogue);
 }
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index 0c0444a..67223b5 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -1140,11 +1140,12 @@
 
   BeginCodeSourceRange();
   if (is_optimizing() && !FLAG_precompiled_mode) {
-    // Leave enough space for patching in case of lazy deoptimization from
-    // deferred code.
+    // Leave enough space for patching in case of lazy deoptimization.
     __ nop(ShortCallPattern::pattern_length_in_bytes());
-    lazy_deopt_pc_offset_ = assembler()->CodeSize();
-    __ Jmp(*StubCode::DeoptimizeLazy_entry(), PP);
+    lazy_deopt_return_pc_offset_ = assembler()->CodeSize();
+    __ Jmp(*StubCode::DeoptimizeLazyFromReturn_entry(), PP);
+    lazy_deopt_throw_pc_offset_ = assembler()->CodeSize();
+    __ Jmp(*StubCode::DeoptimizeLazyFromThrow_entry(), PP);
   }
   EndCodeSourceRange(TokenPosition::kDartCodeEpilogue);
 }
diff --git a/runtime/vm/intrinsifier.cc b/runtime/vm/intrinsifier.cc
index 02c469d..e0355c9 100644
--- a/runtime/vm/intrinsifier.cc
+++ b/runtime/vm/intrinsifier.cc
@@ -215,16 +215,17 @@
 }
 
 
-void Intrinsifier::Intrinsify(const ParsedFunction& parsed_function,
+// Returns true if fall-through code can be omitted.
+bool Intrinsifier::Intrinsify(const ParsedFunction& parsed_function,
                               FlowGraphCompiler* compiler) {
   const Function& function = parsed_function.function();
   if (!CanIntrinsify(function)) {
-    return;
+    return false;
   }
 
   ASSERT(!compiler->flow_graph().IsCompiledForOsr());
   if (GraphIntrinsify(parsed_function, compiler)) {
-    return;
+    return compiler->intrinsic_slow_path_label()->IsUnused();
   }
 
 #define EMIT_CASE(class_name, function_name, enum_name, type, fp)              \
@@ -255,6 +256,7 @@
 #endif
 
 #undef EMIT_INTRINSIC
+  return false;
 }
 
 
diff --git a/runtime/vm/intrinsifier.h b/runtime/vm/intrinsifier.h
index 100dee4..7226d3ac 100644
--- a/runtime/vm/intrinsifier.h
+++ b/runtime/vm/intrinsifier.h
@@ -21,7 +21,7 @@
 
 class Intrinsifier : public AllStatic {
  public:
-  static void Intrinsify(const ParsedFunction& parsed_function,
+  static bool Intrinsify(const ParsedFunction& parsed_function,
                          FlowGraphCompiler* compiler);
 #if defined(DART_NO_SNAPSHOT)
   static void InitializeState();
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index a368c52..6f0f164 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -11925,8 +11925,8 @@
 void CodeSourceMap::Dump(const CodeSourceMap& code_source_map,
                          const Code& code,
                          const Function& function) {
-  const String& code_name = String::Handle(code.QualifiedName());
-  THR_Print("Dumping Code Source Map for %s\n", code_name.ToCString());
+  const char* code_name = code.QualifiedName();
+  THR_Print("Dumping Code Source Map for %s\n", code_name);
   if (code_source_map.Length() == 0) {
     THR_Print("<empty>\n");
     return;
@@ -11949,7 +11949,7 @@
       THR_Print("%#-*" Px "\t%s\t%s\n", addr_width,
                 pc_offset,
                 tp.ToCString(),
-                code_name.ToCString());
+                code_name);
       continue;
     }
     const String& uri = String::Handle(current_script.url());
@@ -14229,7 +14229,8 @@
     result.set_is_alive(false);
     result.set_comments(Comments::New(0));
     result.set_compile_timestamp(0);
-    result.set_lazy_deopt_pc_offset(kInvalidPc);
+    result.set_lazy_deopt_return_pc_offset(kInvalidPc);
+    result.set_lazy_deopt_throw_pc_offset(kInvalidPc);
     result.set_pc_descriptors(Object::empty_descriptors());
   }
   return result.raw();
@@ -14444,7 +14445,7 @@
 }
 
 
-RawString* Code::Name() const {
+const char* Code::Name() const {
   const Object& obj = Object::Handle(owner());
   if (obj.IsNull()) {
     // Regular stub.
@@ -14454,7 +14455,7 @@
     ASSERT(name != NULL);
     char* stub_name = OS::SCreate(zone,
         "%s%s", Symbols::StubPrefix().ToCString(), name);
-    return Symbols::New(thread, stub_name, strlen(stub_name));
+    return stub_name;
   } else if (obj.IsClass()) {
     // Allocation stub.
     Thread* thread = Thread::Current();
@@ -14462,19 +14463,23 @@
     const Class& cls = Class::Cast(obj);
     String& cls_name = String::Handle(zone, cls.ScrubbedName());
     ASSERT(!cls_name.IsNull());
-    return Symbols::FromConcat(thread, Symbols::AllocationStubFor(), cls_name);
+    char* stub_name = OS::SCreate(zone,
+        "%s%s", Symbols::AllocationStubFor().ToCString(), cls_name.ToCString());
+    return stub_name;
   } else {
     ASSERT(obj.IsFunction());
     // Dart function.
-    return Function::Cast(obj).UserVisibleName();  // Same as scrubbed name.
+    // Same as scrubbed name.
+    return String::Handle(Function::Cast(obj).UserVisibleName()).ToCString();
   }
 }
 
 
-RawString* Code::QualifiedName() const {
+const char* Code::QualifiedName() const {
   const Object& obj = Object::Handle(owner());
   if (obj.IsFunction()) {
-    return Function::Cast(obj).QualifiedScrubbedName();
+    return String::Handle(
+        Function::Cast(obj).QualifiedScrubbedName()).ToCString();
   }
   return Name();
 }
@@ -14539,9 +14544,15 @@
 }
 
 
-uword Code::GetLazyDeoptPc() const {
-  return (lazy_deopt_pc_offset() != kInvalidPc)
-      ? PayloadStart() + lazy_deopt_pc_offset() : 0;
+uword Code::GetLazyDeoptReturnPc() const {
+  return (lazy_deopt_return_pc_offset() != kInvalidPc)
+      ? PayloadStart() + lazy_deopt_return_pc_offset() : 0;
+}
+
+
+uword Code::GetLazyDeoptThrowPc() const {
+  return (lazy_deopt_throw_pc_offset() != kInvalidPc)
+      ? PayloadStart() + lazy_deopt_throw_pc_offset() : 0;
 }
 
 
@@ -16374,32 +16385,6 @@
 }
 
 
-// Same as user visible name, but including the URI of each occuring type.
-// Used to report errors involving types with identical names.
-//
-// e.g.
-//   MyClass<String>     -> MyClass<String> where
-//                            MyClass is from my_uri
-//                            String is from dart:core
-//   MyClass<dynamic, T> -> MyClass<dynamic, T> where
-//                            MyClass is from my_uri
-//                            T of OtherClass is from other_uri
-//   (MyClass) => int    -> (MyClass) => int where
-//                            MyClass is from my_uri
-//                            int is from dart:core
-RawString* AbstractType::UserVisibleNameWithURI() const {
-  Thread* thread = Thread::Current();
-  Zone* zone = thread->zone();
-  GrowableHandlePtrArray<const String> pieces(zone, 3);
-  pieces.Add(String::Handle(zone, BuildName(kUserVisibleName)));
-  if (!IsDynamicType() && !IsVoidType()) {
-    pieces.Add(Symbols::SpaceWhereNewLine());
-    pieces.Add(String::Handle(zone, EnumerateURIs()));
-  }
-  return Symbols::FromConcatAll(thread, pieces);
-}
-
-
 RawString* AbstractType::ClassName() const {
   ASSERT(!IsFunctionType());
   if (HasResolvedTypeClass()) {
@@ -20478,7 +20463,7 @@
 }
 
 
-RawString* String::EncodeIRI(const String& str) {
+const char* String::EncodeIRI(const String& str) {
   const intptr_t len = Utf8::Length(str);
   Zone* zone = Thread::Current()->zone();
   uint8_t* utf8 = zone->Alloc<uint8_t>(len);
@@ -20490,27 +20475,22 @@
       num_escapes += 2;
     }
   }
-  const String& dststr = String::Handle(
-      OneByteString::New(len + num_escapes, Heap::kNew));
-  {
-    intptr_t index = 0;
-    for (int i = 0; i < len; ++i) {
-      uint8_t byte = utf8[i];
-      if (!IsURISafeCharacter(byte)) {
-        OneByteString::SetCharAt(dststr, index, '%');
-        OneByteString::SetCharAt(dststr, index + 1,
-                                 GetHexCharacter(byte >> 4));
-        OneByteString::SetCharAt(dststr, index + 2,
-                                 GetHexCharacter(byte & 0xF));
-        index += 3;
-      } else {
-        ASSERT(byte <= 127);
-        OneByteString::SetCharAt(dststr, index, byte);
-        index += 1;
-      }
+  intptr_t cstr_len = len + num_escapes + 1;
+  char* cstr = zone->Alloc<char>(cstr_len);
+  intptr_t index = 0;
+  for (int i = 0; i < len; ++i) {
+    uint8_t byte = utf8[i];
+    if (!IsURISafeCharacter(byte)) {
+      cstr[index++] = '%';
+      cstr[index++] = GetHexCharacter(byte >> 4);
+      cstr[index++] = GetHexCharacter(byte & 0xF);
+    } else {
+      ASSERT(byte <= 127);
+      cstr[index++] = byte;
     }
   }
-  return dststr.raw();
+  cstr[index] = '\0';
+  return cstr;
 }
 
 
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index fbc72e2..3ce365b 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -4922,14 +4922,15 @@
     kInvalidPc = -1
   };
 
-  uword GetLazyDeoptPc() const;
+  uword GetLazyDeoptReturnPc() const;
+  uword GetLazyDeoptThrowPc() const;
 
   // Find pc, return 0 if not found.
   uword GetPcForDeoptId(intptr_t deopt_id, RawPcDescriptors::Kind kind) const;
   intptr_t GetDeoptIdForOsr(uword pc) const;
 
-  RawString* Name() const;
-  RawString* QualifiedName() const;
+  const char* Name() const;
+  const char* QualifiedName() const;
 
   int64_t compile_timestamp() const {
 #if defined(DART_PRECOMPILED_RUNTIME)
@@ -4939,18 +4940,32 @@
 #endif
   }
 
-  intptr_t lazy_deopt_pc_offset() const {
+  intptr_t lazy_deopt_return_pc_offset() const {
 #if defined(DART_PRECOMPILED_RUNTIME)
     return 0;
 #else
-    return raw_ptr()->lazy_deopt_pc_offset_;
+    return raw_ptr()->lazy_deopt_return_pc_offset_;
 #endif
   }
-  void set_lazy_deopt_pc_offset(intptr_t pc) const {
+  void set_lazy_deopt_return_pc_offset(intptr_t pc) const {
 #if defined(DART_PRECOMPILED_RUNTIME)
     UNREACHABLE();
 #else
-    StoreNonPointer(&raw_ptr()->lazy_deopt_pc_offset_, pc);
+    StoreNonPointer(&raw_ptr()->lazy_deopt_return_pc_offset_, pc);
+#endif
+  }
+  intptr_t lazy_deopt_throw_pc_offset() const {
+#if defined(DART_PRECOMPILED_RUNTIME)
+    return 0;
+#else
+    return raw_ptr()->lazy_deopt_throw_pc_offset_;
+#endif
+  }
+  void set_lazy_deopt_throw_pc_offset(intptr_t pc) const {
+#if defined(DART_PRECOMPILED_RUNTIME)
+    UNREACHABLE();
+#else
+    StoreNonPointer(&raw_ptr()->lazy_deopt_throw_pc_offset_, pc);
 #endif
   }
 
@@ -5806,10 +5821,6 @@
     return BuildName(kUserVisibleName);
   }
 
-  // Same as user visible name, but including the URI of each occuring type.
-  // Used to report errors involving types with identical names.
-  virtual RawString* UserVisibleNameWithURI() const;
-
   // Returns a formatted list of occuring types with their URI.
   virtual RawString* EnumerateURIs() const;
 
@@ -6965,7 +6976,7 @@
   static RawString* EscapeSpecialCharacters(const String& str);
   // Encodes 'str' for use in an Internationalized Resource Identifier (IRI),
   // a generalization of URI (percent-encoding). See RFC 3987.
-  static RawString* EncodeIRI(const String& str);
+  static const char* EncodeIRI(const String& str);
   // Returns null if 'str' is not a valid encoding.
   static RawString* DecodeIRI(const String& str);
   static RawString* Concat(const String& str1,
diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc
index bb0bb26..578d97a 100644
--- a/runtime/vm/object_service.cc
+++ b/runtime/vm/object_service.cc
@@ -15,11 +15,11 @@
 #ifndef PRODUCT
 
 static void AddNameProperties(JSONObject* jsobj,
-                              const String& name,
-                              const String& vm_name) {
-  jsobj->AddProperty("name", name.ToCString());
-  if (!name.Equals(vm_name)) {
-    jsobj->AddProperty("_vmName", vm_name.ToCString());
+                              const char* name,
+                              const char* vm_name) {
+  jsobj->AddProperty("name", name);
+  if (strcmp(name, vm_name) != 0) {
+    jsobj->AddProperty("_vmName", vm_name);
   }
 }
 
@@ -87,7 +87,9 @@
   jsobj.AddFixedServiceId("classes/%" Pd "", id());
   const String& scrubbed_name = String::Handle(ScrubbedName());
   const String& vm_name = String::Handle(Name());
-  AddNameProperties(&jsobj, scrubbed_name, vm_name);
+  AddNameProperties(&jsobj,
+                    scrubbed_name.ToCString(),
+                    vm_name.ToCString());
   if (ref) {
     return;
   }
@@ -202,7 +204,7 @@
   jsobj.AddServiceId(*this);
   const String& user_name = String::Handle(UserVisibleName());
   const String& vm_name = String::Handle(Name());
-  AddNameProperties(&jsobj, user_name, vm_name);
+  AddNameProperties(&jsobj, user_name.ToCString(), vm_name.ToCString());
   if (ref) {
     return;
   }
@@ -265,9 +267,9 @@
   // Regular functions known to their owner use their name (percent-encoded).
   String& name = String::Handle(f.name());
   if (cls.LookupFunction(name) == f.raw()) {
-    name = String::EncodeIRI(name);
+    const char* encoded_name = String::EncodeIRI(name);
     jsobj.AddFixedServiceId("classes/%" Pd "/functions/%s",
-                            cls.id(), name.ToCString());
+                            cls.id(), encoded_name);
     return;
   }
   // Oddball functions (not known to their owner) fall back to use the object
@@ -288,7 +290,7 @@
   AddFunctionServiceId(jsobj, *this, cls);
   const String& user_name = String::Handle(UserVisibleName());
   const String& vm_name = String::Handle(name());
-  AddNameProperties(&jsobj, user_name, vm_name);
+  AddNameProperties(&jsobj, user_name.ToCString(), vm_name.ToCString());
   const Function& parent = Function::Handle(parent_function());
   if (!parent.IsNull()) {
     jsobj.AddProperty("owner", parent);
@@ -352,14 +354,14 @@
   JSONObject jsobj(stream);
   Class& cls = Class::Handle(Owner());
   String& field_name = String::Handle(name());
-  field_name = String::EncodeIRI(field_name);
+  const char* encoded_field_name = String::EncodeIRI(field_name);
   AddCommonObjectProperties(&jsobj, "Field", ref);
   jsobj.AddFixedServiceId("classes/%" Pd "/fields/%s",
-                          cls.id(), field_name.ToCString());
+                          cls.id(), encoded_field_name);
 
   const String& user_name = String::Handle(UserVisibleName());
   const String& vm_name = String::Handle(name());
-  AddNameProperties(&jsobj, user_name, vm_name);
+  AddNameProperties(&jsobj, user_name.ToCString(), vm_name.ToCString());
   if (cls.IsTopLevel()) {
     const Library& library = Library::Handle(cls.library());
     jsobj.AddProperty("owner", library);
@@ -434,14 +436,13 @@
   AddCommonObjectProperties(&jsobj, "Script", ref);
   const String& uri = String::Handle(url());
   ASSERT(!uri.IsNull());
-  const String& encoded_uri = String::Handle(String::EncodeIRI(uri));
-  ASSERT(!encoded_uri.IsNull());
+  const char* encoded_uri = String::EncodeIRI(uri);
   const Library& lib = Library::Handle(FindLibrary());
   if (lib.IsNull()) {
     jsobj.AddServiceId(*this);
   } else {
     jsobj.AddFixedServiceId("libraries/%" Pd "/scripts/%s/%" Px64 "",
-                            lib.index(), encoded_uri.ToCString(),
+                            lib.index(), encoded_uri,
                             load_timestamp());
   }
   jsobj.AddPropertyStr("uri", uri);
@@ -499,7 +500,7 @@
   jsobj.AddFixedServiceId("libraries/%" Pd "", id);
   const String& vm_name = String::Handle(name());
   const String& scrubbed_name = String::Handle(String::ScrubName(vm_name));
-  AddNameProperties(&jsobj, scrubbed_name, vm_name);
+  AddNameProperties(&jsobj, scrubbed_name.ToCString(), vm_name.ToCString());
   const String& library_url = String::Handle(url());
   jsobj.AddPropertyStr("uri", library_url);
   if (ref) {
@@ -808,8 +809,8 @@
   jsobj.AddFixedServiceId("code/%" Px64"-%" Px "",
                           compile_timestamp(),
                           PayloadStart());
-  const String& qualified_name = String::Handle(QualifiedName());
-  const String& vm_name = String::Handle(Name());
+  const char* qualified_name = QualifiedName();
+  const char* vm_name = Name();
   AddNameProperties(&jsobj, qualified_name, vm_name);
   const bool is_stub = IsStubCode() || IsAllocationStubCode();
   if (is_stub) {
@@ -837,8 +838,8 @@
     JSONObject func(&jsobj, "function");
     func.AddProperty("type", "@Function");
     func.AddProperty("_kind", "Stub");
-    ASSERT(qualified_name.Equals(vm_name));
-    func.AddProperty("name", vm_name.ToCString());
+    ASSERT(strcmp(qualified_name, vm_name) == 0);
+    func.AddProperty("name", vm_name);
     AddNameProperties(&func, vm_name, vm_name);
   }
   jsobj.AddPropertyF("_startAddress", "%" Px "", PayloadStart());
@@ -1122,7 +1123,7 @@
   }
   const String& user_name = String::Handle(UserVisibleName());
   const String& vm_name = String::Handle(Name());
-  AddNameProperties(&jsobj, user_name, vm_name);
+  AddNameProperties(&jsobj, user_name.ToCString(), vm_name.ToCString());
   if (ref) {
     return;
   }
@@ -1140,7 +1141,7 @@
   jsobj.AddServiceId(*this);
   const String& user_name = String::Handle(UserVisibleName());
   const String& vm_name = String::Handle(Name());
-  AddNameProperties(&jsobj, user_name, vm_name);
+  AddNameProperties(&jsobj, user_name.ToCString(), vm_name.ToCString());
   if (ref) {
     return;
   }
@@ -1155,7 +1156,7 @@
   jsobj.AddServiceId(*this);
   const String& user_name = String::Handle(UserVisibleName());
   const String& vm_name = String::Handle(Name());
-  AddNameProperties(&jsobj, user_name, vm_name);
+  AddNameProperties(&jsobj, user_name.ToCString(), vm_name.ToCString());
   const Class& param_cls = Class::Handle(parameterized_class());
   jsobj.AddProperty("parameterizedClass", param_cls);
   if (ref) {
@@ -1174,7 +1175,7 @@
   jsobj.AddServiceId(*this);
   const String& user_name = String::Handle(UserVisibleName());
   const String& vm_name = String::Handle(Name());
-  AddNameProperties(&jsobj, user_name, vm_name);
+  AddNameProperties(&jsobj, user_name.ToCString(), vm_name.ToCString());
   if (ref) {
     return;
   }
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 52ab426..73e2d70 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -407,9 +407,8 @@
       "file%3A%2F%2F%2Fusr%2Flocal%2Fjohnmccutchan%2Fworkspace%2F"
       "dart-repo%2Fdart%2Ftest.dart";
   const String& input = String::Handle(String::New(kInput));
-  const String& output = String::Handle(String::New(kOutput));
-  const String& encoded = String::Handle(String::EncodeIRI(input));
-  EXPECT(output.Equals(encoded));
+  const char* encoded = String::EncodeIRI(input);
+  EXPECT(strcmp(encoded, kOutput) == 0);
 }
 
 
@@ -449,7 +448,7 @@
   const uint16_t kOutput[kOutputLen] =
       { 'x', '%', '2', 'F', '%', 'C', '4', '%', '8', '0' };
   const String& output = String::Handle(String::FromUTF16(kOutput, kOutputLen));
-  const String& encoded = String::Handle(String::EncodeIRI(input));
+  const String& encoded = String::Handle(String::New(String::EncodeIRI(input)));
   EXPECT(output.Equals(encoded));
   const String& decoded = String::Handle(String::DecodeIRI(output));
   EXPECT(input.Equals(decoded));
diff --git a/runtime/vm/os_thread_android.cc b/runtime/vm/os_thread_android.cc
index 0ea90e6..8f9c648 100644
--- a/runtime/vm/os_thread_android.cc
+++ b/runtime/vm/os_thread_android.cc
@@ -16,12 +16,15 @@
 #include "platform/signal_blocker.h"
 #include "platform/utils.h"
 
+#include "vm/profiler.h"
+
 namespace dart {
 
 #define VALIDATE_PTHREAD_RESULT(result) \
   if (result != 0) { \
     const int kBufferSize = 1024; \
     char error_message[kBufferSize]; \
+    NOT_IN_PRODUCT(Profiler::DumpStackTrace(true /* native_stack_trace */)); \
     Utils::StrError(result, error_message, kBufferSize); \
     FATAL2("pthread error: %d (%s)", result, error_message); \
   }
diff --git a/runtime/vm/os_thread_linux.cc b/runtime/vm/os_thread_linux.cc
index 0f8f958..ac8a02b 100644
--- a/runtime/vm/os_thread_linux.cc
+++ b/runtime/vm/os_thread_linux.cc
@@ -17,12 +17,15 @@
 #include "platform/signal_blocker.h"
 #include "platform/utils.h"
 
+#include "vm/profiler.h"
+
 namespace dart {
 
 #define VALIDATE_PTHREAD_RESULT(result) \
   if (result != 0) { \
     const int kBufferSize = 1024; \
     char error_buf[kBufferSize]; \
+    NOT_IN_PRODUCT(Profiler::DumpStackTrace(true /* native_stack_trace */)); \
     FATAL2("pthread error: %d (%s)", result, \
            Utils::StrError(result, error_buf, kBufferSize)); \
   }
diff --git a/runtime/vm/os_thread_macos.cc b/runtime/vm/os_thread_macos.cc
index 53034be..92d0414 100644
--- a/runtime/vm/os_thread_macos.cc
+++ b/runtime/vm/os_thread_macos.cc
@@ -21,12 +21,15 @@
 #include "platform/assert.h"
 #include "platform/utils.h"
 
+#include "vm/profiler.h"
+
 namespace dart {
 
 #define VALIDATE_PTHREAD_RESULT(result)         \
   if (result != 0) { \
     const int kBufferSize = 1024; \
     char error_message[kBufferSize]; \
+    NOT_IN_PRODUCT(Profiler::DumpStackTrace(true /* native_stack_trace */)); \
     Utils::StrError(result, error_message, kBufferSize); \
     FATAL2("pthread error: %d (%s)", result, error_message); \
   }
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index 067f382..50a202a 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -65,11 +65,11 @@
   }
   ASSERT(!initialized_);
   sample_buffer_ = new SampleBuffer();
+  // Zero counters.
+  memset(&counters_, 0, sizeof(counters_));
   NativeSymbolResolver::InitOnce();
   ThreadInterrupter::SetInterruptPeriod(FLAG_profile_period);
   ThreadInterrupter::Startup();
-  // Zero counters.
-  memset(&counters_, 0, sizeof(counters_));
   initialized_ = true;
 }
 
@@ -786,18 +786,18 @@
 
   if (FLAG_profile_vm) {
     // Always walk the native stack collecting both native and Dart frames.
-    counters->stack_walker_native++;
+    AtomicOperations::IncrementInt64By(&counters->stack_walker_native, 1);
     native_stack_walker->walk();
   } else if (StubCode::HasBeenInitialized() && exited_dart_code) {
-    counters->stack_walker_dart_exit++;
+    AtomicOperations::IncrementInt64By(&counters->stack_walker_dart_exit, 1);
     // We have a valid exit frame info, use the Dart stack walker.
     dart_exit_stack_walker->walk();
   } else if (StubCode::HasBeenInitialized() && in_dart_code) {
-    counters->stack_walker_dart++;
+    AtomicOperations::IncrementInt64By(&counters->stack_walker_dart, 1);
     // We are executing Dart code. We have frame pointers.
     dart_stack_walker->walk();
   } else {
-    counters->stack_walker_none++;
+    AtomicOperations::IncrementInt64By(&counters->stack_walker_none, 1);
     sample->SetAt(0, pc);
   }
 
@@ -1139,7 +1139,7 @@
 
   // Thread is not doing VM work.
   if (thread->task_kind() == Thread::kUnknownTask) {
-    counters_.bail_out_unknown_task++;
+    AtomicOperations::IncrementInt64By(&counters_.bail_out_unknown_task, 1);
     return;
   }
 
@@ -1148,7 +1148,8 @@
     // The JumpToExceptionHandler stub manually adjusts the stack pointer,
     // frame pointer, and some isolate state before jumping to a catch entry.
     // It is not safe to walk the stack when executing this stub.
-    counters_.bail_out_jump_to_exception_handler++;
+    AtomicOperations::IncrementInt64By(
+        &counters_.bail_out_jump_to_exception_handler, 1);
     return;
   }
 
@@ -1182,18 +1183,20 @@
   }
 
   if (!CheckIsolate(isolate)) {
-    counters_.bail_out_check_isolate++;
+    AtomicOperations::IncrementInt64By(&counters_.bail_out_check_isolate, 1);
     return;
   }
 
   if (thread->IsMutatorThread() && isolate->IsDeoptimizing()) {
-    counters_.single_frame_sample_deoptimizing++;
+    AtomicOperations::IncrementInt64By(
+        &counters_.single_frame_sample_deoptimizing, 1);
     SampleThreadSingleFrame(thread, pc);
     return;
   }
 
   if (!InitialRegisterCheck(pc, fp, sp)) {
-    counters_.single_frame_sample_register_check++;
+    AtomicOperations::IncrementInt64By(
+        &counters_.single_frame_sample_register_check, 1);
     SampleThreadSingleFrame(thread, pc);
     return;
   }
@@ -1205,7 +1208,8 @@
                                         sp,
                                         &stack_lower,
                                         &stack_upper)) {
-    counters_.single_frame_sample_get_and_validate_stack_bounds++;
+    AtomicOperations::IncrementInt64By(
+       &counters_.single_frame_sample_get_and_validate_stack_bounds, 1);
     // Could not get stack boundary.
     SampleThreadSingleFrame(thread, pc);
     return;
diff --git a/runtime/vm/profiler.h b/runtime/vm/profiler.h
index be4f049..529a193 100644
--- a/runtime/vm/profiler.h
+++ b/runtime/vm/profiler.h
@@ -434,8 +434,7 @@
   }
 
   const char* Name() const {
-    const String& name = String::Handle(code_.Name());
-    return name.ToCString();
+    return code_.Name();
   }
 
   bool Contains(uword pc) const {
diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc
index 1a80017..b198a22 100644
--- a/runtime/vm/profiler_service.cc
+++ b/runtime/vm/profiler_service.cc
@@ -646,15 +646,15 @@
     function = table->GetUnknown();
   } else if (kind() == kDartCode) {
     ASSERT(!code_.IsNull());
-    const String& name = String::Handle(code_.QualifiedName());
+    const char* name = code_.QualifiedName();
     const Object& obj = Object::Handle(code_.owner());
     if (obj.IsFunction()) {
       function = table->LookupOrAdd(Function::Cast(obj));
     } else {
       // A stub.
-      function = table->AddStub(start(), name.ToCString());
+      function = table->AddStub(start(), name);
     }
-    SetName(name.ToCString());
+    SetName(name);
   } else if (kind() == kNativeCode) {
     if (name() == NULL) {
       // Lazily set generated name.
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 66b2d4c..cef387b 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -1166,7 +1166,8 @@
   int32_t state_bits_;
 
   // PC offsets for code patching.
-  NOT_IN_PRECOMPILED(int32_t lazy_deopt_pc_offset_);
+  NOT_IN_PRECOMPILED(int32_t lazy_deopt_return_pc_offset_);
+  NOT_IN_PRECOMPILED(int32_t lazy_deopt_throw_pc_offset_);
 
   // Variable length data follows here.
   int32_t* data() { OPEN_ARRAY_START(int32_t, int32_t); }
diff --git a/runtime/vm/stub_code.h b/runtime/vm/stub_code.h
index c179cac..bda3ba0 100644
--- a/runtime/vm/stub_code.h
+++ b/runtime/vm/stub_code.h
@@ -45,7 +45,8 @@
   V(MegamorphicCall)                                                           \
   V(FixAllocationStubTarget)                                                   \
   V(Deoptimize)                                                                \
-  V(DeoptimizeLazy)                                                            \
+  V(DeoptimizeLazyFromReturn)                                                  \
+  V(DeoptimizeLazyFromThrow)                                                   \
   V(UnoptimizedIdenticalWithNumberCheck)                                       \
   V(OptimizedIdenticalWithNumberCheck)                                         \
   V(ICCallBreakpoint)                                                          \
@@ -73,7 +74,8 @@
   V(LazyCompile)                                                               \
   V(FixCallersTarget)                                                          \
   V(Deoptimize)                                                                \
-  V(DeoptimizeLazy)                                                            \
+  V(DeoptimizeLazyFromReturn)                                                  \
+  V(DeoptimizeLazyFromThrow)                                                   \
   V(FrameAwaitingMaterialization)                                              \
 
 #endif  // !defined(TARGET_ARCH_DBC)
@@ -194,7 +196,8 @@
 
 
 enum DeoptStubKind {
-  kLazyDeopt,
+  kLazyDeoptFromReturn,
+  kLazyDeoptFromThrow,
   kEagerDeopt
 };
 
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index c000508..3bcf173 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -427,6 +427,10 @@
   // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls.
   const intptr_t saved_result_slot_from_fp =
       kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - R0);
+  const intptr_t saved_exception_slot_from_fp =
+      kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - R0);
+  const intptr_t saved_stacktrace_slot_from_fp =
+      kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - R1);
   // Result in R0 is preserved as part of pushing all registers below.
 
   // Push registers in their enumeration order: lowest register number at
@@ -459,15 +463,20 @@
   }
 
   __ mov(R0, Operand(SP));  // Pass address of saved registers block.
-  __ mov(R1, Operand(kind == kLazyDeopt ? 1 : 0));
+  bool is_lazy = (kind == kLazyDeoptFromReturn) ||
+                 (kind == kLazyDeoptFromThrow);
+  __ mov(R1, Operand(is_lazy ? 1 : 0));
   __ ReserveAlignedFrameSpace(0);
   __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 2);
   // Result (R0) is stack-size (FP - SP) in bytes.
 
-  const bool preserve_result = (kind == kLazyDeopt);
-  if (preserve_result) {
+  if (kind == kLazyDeoptFromReturn) {
     // Restore result into R1 temporarily.
     __ ldr(R1, Address(FP, saved_result_slot_from_fp * kWordSize));
+  } else if (kind == kLazyDeoptFromThrow) {
+    // Restore result into R1 temporarily.
+    __ ldr(R1, Address(FP, saved_exception_slot_from_fp * kWordSize));
+    __ ldr(R2, Address(FP, saved_stacktrace_slot_from_fp * kWordSize));
   }
 
   __ RestoreCodePointer();
@@ -478,14 +487,21 @@
   // is no need to set the correct PC marker or load PP, since they get patched.
   __ EnterStubFrame();
   __ mov(R0, Operand(FP));  // Get last FP address.
-  if (preserve_result) {
+  if (kind == kLazyDeoptFromReturn) {
     __ Push(R1);  // Preserve result as first local.
+  } else if (kind == kLazyDeoptFromThrow) {
+    __ Push(R1);  // Preserve exception as first local.
+    __ Push(R2);  // Preserve stacktrace as second local.
   }
   __ ReserveAlignedFrameSpace(0);
   __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry, 1);  // Pass last FP in R0.
-  if (preserve_result) {
+  if (kind == kLazyDeoptFromReturn) {
     // Restore result into R1.
     __ ldr(R1, Address(FP, kFirstLocalSlotFromFp * kWordSize));
+  } else if (kind == kLazyDeoptFromThrow) {
+    // Restore result into R1.
+    __ ldr(R1, Address(FP, kFirstLocalSlotFromFp * kWordSize));
+    __ ldr(R2, Address(FP, (kFirstLocalSlotFromFp - 1) * kWordSize));
   }
   // Code above cannot cause GC.
   __ RestoreCodePointer();
@@ -496,16 +512,22 @@
   // require allocation.
   // Enter stub frame with loading PP. The caller's PP is not materialized yet.
   __ EnterStubFrame();
-  if (preserve_result) {
+  if (kind == kLazyDeoptFromReturn) {
     __ Push(R1);  // Preserve result, it will be GC-d here.
+  } else if (kind == kLazyDeoptFromThrow) {
+    __ Push(R1);  // Preserve exception, it will be GC-d here.
+    __ Push(R2);  // Preserve stacktrace, it will be GC-d here.
   }
   __ PushObject(Smi::ZoneHandle());  // Space for the result.
   __ CallRuntime(kDeoptimizeMaterializeRuntimeEntry, 0);
   // Result tells stub how many bytes to remove from the expression stack
   // of the bottom-most frame. They were used as materialization arguments.
   __ Pop(R1);
-  if (preserve_result) {
+  if (kind == kLazyDeoptFromReturn) {
     __ Pop(R0);  // Restore result.
+  } else if (kind == kLazyDeoptFromThrow) {
+    __ Pop(R1);  // Restore stacktrace.
+    __ Pop(R0);  // Restore exception.
   }
   __ LeaveStubFrame();
   // Remove materialization arguments.
@@ -514,14 +536,30 @@
 }
 
 
-void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) {
+// LR: return address + call-instruction-size
+// R0: result, must be preserved
+void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) {
   // Correct return address to point just after the call that is being
   // deoptimized.
   __ AddImmediate(LR, -CallPattern::DeoptCallPatternLengthInBytes());
   // Push zap value instead of CODE_REG for lazy deopt.
   __ LoadImmediate(IP, 0xf1f1f1f1);
   __ Push(IP);
-  GenerateDeoptimizationSequence(assembler, kLazyDeopt);
+  GenerateDeoptimizationSequence(assembler, kLazyDeoptFromReturn);
+}
+
+
+// LR: return address + call-instruction-size
+// R0: exception, must be preserved
+// R1: stacktrace, must be preserved
+void StubCode::GenerateDeoptimizeLazyFromThrowStub(Assembler* assembler) {
+  // Correct return address to point just after the call that is being
+  // deoptimized.
+  __ AddImmediate(LR, -CallPattern::DeoptCallPatternLengthInBytes());
+  // Push zap value instead of CODE_REG for lazy deopt.
+  __ LoadImmediate(IP, 0xf1f1f1f1);
+  __ Push(IP);
+  GenerateDeoptimizationSequence(assembler, kLazyDeoptFromThrow);
 }
 
 
diff --git a/runtime/vm/stub_code_arm64.cc b/runtime/vm/stub_code_arm64.cc
index 6d97d6a..7ee3dd3 100644
--- a/runtime/vm/stub_code_arm64.cc
+++ b/runtime/vm/stub_code_arm64.cc
@@ -452,6 +452,10 @@
   // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls.
   const intptr_t saved_result_slot_from_fp =
       kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - R0);
+  const intptr_t saved_exception_slot_from_fp =
+      kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - R0);
+  const intptr_t saved_stacktrace_slot_from_fp =
+      kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - R1);
   // Result in R0 is preserved as part of pushing all registers below.
 
   // Push registers in their enumeration order: lowest register number at
@@ -475,15 +479,20 @@
   }
 
   __ mov(R0, SP);  // Pass address of saved registers block.
-  __ LoadImmediate(R1, kind == kLazyDeopt ? 1 : 0);
+  bool is_lazy = (kind == kLazyDeoptFromReturn) ||
+                 (kind == kLazyDeoptFromThrow);
+  __ LoadImmediate(R1, is_lazy ? 1 : 0);
   __ ReserveAlignedFrameSpace(0);
   __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 2);
   // Result (R0) is stack-size (FP - SP) in bytes.
 
-  const bool preserve_result = (kind == kLazyDeopt);
-  if (preserve_result) {
+  if (kind == kLazyDeoptFromReturn) {
     // Restore result into R1 temporarily.
     __ LoadFromOffset(R1, FP, saved_result_slot_from_fp * kWordSize);
+  } else if (kind == kLazyDeoptFromThrow) {
+    // Restore result into R1 temporarily.
+    __ LoadFromOffset(R1, FP, saved_exception_slot_from_fp * kWordSize);
+    __ LoadFromOffset(R2, FP, saved_stacktrace_slot_from_fp * kWordSize);
   }
 
   // There is a Dart Frame on the stack. We must restore PP and leave frame.
@@ -495,15 +504,22 @@
   // is no need to set the correct PC marker or load PP, since they get patched.
   __ EnterStubFrame();
 
-  if (preserve_result) {
+  if (kind == kLazyDeoptFromReturn) {
     __ Push(R1);  // Preserve result as first local.
+  } else if (kind == kLazyDeoptFromThrow) {
+    __ Push(R1);  // Preserve exception as first local.
+    __ Push(R2);  // Preserve stacktrace as second local.
   }
   __ ReserveAlignedFrameSpace(0);
   __ mov(R0, FP);  // Pass last FP as parameter in R0.
   __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry, 1);
-  if (preserve_result) {
+  if (kind == kLazyDeoptFromReturn) {
     // Restore result into R1.
     __ LoadFromOffset(R1, FP, kFirstLocalSlotFromFp * kWordSize);
+  } else if (kind == kLazyDeoptFromThrow) {
+    // Restore result into R1.
+    __ LoadFromOffset(R1, FP, kFirstLocalSlotFromFp * kWordSize);
+    __ LoadFromOffset(R2, FP, (kFirstLocalSlotFromFp - 1) * kWordSize);
   }
   // Code above cannot cause GC.
   // There is a Dart Frame on the stack. We must restore PP and leave frame.
@@ -515,17 +531,24 @@
   // require allocation.
   // Enter stub frame with loading PP. The caller's PP is not materialized yet.
   __ EnterStubFrame();
-  if (preserve_result) {
+  if (kind == kLazyDeoptFromReturn) {
     __ Push(R1);  // Preserve result, it will be GC-d here.
+  } else if (kind == kLazyDeoptFromThrow) {
+    __ Push(R1);  // Preserve exception, it will be GC-d here.
+    __ Push(R2);  // Preserve stacktrace, it will be GC-d here.
   }
+
   __ Push(ZR);  // Space for the result.
   __ CallRuntime(kDeoptimizeMaterializeRuntimeEntry, 0);
   // Result tells stub how many bytes to remove from the expression stack
   // of the bottom-most frame. They were used as materialization arguments.
   __ Pop(R1);
   __ SmiUntag(R1);
-  if (preserve_result) {
+  if (kind == kLazyDeoptFromReturn) {
     __ Pop(R0);  // Restore result.
+  } else if (kind == kLazyDeoptFromThrow) {
+    __ Pop(R1);  // Restore stacktrace.
+    __ Pop(R0);  // Restore exception.
   }
   __ LeaveStubFrame();
   // Remove materialization arguments.
@@ -534,14 +557,30 @@
 }
 
 
-void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) {
+// LR: return address + call-instruction-size
+// R0: result, must be preserved
+void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) {
   // Correct return address to point just after the call that is being
   // deoptimized.
   __ AddImmediate(LR, LR, -CallPattern::kDeoptCallLengthInBytes);
   // Push zap value instead of CODE_REG for lazy deopt.
   __ LoadImmediate(TMP, 0xf1f1f1f1);
   __ Push(TMP);
-  GenerateDeoptimizationSequence(assembler, kLazyDeopt);
+  GenerateDeoptimizationSequence(assembler, kLazyDeoptFromReturn);
+}
+
+
+// LR: return address + call-instruction-size
+// R0: exception, must be preserved
+// R1: stacktrace, must be preserved
+void StubCode::GenerateDeoptimizeLazyFromThrowStub(Assembler* assembler) {
+  // Correct return address to point just after the call that is being
+  // deoptimized.
+  __ AddImmediate(LR, LR, -CallPattern::kDeoptCallLengthInBytes);
+  // Push zap value instead of CODE_REG for lazy deopt.
+  __ LoadImmediate(TMP, 0xf1f1f1f1);
+  __ Push(TMP);
+  GenerateDeoptimizationSequence(assembler, kLazyDeoptFromThrow);
 }
 
 
diff --git a/runtime/vm/stub_code_dbc.cc b/runtime/vm/stub_code_dbc.cc
index 66a46bd..1f2d23e 100644
--- a/runtime/vm/stub_code_dbc.cc
+++ b/runtime/vm/stub_code_dbc.cc
@@ -54,7 +54,12 @@
 // These deoptimization stubs are only used to populate stack frames
 // with something meaningful to make sure GC can scan the stack during
 // the last phase of deoptimization which materializes objects.
-void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) {
+void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) {
+  __ Trap();
+}
+
+
+void StubCode::GenerateDeoptimizeLazyFromThrowStub(Assembler* assembler) {
   __ Trap();
 }
 
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index cb805c6..fab258e 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -359,6 +359,10 @@
   // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls.
   const intptr_t saved_result_slot_from_fp =
       kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - EAX);
+  const intptr_t saved_exception_slot_from_fp =
+      kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - EAX);
+  const intptr_t saved_stacktrace_slot_from_fp =
+      kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - EDX);
   // Result in EAX is preserved as part of pushing all registers below.
 
   // Push registers in their enumeration order: lowest register number at
@@ -383,14 +387,19 @@
   __ movl(ECX, ESP);  // Preserve saved registers block.
   __ ReserveAlignedFrameSpace(2 * kWordSize);
   __ movl(Address(ESP, 0 * kWordSize), ECX);  // Start of register block.
-  __ movl(Address(ESP, 1 * kWordSize), Immediate(kind == kLazyDeopt ? 1 : 0));
+  bool is_lazy = (kind == kLazyDeoptFromReturn) ||
+                 (kind == kLazyDeoptFromThrow);
+  __ movl(Address(ESP, 1 * kWordSize), Immediate(is_lazy ? 1 : 0));
   __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 2);
   // Result (EAX) is stack-size (FP - SP) in bytes.
 
-  const bool preserve_result = (kind == kLazyDeopt);
-  if (preserve_result) {
+  if (kind == kLazyDeoptFromReturn) {
     // Restore result into EBX temporarily.
     __ movl(EBX, Address(EBP, saved_result_slot_from_fp * kWordSize));
+  } else if (kind == kLazyDeoptFromThrow) {
+    // Restore result into EBX temporarily.
+    __ movl(EBX, Address(EBP, saved_exception_slot_from_fp * kWordSize));
+    __ movl(ECX, Address(EBP, saved_stacktrace_slot_from_fp * kWordSize));
   }
 
   __ LeaveFrame();
@@ -401,15 +410,22 @@
 
   // Leaf runtime function DeoptimizeFillFrame expects a Dart frame.
   __ EnterDartFrame(0);
-  if (preserve_result) {
+  if (kind == kLazyDeoptFromReturn) {
     __ pushl(EBX);  // Preserve result as first local.
+  } else if (kind == kLazyDeoptFromThrow) {
+    __ pushl(EBX);  // Preserve exception as first local.
+    __ pushl(ECX);  // Preserve stacktrace as first local.
   }
   __ ReserveAlignedFrameSpace(1 * kWordSize);
   __ movl(Address(ESP, 0), EBP);  // Pass last FP as parameter on stack.
   __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry, 1);
-  if (preserve_result) {
+  if (kind == kLazyDeoptFromReturn) {
     // Restore result into EBX.
     __ movl(EBX, Address(EBP, kFirstLocalSlotFromFp * kWordSize));
+  } else if (kind == kLazyDeoptFromThrow) {
+    // Restore result into EBX.
+    __ movl(EBX, Address(EBP, kFirstLocalSlotFromFp * kWordSize));
+    __ movl(ECX, Address(EBP, (kFirstLocalSlotFromFp - 1) * kWordSize));
   }
   // Code above cannot cause GC.
   __ LeaveFrame();
@@ -418,8 +434,11 @@
   // Materialize any objects that were deferred by FillFrame because they
   // require allocation.
   __ EnterStubFrame();
-  if (preserve_result) {
+  if (kind == kLazyDeoptFromReturn) {
     __ pushl(EBX);  // Preserve result, it will be GC-d here.
+  } else if (kind == kLazyDeoptFromThrow) {
+    __ pushl(EBX);  // Preserve exception, it will be GC-d here.
+    __ pushl(ECX);  // Preserve stacktrace, it will be GC-d here.
   }
   __ pushl(Immediate(Smi::RawValue(0)));  // Space for the result.
   __ CallRuntime(kDeoptimizeMaterializeRuntimeEntry, 0);
@@ -427,8 +446,11 @@
   // of the bottom-most frame. They were used as materialization arguments.
   __ popl(EBX);
   __ SmiUntag(EBX);
-  if (preserve_result) {
+  if (kind == kLazyDeoptFromReturn) {
     __ popl(EAX);  // Restore result.
+  } else if (kind == kLazyDeoptFromThrow) {
+    __ popl(EDX);  // Restore exception.
+    __ popl(EAX);  // Restore stacktrace.
   }
   __ LeaveFrame();
 
@@ -441,13 +463,26 @@
 
 // TOS: return address + call-instruction-size (5 bytes).
 // EAX: result, must be preserved
-void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) {
+void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) {
   // Correct return address to point just after the call that is being
   // deoptimized.
   __ popl(EBX);
   __ subl(EBX, Immediate(CallPattern::pattern_length_in_bytes()));
   __ pushl(EBX);
-  GenerateDeoptimizationSequence(assembler, kLazyDeopt);
+  GenerateDeoptimizationSequence(assembler, kLazyDeoptFromReturn);
+}
+
+
+// TOS: return address + call-instruction-size (5 bytes).
+// EAX: exception, must be preserved
+// EDX: stacktrace, must be preserved
+void StubCode::GenerateDeoptimizeLazyFromThrowStub(Assembler* assembler) {
+  // Correct return address to point just after the call that is being
+  // deoptimized.
+  __ popl(EBX);
+  __ subl(EBX, Immediate(CallPattern::pattern_length_in_bytes()));
+  __ pushl(EBX);
+  GenerateDeoptimizationSequence(assembler, kLazyDeoptFromThrow);
 }
 
 
diff --git a/runtime/vm/stub_code_mips.cc b/runtime/vm/stub_code_mips.cc
index e6384d8..de6db70 100644
--- a/runtime/vm/stub_code_mips.cc
+++ b/runtime/vm/stub_code_mips.cc
@@ -444,6 +444,10 @@
   // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls.
   const intptr_t saved_result_slot_from_fp =
       kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - V0);
+  const intptr_t saved_exception_slot_from_fp =
+      kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - V0);
+  const intptr_t saved_stacktrace_slot_from_fp =
+      kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - V1);
   // Result in V0 is preserved as part of pushing all registers below.
 
   // Push registers in their enumeration order: lowest register number at
@@ -469,15 +473,20 @@
   }
 
   __ mov(A0, SP);  // Pass address of saved registers block.
-  __ LoadImmediate(A1, (kind == kLazyDeopt) ? 1 : 0);
+  bool is_lazy = (kind == kLazyDeoptFromReturn) ||
+                 (kind == kLazyDeoptFromThrow);
+  __ LoadImmediate(A1, is_lazy ? 1 : 0);
   __ ReserveAlignedFrameSpace(1 * kWordSize);
   __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 2);
   // Result (V0) is stack-size (FP - SP) in bytes, incl. the return address.
 
-  const bool preserve_result = (kind == kLazyDeopt);
-  if (preserve_result) {
+  if (kind == kLazyDeoptFromReturn) {
     // Restore result into T1 temporarily.
     __ lw(T1, Address(FP, saved_result_slot_from_fp * kWordSize));
+  } else if (kind == kLazyDeoptFromThrow) {
+    // Restore result into T1 temporarily.
+    __ lw(T1, Address(FP, saved_exception_slot_from_fp * kWordSize));
+    __ lw(T2, Address(FP, saved_stacktrace_slot_from_fp * kWordSize));
   }
 
   __ RestoreCodePointer();
@@ -489,14 +498,21 @@
   __ EnterStubFrame();
 
   __ mov(A0, FP);  // Get last FP address.
-  if (preserve_result) {
+  if (kind == kLazyDeoptFromReturn) {
     __ Push(T1);  // Preserve result as first local.
+  } else if (kind == kLazyDeoptFromThrow) {
+    __ Push(T1);  // Preserve exception as first local.
+    __ Push(T2);  // Preserve stacktrace as second local.
   }
   __ ReserveAlignedFrameSpace(1 * kWordSize);
   __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry, 1);  // Pass last FP in A0.
-  if (preserve_result) {
+  if (kind == kLazyDeoptFromReturn) {
     // Restore result into T1.
     __ lw(T1, Address(FP, kFirstLocalSlotFromFp * kWordSize));
+  } else if (kind == kLazyDeoptFromThrow) {
+    // Restore result into T1.
+    __ lw(T1, Address(FP, kFirstLocalSlotFromFp * kWordSize));
+    __ lw(T2, Address(FP, (kFirstLocalSlotFromFp - 1) * kWordSize));
   }
   // Code above cannot cause GC.
   __ RestoreCodePointer();
@@ -507,16 +523,22 @@
   // require allocation.
   // Enter stub frame with loading PP. The caller's PP is not materialized yet.
   __ EnterStubFrame();
-  if (preserve_result) {
+  if (kind == kLazyDeoptFromReturn) {
     __ Push(T1);  // Preserve result, it will be GC-d here.
+  } else if (kind == kLazyDeoptFromThrow) {
+    __ Push(T1);  // Preserve exception, it will be GC-d here.
+    __ Push(T2);  // Preserve stacktrace, it will be GC-d here.
   }
   __ PushObject(Smi::ZoneHandle());  // Space for the result.
   __ CallRuntime(kDeoptimizeMaterializeRuntimeEntry, 0);
   // Result tells stub how many bytes to remove from the expression stack
   // of the bottom-most frame. They were used as materialization arguments.
   __ Pop(T1);
-  if (preserve_result) {
+  if (kind == kLazyDeoptFromReturn) {
     __ Pop(V0);  // Restore result.
+  } else if (kind == kLazyDeoptFromThrow) {
+    __ Pop(V1);  // Restore stacktrace.
+    __ Pop(V0);  // Restore exception.
   }
   __ LeaveStubFrame();
   // Remove materialization arguments.
@@ -525,15 +547,30 @@
   __ Ret();
 }
 
-
-void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) {
+// RA: return address + call-instruction-size
+// V0: result, must be preserved
+void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) {
   // Correct return address to point just after the call that is being
   // deoptimized.
   __ AddImmediate(RA, -CallPattern::kDeoptCallLengthInBytes);
   // Push zap value instead of CODE_REG for lazy deopt.
   __ LoadImmediate(TMP, 0xf1f1f1f1);
   __ Push(TMP);
-  GenerateDeoptimizationSequence(assembler, kLazyDeopt);
+  GenerateDeoptimizationSequence(assembler, kLazyDeoptFromReturn);
+}
+
+
+// RA: return address + call-instruction-size
+// V0: exception, must be preserved
+// V1: stacktrace, must be preserved
+void StubCode::GenerateDeoptimizeLazyFromThrowStub(Assembler* assembler) {
+  // Correct return address to point just after the call that is being
+  // deoptimized.
+  __ AddImmediate(RA, -CallPattern::kDeoptCallLengthInBytes);
+  // Push zap value instead of CODE_REG for lazy deopt.
+  __ LoadImmediate(TMP, 0xf1f1f1f1);
+  __ Push(TMP);
+  GenerateDeoptimizationSequence(assembler, kLazyDeoptFromThrow);
 }
 
 
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index 5c4384c..6ec5ba1 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -385,6 +385,10 @@
   // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls.
   const intptr_t saved_result_slot_from_fp =
       kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - RAX);
+  const intptr_t saved_exception_slot_from_fp =
+      kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - RAX);
+  const intptr_t saved_stacktrace_slot_from_fp =
+      kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - RDX);
   // Result in RAX is preserved as part of pushing all registers below.
 
   // Push registers in their enumeration order: lowest register number at
@@ -408,15 +412,20 @@
 
   // Pass address of saved registers block.
   __ movq(CallingConventions::kArg1Reg, RSP);
-  __ movq(CallingConventions::kArg2Reg, Immediate(kind == kLazyDeopt ? 1 : 0));
+  bool is_lazy = (kind == kLazyDeoptFromReturn) ||
+                 (kind == kLazyDeoptFromThrow);
+  __ movq(CallingConventions::kArg2Reg, Immediate(is_lazy ? 1 : 0));
   __ ReserveAlignedFrameSpace(0);  // Ensure stack is aligned before the call.
   __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 2);
   // Result (RAX) is stack-size (FP - SP) in bytes.
 
-  const bool preserve_result = (kind == kLazyDeopt);
-  if (preserve_result) {
+  if (kind == kLazyDeoptFromReturn) {
     // Restore result into RBX temporarily.
     __ movq(RBX, Address(RBP, saved_result_slot_from_fp * kWordSize));
+  } else if (kind == kLazyDeoptFromThrow) {
+    // Restore result into RBX temporarily.
+    __ movq(RBX, Address(RBP, saved_exception_slot_from_fp * kWordSize));
+    __ movq(RDX, Address(RBP, saved_stacktrace_slot_from_fp * kWordSize));
   }
 
   // There is a Dart Frame on the stack. We must restore PP and leave frame.
@@ -432,16 +441,24 @@
   // is no need to set the correct PC marker or load PP, since they get patched.
   __ EnterStubFrame();
 
-  if (preserve_result) {
+  if (kind == kLazyDeoptFromReturn) {
     __ pushq(RBX);  // Preserve result as first local.
+  } else if (kind == kLazyDeoptFromThrow) {
+    __ pushq(RBX);  // Preserve exception as first local.
+    __ pushq(RDX);  // Preserve stacktrace as second local.
   }
   __ ReserveAlignedFrameSpace(0);
   // Pass last FP as a parameter.
   __ movq(CallingConventions::kArg1Reg, RBP);
   __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry, 1);
-  if (preserve_result) {
+  if (kind == kLazyDeoptFromReturn) {
     // Restore result into RBX.
     __ movq(RBX, Address(RBP, kFirstLocalSlotFromFp * kWordSize));
+  } else if (kind == kLazyDeoptFromThrow) {
+    // Restore exception into RBX.
+    __ movq(RBX, Address(RBP, kFirstLocalSlotFromFp * kWordSize));
+    // Restore stacktrace into RDX.
+    __ movq(RDX, Address(RBP, (kFirstLocalSlotFromFp - 1) * kWordSize));
   }
   // Code above cannot cause GC.
   // There is a Dart Frame on the stack. We must restore PP and leave frame.
@@ -453,8 +470,11 @@
   // require allocation.
   // Enter stub frame with loading PP. The caller's PP is not materialized yet.
   __ EnterStubFrame();
-  if (preserve_result) {
+  if (kind == kLazyDeoptFromReturn) {
     __ pushq(RBX);  // Preserve result, it will be GC-d here.
+  } else if (kind == kLazyDeoptFromThrow) {
+    __ pushq(RBX);  // Preserve exception.
+    __ pushq(RDX);  // Preserve stacktrace.
   }
   __ pushq(Immediate(Smi::RawValue(0)));  // Space for the result.
   __ CallRuntime(kDeoptimizeMaterializeRuntimeEntry, 0);
@@ -462,8 +482,11 @@
   // of the bottom-most frame. They were used as materialization arguments.
   __ popq(RBX);
   __ SmiUntag(RBX);
-  if (preserve_result) {
+  if (kind == kLazyDeoptFromReturn) {
     __ popq(RAX);  // Restore result.
+  } else if (kind == kLazyDeoptFromThrow) {
+    __ popq(RDX);  // Restore stacktrace.
+    __ popq(RAX);  // Restore exception.
   }
   __ LeaveStubFrame();
 
@@ -476,7 +499,7 @@
 
 // TOS: return address + call-instruction-size (5 bytes).
 // RAX: result, must be preserved
-void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) {
+void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) {
   // Correct return address to point just after the call that is being
   // deoptimized.
   __ popq(RBX);
@@ -484,7 +507,22 @@
   // Push zap value instead of CODE_REG for lazy deopt.
   __ pushq(Immediate(0xf1f1f1f1));
   __ pushq(RBX);
-  GenerateDeoptimizationSequence(assembler, kLazyDeopt);
+  GenerateDeoptimizationSequence(assembler, kLazyDeoptFromReturn);
+}
+
+
+// TOS: return address + call-instruction-size (5 bytes).
+// RAX: exception, must be preserved
+// RDX: stacktrace, must be preserved
+void StubCode::GenerateDeoptimizeLazyFromThrowStub(Assembler* assembler) {
+  // Correct return address to point just after the call that is being
+  // deoptimized.
+  __ popq(RBX);
+  __ subq(RBX, Immediate(ShortCallPattern::pattern_length_in_bytes()));
+  // Push zap value instead of CODE_REG for lazy deopt.
+  __ pushq(Immediate(0xf1f1f1f1));
+  __ pushq(RBX);
+  GenerateDeoptimizationSequence(assembler, kLazyDeoptFromThrow);
 }
 
 
diff --git a/sdk/lib/core/uri.dart b/sdk/lib/core/uri.dart
index d7f911b..847521a 100644
--- a/sdk/lib/core/uri.dart
+++ b/sdk/lib/core/uri.dart
@@ -4323,10 +4323,6 @@
         base._schemeCache);
     }
     // Merge paths.
-    if (base._uri.startsWith("../", base._pathStart)) {
-      // Complex rare case, go slow.
-      return _toNonSimple().resolveUri(ref);
-    }
 
     // The RFC 3986 algorithm merges the base path without its final segment
     // (anything after the final "/", or everything if the base path doesn't
@@ -4341,39 +4337,53 @@
     String refUri = ref._uri;
     int baseStart = base._pathStart;
     int baseEnd = base._queryStart;
+    while (baseUri.startsWith("../", baseStart)) baseStart += 3;
     int refStart = ref._pathStart;
     int refEnd = ref._queryStart;
-    int backCount = 1;
 
-    int slashCount = 0;
-
-    // Count leading ".." segments in reference path.
+    /// Count of leading ".." segments in reference path.
+    /// The count is decremented when the segment is matched with a
+    /// segment of the base path, and both are then omitted from the result.
+    int backCount = 0;
+    /// Count "../" segments and advance `refStart` to after the segments.
     while (refStart + 3 <= refEnd && refUri.startsWith("../", refStart)) {
       refStart += 3;
       backCount += 1;
     }
 
     // Extra slash inserted between base and reference path parts if
-    // the base path contains any slashes.
+    // the base path contains any slashes, or empty string if none.
     // (We could use a slash from the base path in most cases, but not if
     // we remove the entire base path).
     String insert = "";
+
+    /// Remove segments from the base path.
+    /// Start with the segment trailing the last slash,
+    /// then remove segments for each leading "../" segment
+    /// from the reference path, or as many of them as are available.
     while (baseEnd > baseStart) {
       baseEnd--;
       int char = baseUri.codeUnitAt(baseEnd);
       if (char == _SLASH) {
         insert = "/";
-        backCount--;
         if (backCount == 0) break;
+        backCount--;
       }
     }
-    // If the base URI has no scheme or authority (`_pathStart == 0`)
-    // and a relative path, and we reached the beginning of the path,
-    // we have a special case.
-    if (baseEnd == 0 && !base.hasAbsolutePath) {
-      // Non-RFC 3986 behavior when resolving a purely relative path on top of
-      // another relative path: Don't make the result absolute.
+
+    if (baseEnd == baseStart && !base.hasScheme && !base.hasAbsolutePath) {
+      // If the base is *just* a relative path (no scheme or authority),
+      // then merging with another relative path doesn't follow the
+      // RFC-3986 behavior.
+      // Don't need to check `base.hasAuthority` since the base path is
+      // non-empty - if there is an authority, a non-empty path is absolute.
+
+      // We reached the start of the base path, and want to stay relative,
+      // so don't insert a slash.
       insert = "";
+      // If we reached the start of the base path with more "../" left over
+      // in the reference path, include those segments in the result.
+      refStart -= backCount * 3;
     }
 
     var delta = baseEnd - refStart + insert.length;
diff --git a/sdk/lib/isolate/isolate.dart b/sdk/lib/isolate/isolate.dart
index 8caccdb..cb58a44 100644
--- a/sdk/lib/isolate/isolate.dart
+++ b/sdk/lib/isolate/isolate.dart
@@ -7,9 +7,9 @@
  * independent workers that are similar to threads
  * but don't share memory,
  * communicating only via messages.
- * 
+ *
  * To use this library in your code:
- * 
+ *
  *     import 'dart:isolate';
  */
 library dart.isolate;
@@ -162,19 +162,27 @@
    * Creates and spawns an isolate that shares the same code as the current
    * isolate.
    *
-   * The argument [entryPoint] specifies the entry point of the spawned
-   * isolate. It must be a top-level function or a static method that
-   * takes one argument - that is, one-parameter functions that can be
-   * compile-time constant function values.
-   * It is not allowed to pass the value of function expressions or an instance
-   * method extracted from an object.
+   * The argument [entryPoint] specifies the initial function to call
+   * in the spawned isolate.
+   * The entry-point function is invoked in the new isolate with [message]
+   * as the only argument.
    *
-   * The entry-point function is invoked with the initial [message].
+   * The function must be a top-level function or a static method
+   * that can be called with a single argument,
+   * that is, a compile-time constant function value
+   * which accepts at least one positional parameter
+   * and has at most one required positional parameter.
+   * The function may accept any number of optional parameters,
+   * as long as it *can* be called with just a single argument.
+   * The function must not be the value of a function expression
+   * or an instance method tear-off.
+   *
    * Usually the initial [message] contains a [SendPort] so
    * that the spawner and spawnee can communicate with each other.
    *
    * If the [paused] parameter is set to `true`,
    * the isolate will start up in a paused state,
+   * just before calling the [entryPoint] function with the [message],
    * as if by an initial call of `isolate.pause(isolate.pauseCapability)`.
    * To resume the isolate, call `isolate.resume(isolate.pauseCapability)`.
    *
@@ -184,19 +192,22 @@
    * corresponding parameter and was processed before the isolate starts
    * running.
    *
+   * If [errorsAreFatal] is omitted, the platform may choose a default behavior
+   * or inherit the current isolate's behavior.
+   *
    * You can also call the [setErrorsFatal], [addOnExitListener] and
    * [addErrorListener] methods on the returned isolate, but unless the
    * isolate was started as [paused], it may already have terminated
    * before those methods can complete.
    *
-   * Returns a future that will complete with an [Isolate] instance if the
+   * Returns a future which will complete with an [Isolate] instance if the
    * spawning succeeded. It will complete with an error otherwise.
    */
   external static Future<Isolate> spawn(void entryPoint(message), var message,
-                                        { bool paused: false,
-                                          bool errorsAreFatal,
-                                          SendPort onExit,
-                                          SendPort onError });
+                                        {bool paused: false,
+                                         bool errorsAreFatal,
+                                         SendPort onExit,
+                                         SendPort onError});
 
   /**
    * Creates and spawns an isolate that runs the code from the library with
@@ -291,13 +302,16 @@
   /**
    * Requests the isolate to pause.
    *
-   * The isolate should stop handling events by pausing its event queue.
-   * The request will eventually make the isolate stop doing anything.
-   * It will be handled before any other messages that are later sent to the
-   * isolate from the current isolate, but no other guarantees are provided.
+   * When the isolate receives the pause command, it stops
+   * processing events from the event loop queue.
+   * It may still add new events to the queue in response to, e.g., timers
+   * or receive-port messages. When the isolate is resumed, it handles
+   * the already enqueued events.
    *
-   * The event loop may be paused before previously sent, but not yet exeuted,
-   * messages have been reached.
+   * The pause request is sent through the isolate's command port,
+   * which bypasses the receiving isolate's event loop.
+   * The pause takes effect when it is received, pausing the event loop
+   * as it is at that time.
    *
    * If [resumeCapability] is provided, it is used to identity the pause,
    * and must be used again to end the pause using [resume].
@@ -307,12 +321,12 @@
    * only one resume with that capability is needed to end the pause.
    *
    * If an isolate is paused using more than one capability,
-   * they must all be individully ended before the isolate resumes.
+   * each pause must be individually ended before the isolate resumes.
    *
-   * Returns the capability that must be used to resume end the pause.
+   * Returns the capability that must be used to end the pause.
    */
   Capability pause([Capability resumeCapability]) {
-    if (resumeCapability == null) resumeCapability = new Capability();
+    resumeCapability ??= new Capability();
     _pause(resumeCapability);
     return resumeCapability;
   }
@@ -327,7 +341,7 @@
    * that was requested using the [resumeCapability].
    *
    * When all active pause requests have been cancelled, the isolate
-   * will continue handling normal messages.
+   * will continue processing events and handling normal messages.
    *
    * The capability must be one returned by a call to [pause] on this
    * isolate, otherwise the resume call does nothing.
diff --git a/tests/compiler/dart2js/kernel/helper.dart b/tests/compiler/dart2js/kernel/helper.dart
index 4e89025..1d83a10 100644
--- a/tests/compiler/dart2js/kernel/helper.dart
+++ b/tests/compiler/dart2js/kernel/helper.dart
@@ -14,11 +14,13 @@
 import '../memory_compiler.dart';
 
 Future<String> compile(String code,
-    {String entry: 'main', bool useKernel: true}) async {
+    {String entry: 'main',
+    bool useKernel: true,
+    bool disableTypeInference: true}) async {
   List<String> options = <String>[
-    Flags.disableTypeInference,
     Flags.disableInlining,
   ];
+  if (disableTypeInference) options.add(Flags.disableTypeInference);
   if (useKernel) options.add(Flags.useKernel);
 
   if (entry != 'main' && !code.contains('main')) {
@@ -33,8 +35,15 @@
   return backend.getGeneratedCode(element);
 }
 
-Future check(String code, {String entry: 'main'}) async {
-  var original = await compile(code, entry: entry, useKernel: false);
-  var kernel = await compile(code, entry: entry, useKernel: true);
+Future check(String code,
+    {String entry: 'main', bool disableTypeInference: true}) async {
+  var original = await compile(code,
+      entry: entry,
+      useKernel: false,
+      disableTypeInference: disableTypeInference);
+  var kernel = await compile(code,
+      entry: entry,
+      useKernel: true,
+      disableTypeInference: disableTypeInference);
   expect(kernel, original);
 }
diff --git a/tests/compiler/dart2js/kernel/loops_test.dart b/tests/compiler/dart2js/kernel/loops_test.dart
index 6535e95..a619c36 100644
--- a/tests/compiler/dart2js/kernel/loops_test.dart
+++ b/tests/compiler/dart2js/kernel/loops_test.dart
@@ -7,7 +7,7 @@
 import 'helper.dart' show check;
 
 main() {
-  test('for-loop', () {
+  test('for loop', () {
     String code = '''
 main() {
   var a = 0;
@@ -19,7 +19,7 @@
     return check(code);
   });
 
-  test('while-loop', () {
+  test('while loop', () {
     String code = '''
 main() {
   var a = 0;
@@ -30,4 +30,46 @@
 }''';
     return check(code);
   });
+
+  test('for-in loop', () {
+    String code = '''
+main() {
+  var sum = 0;
+  for (var a in [1, 2, 3]) {
+    sum += a;
+  }
+  return sum;
+}''';
+    // TODO(het): Check that the code is alpha-equivalent. That is,
+    // the same except for variable names.
+    return check(code);
+  }, skip: "The output is the same, with one variable renamed");
+
+  test('for-in loop optimized', () {
+    String code = '''
+main() {
+  var sum = 0;
+  for (var a in [1, 2, 3]) {
+    sum += a;
+  }
+  return sum;
+}''';
+    // This is the same test as above, but by enabling type inference
+    // we allow the compiler to detect that it can iterate over the
+    // array using indexing.
+    return check(code, disableTypeInference: false);
+  });
+
+  test('for-in loop top-level variable', () {
+    String code = '''
+var a = 0;
+main() {
+  var sum = 0;
+  for (a in [1, 2, 3]) {
+    sum += a;
+  }
+  return sum;
+}''';
+    return check(code, disableTypeInference: false);
+  });
 }
diff --git a/tests/corelib/uri_test.dart b/tests/corelib/uri_test.dart
index 5c8c1d1..9e4b24f 100644
--- a/tests/corelib/uri_test.dart
+++ b/tests/corelib/uri_test.dart
@@ -85,14 +85,42 @@
 }
 
 testUriPerRFCs() {
-  final urisSample = "http://a/b/c/d;p?q";
-  Uri base = Uri.parse(urisSample);
+  // Convert a Uri to a guaranteed "non simple" URI with the same content.
+  toComplex(Uri uri) {
+    Uri complex = new Uri(
+      scheme: uri.scheme,
+      userInfo: uri.hasAuthority ? uri.userInfo : null,
+      host: uri.hasAuthority ? uri.host : null,
+      port: uri.hasAuthority ? uri.port : null,
+      path: uri.path,
+      query: uri.hasQuery ? uri.query : null,
+      fragment: uri.hasFragment ? uri.fragment : null,
+    );
+    assert(complex.toString() == uri.toString());
+    return complex;
+  }
+
+  Uri base;
+  Uri complexBase;
+  // Sets the [base] and [complexBase] to the parse of the URI and a
+  // guaranteed non-simple version of the same URI.
+  setBase(String uri) {
+    base = Uri.parse(uri);
+    complexBase = toComplex(base);
+  }
+
   testResolve(expect, relative) {
     String name = "$base << $relative";
     Expect.stringEquals(expect, base.resolve(relative).toString(), name);
+
+    Expect.stringEquals(expect, complexBase.resolve(relative).toString(),
+                        name + " (complex base)");
   }
 
   // From RFC 3986.
+  final urisSample = "http://a/b/c/d;p?q";
+  setBase(urisSample);
+
   testResolve("g:h",                   "g:h");
   testResolve("http://a/b/c/g",        "g");
   testResolve("http://a/b/c/g",        "./g");
@@ -139,47 +167,66 @@
   // Additional tests (not from RFC 3986).
   testResolve("http://a/b/g;p/h;s",    "../g;p/h;s");
 
-  base = Uri.parse("s:a/b");
+  setBase("s:a/b");
   testResolve("s:a/c", "c");
   testResolve("s:/c", "../c");
 
-  base = Uri.parse("S:a/b");
+  setBase("S:a/b");
   testResolve("s:a/c", "c");
   testResolve("s:/c", "../c");
 
-  base = Uri.parse("s:foo");
+  setBase("s:foo");
   testResolve("s:bar", "bar");
   testResolve("s:bar", "../bar");
 
-  base = Uri.parse("S:foo");
+  setBase("S:foo");
   testResolve("s:bar", "bar");
   testResolve("s:bar", "../bar");
 
   // Special-case (deliberate non-RFC behavior).
-  base = Uri.parse("foo/bar");
+  setBase("foo/bar");
   testResolve("foo/baz", "baz");
   testResolve("baz", "../baz");
 
-  base = Uri.parse("s:/foo");
+  setBase("s:/foo");
   testResolve("s:/bar", "bar");
   testResolve("s:/bar", "../bar");
 
-  base = Uri.parse("S:/foo");
+  setBase("S:/foo");
   testResolve("s:/bar", "bar");
   testResolve("s:/bar", "../bar");
 
   // Test non-URI base (no scheme, no authority, relative path).
-  base = Uri.parse("a/b/c?_#_");
+  setBase("a/b/c?_#_");
   testResolve("a/b/g?q#f", "g?q#f");
   testResolve("./", "../..");
   testResolve("../", "../../..");
   testResolve("a/b/", ".");
   testResolve("c", "../../c");  // Deliberate non-RFC behavior.
-  base = Uri.parse("../../a/b/c?_#_");  // Initial ".." in base url.
+  setBase("../../a/b/c?_#_");  // Initial ".." in base url.
   testResolve("../../a/d", "../d");
+  testResolve("../../d", "../../d");
   testResolve("../../../d", "../../../d");
+  setBase("../../a/b");
+  testResolve("../../a/d", "d");
+  testResolve("../../d", "../d");
+  testResolve("../../../d", "../../d");
+  setBase("../../a");
+  testResolve("../../d", "d");
+  testResolve("../../../d", "../d");
+  testResolve("../../../../d", "../../d");
 
-  base = Uri.parse("s://h/p?q#f");  // A simple base.
+  // Absoluyte path, not scheme or authority.
+  setBase("/a");
+  testResolve("/b", "b");
+  testResolve("/b", "../b");
+  testResolve("/b", "../../b");
+  setBase("/a/b");
+  testResolve("/a/c", "c");
+  testResolve("/c", "../c");
+  testResolve("/c", "../../c");
+
+  setBase("s://h/p?q#f");  // A simple base.
   // Simple references:
   testResolve("s2://h2/P?Q#F", "s2://h2/P?Q#F");
   testResolve("s://h2/P?Q#F", "//h2/P?Q#F");
@@ -195,7 +242,7 @@
   testResolve("s://h/p?Q#F%20", "?Q#F%20");
   testResolve("s://h/p?q#F%20", "#F%20");
 
-  base = Uri.parse("s://h/p1/p2/p3");  // A simple base with a path.
+  setBase("s://h/p1/p2/p3");  // A simple base with a path.
   testResolve("s://h/p1/p2/", ".");
   testResolve("s://h/p1/p2/", "./");
   testResolve("s://h/p1/", "..");
@@ -206,7 +253,7 @@
   testResolve("s://h/", "../../../..");
   testResolve("s://h/", "../../../../");
 
-  base = Uri.parse("s://h/p?q#f%20");  // A non-simpe base.
+  setBase("s://h/p?q#f%20");  // A non-simpe base.
   // Simple references:
   testResolve("s2://h2/P?Q#F", "s2://h2/P?Q#F");
   testResolve("s://h2/P?Q#F", "//h2/P?Q#F");
@@ -222,7 +269,7 @@
   testResolve("s://h/p?Q#F%20", "?Q#F%20");
   testResolve("s://h/p?q#F%20", "#F%20");
 
-  base = Uri.parse("S://h/p1/p2/p3");  // A non-simple base with a path.
+  setBase("S://h/p1/p2/p3");  // A non-simple base with a path.
   testResolve("s://h/p1/p2/", ".");
   testResolve("s://h/p1/p2/", "./");
   testResolve("s://h/p1/", "..");
@@ -233,7 +280,7 @@
   testResolve("s://h/", "../../../..");
   testResolve("s://h/", "../../../../");
 
-  base = Uri.parse("../../../");  // A simple relative path.
+  setBase("../../../");  // A simple relative path.
   testResolve("../../../a", "a");
   testResolve("../../../../a", "../a");
   testResolve("../../../a%20", "a%20");
@@ -242,8 +289,7 @@
   // Tests covering the branches of the merge algorithm in RFC 3986
   // with both simple and complex base URIs.
   for (var b in ["s://a/pa/pb?q#f", "s://a/pa/pb?q#f%20"]) {
-    var origBase = Uri.parse(b);
-    base = origBase;
+    setBase(b);
 
     // if defined(R.scheme) then ...
     testResolve("s2://a2/p2?q2#f2", "s2://a2/p2?q2#f2");
@@ -271,40 +317,40 @@
     // (Cover the merge function and the remove-dot-fragments functions too).
 
     // If base has authority and empty path ...
-    var emptyPathBase = Uri.parse(b.replaceFirst("/pa/pb", ""));
-    base = emptyPathBase;
+    var emptyPathBase = b.replaceFirst("/pa/pb", "");
+    setBase(emptyPathBase);
     testResolve("s://a/p2?q2#f2", "p2?q2#f2");
     testResolve("s://a/p2#f2", "p2#f2");
     testResolve("s://a/p2", "p2");
 
-    base = origBase;
+    setBase(b);
     // otherwise
     // (Cover both no authority and non-empty path and both).
-    var noAuthEmptyPathBase = Uri.parse(b.replaceFirst("//a/pa/pb", ""));
-    var noAuthAbsPathBase = Uri.parse(b.replaceFirst("//a", ""));
-    var noAuthRelPathBase = Uri.parse(b.replaceFirst("//a/", ""));
-    var noAuthRelSinglePathBase = Uri.parse(b.replaceFirst("//a/pa/", ""));
+    var noAuthEmptyPathBase = b.replaceFirst("//a/pa/pb", "");
+    var noAuthAbsPathBase = b.replaceFirst("//a", "");
+    var noAuthRelPathBase = b.replaceFirst("//a/", "");
+    var noAuthRelSinglePathBase = b.replaceFirst("//a/pa/", "");
 
     testResolve("s://a/pa/p2?q2#f2", "p2?q2#f2");
     testResolve("s://a/pa/p2#f2", "p2#f2");
     testResolve("s://a/pa/p2", "p2");
 
-    base = noAuthEmptyPathBase;
+    setBase(noAuthEmptyPathBase);
     testResolve("s:p2?q2#f2", "p2?q2#f2");
     testResolve("s:p2#f2", "p2#f2");
     testResolve("s:p2", "p2");
 
-    base = noAuthAbsPathBase;
+    setBase(noAuthAbsPathBase);
     testResolve("s:/pa/p2?q2#f2", "p2?q2#f2");
     testResolve("s:/pa/p2#f2", "p2#f2");
     testResolve("s:/pa/p2", "p2");
 
-    base = noAuthRelPathBase;
+    setBase(noAuthRelPathBase);
     testResolve("s:pa/p2?q2#f2", "p2?q2#f2");
     testResolve("s:pa/p2#f2", "p2#f2");
     testResolve("s:pa/p2", "p2");
 
-    base = noAuthRelSinglePathBase;
+    setBase(noAuthRelSinglePathBase);
     testResolve("s:p2?q2#f2", "p2?q2#f2");
     testResolve("s:p2#f2", "p2#f2");
     testResolve("s:p2", "p2");
@@ -314,7 +360,7 @@
     // A. if input buffer starts with "../" or "./".
     // This only happens if base has only a single (may be empty) segment and
     // no slash.
-    base = emptyPathBase;
+    setBase(emptyPathBase);
     testResolve("s://a/p2", "../p2");
     testResolve("s://a/", "../");
     testResolve("s://a/", "..");
@@ -324,7 +370,7 @@
     testResolve("s://a/p2", "../../p2");
     testResolve("s://a/p2", "../../././p2");
 
-    base = noAuthRelSinglePathBase;
+    setBase(noAuthRelSinglePathBase);
     testResolve("s:p2", "../p2");
     testResolve("s:", "../");
     testResolve("s:", "..");
@@ -337,31 +383,30 @@
     // B. if input buffer starts with "/./" or is "/.". replace with "/".
     // (The URI implementation removes the "." path segments when parsing,
     // so this case isn't handled by merge).
-    base = origBase;
+    setBase(b);
     testResolve("s://a/pa/p2", "./p2");
 
     // C. if input buffer starts with "/../" or is "/..", replace with "/"
     // and remove preceeding segment.
     testResolve("s://a/p2", "../p2");
-    var longPathBase = Uri.parse(b.replaceFirst("/pb", "/pb/pc/pd"));
-    base = longPathBase;
+    var longPathBase = b.replaceFirst("/pb", "/pb/pc/pd");
+    setBase(longPathBase);
     testResolve("s://a/pa/pb/p2", "../p2");
     testResolve("s://a/pa/p2", "../../p2");
     testResolve("s://a/p2", "../../../p2");
     testResolve("s://a/p2", "../../../../p2");
-    var noAuthRelLongPathBase =
-        Uri.parse(b.replaceFirst("//a/pa/pb", "pa/pb/pc/pd"));
-    base = noAuthRelLongPathBase;
+    var noAuthRelLongPathBase = b.replaceFirst("//a/pa/pb", "pa/pb/pc/pd");
+    setBase(noAuthRelLongPathBase);
     testResolve("s:pa/pb/p2", "../p2");
     testResolve("s:pa/p2", "../../p2");
     testResolve("s:/p2", "../../../p2");
     testResolve("s:/p2", "../../../../p2");
 
     // D. if the input buffer contains only ".." or ".", remove it.
-    base = noAuthEmptyPathBase;
+    setBase(noAuthEmptyPathBase);
     testResolve("s:", "..");
     testResolve("s:", ".");
-    base = noAuthRelSinglePathBase;
+    setBase(noAuthRelSinglePathBase);
     testResolve("s:", "..");
     testResolve("s:", ".");
   }
diff --git a/tests/language/disassemble_test.dart b/tests/language/disassemble_test.dart
index bdee5fff..cbea903 100644
--- a/tests/language/disassemble_test.dart
+++ b/tests/language/disassemble_test.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 // Dart test program for testing isolate communication with
 // typed objects.
-// VMOptions=--disassemble
+// VMOptions=--disassemble --no-background-compilation
 // VMOptions=--disassemble --print-variable-descriptors --no-background-compilation
 
 // Tests proper object recognition in disassembler.
diff --git a/tests/language/vm/lazy_deopt_with_exception_and_stacktrace_test.dart b/tests/language/vm/lazy_deopt_with_exception_and_stacktrace_test.dart
new file mode 100644
index 0000000..f67845a
--- /dev/null
+++ b/tests/language/vm/lazy_deopt_with_exception_and_stacktrace_test.dart
@@ -0,0 +1,70 @@
+// 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 catch (e, st) {
+    print(e);
+    print(st);
+    Expect.isTrue(st is StackTrace, "is StackTrace");
+  }
+  return c.x + 1;
+}
+
+
+@NeverInline
+T2(C c, bool b) {
+  try {
+    AA(c, b);
+  } on String catch(e, st) {
+    print(e);
+    print(st);
+    Expect.isTrue(st is StackTrace, "is StackTrace");
+    Expect.isTrue(false);
+  } on int catch(e, st) {
+    Expect.equals(e, 123);
+    Expect.equals(b, true);
+    Expect.equals(c.x, 2.5);
+    print(st);
+    Expect.isTrue(st is StackTrace, "is StackTrace");
+  }
+  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/utils/utils.status b/tests/utils/utils.status
index e2df361..acd7a5b 100644
--- a/tests/utils/utils.status
+++ b/tests/utils/utils.status
@@ -24,3 +24,6 @@
 [ $hot_reload || $hot_reload_rollback ]
 recursive_import_test: Skip # Running dart2js under frequent reloads is slow.
 dummy_compiler_test: Skip # Running dart2js under frequent reloads is slow.
+
+[ $builder_tag == asan ]
+recursive_import_test: Skip # Issue 27441
diff --git a/tools/VERSION b/tools/VERSION
index 07b5836..d6fd7e3 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 1
 MINOR 20
 PATCH 0
-PRERELEASE 9
+PRERELEASE 10
 PRERELEASE_PATCH 0
diff --git a/tools/deps/dartium.deps/DEPS b/tools/deps/dartium.deps/DEPS
index 2083c3a..fcd0c2f 100644
--- a/tools/deps/dartium.deps/DEPS
+++ b/tools/deps/dartium.deps/DEPS
@@ -8,7 +8,7 @@
 # Now we need to override some settings and add some new ones.
 
 vars.update({
-  "dartium_chromium_commit": "a8ead7ec922730667be7112de7ec40abbfd5f5aa",
+  "dartium_chromium_commit": "7558afb6379171d7f96b2db68ae9d2b64b2c5544",
   "dartium_webkit_commit": "b32a113c16f0a46b0dd747f80f0ec78e8db3512b",
   "chromium_base_revision": "338390",
 
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index b640ce3..220d3eb 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -1868,6 +1868,21 @@
                     DebugLogger.error("Unable to kill ${process.pid}");
                   }
                 });
+              } else if (io.Platform.isMacOS) {
+                // Try to print stack traces of the timed out process.
+                io.Process.run('/usr/bin/sample',
+                               ['${process.pid}', '1', '1', '-mayDie'])
+                .then((result) {
+                  io.stdout.write(result.stdout);
+                  io.stderr.write(result.stderr);
+                })
+                .catchError(
+                    (error) => print("Error when printing stack trace: $error"))
+                .whenComplete(() {
+                  if (!process.kill()) {
+                    DebugLogger.error("Unable to kill ${process.pid}");
+                  }
+                });
               } else {
                 if (!process.kill()) {
                   DebugLogger.error("Unable to kill ${process.pid}");