Version 2.14.0-246.0.dev

Merge commit 'a44b4f5b62ac1bb3863d2ac0c915e8df8915517d' into 'dev'
diff --git a/pkg/dart2js_tools/lib/src/sourcemap_helper.dart b/pkg/dart2js_tools/lib/src/sourcemap_helper.dart
index 5b146b8..68ffd94 100644
--- a/pkg/dart2js_tools/lib/src/sourcemap_helper.dart
+++ b/pkg/dart2js_tools/lib/src/sourcemap_helper.dart
@@ -15,9 +15,9 @@
   if (sources == null) return null;
   SourceFile file = provider.fileFor(uri);
   SingleMapping mapping = provider.mappingFor(uri).sourceMap;
-  int index = start;
+  var index = start;
   while (true) {
-    index = sources.lastIndexOf('function', index);
+    index = nextDeclarationCandidate(sources, index);
     if (index < 0) return null;
     var line = file.getLine(index);
     var lineEntry = findLine(mapping, line);
@@ -33,6 +33,29 @@
   }
 }
 
+/// Returns the index of a candidate location of a enclosing function
+/// declaration. We try to find the beginning of a `function` keyword or the
+/// `(` of an ES6 method definition, but the search contains some false
+/// positives. To rule out false positives, [findEnclosingFunction]
+/// validates that the returned location contains a source-map entry, searching
+/// for another candidate if not.
+int nextDeclarationCandidate(String sources, int start) {
+  var indexForFunctionKeyword = sources.lastIndexOf('function', start);
+  // We attempt to identify potential method definitions by looking for any '('
+  // that precedes a '{'. This method will fail if 1) Dart2JS starts emitting
+  // functions with initializers or 2) sourcemap boundaries appear at '(' for
+  // non-method-definition constructs.
+  var indexForMethodDefinition = sources.lastIndexOf('{', start);
+  if (indexForFunctionKeyword > indexForMethodDefinition ||
+      indexForFunctionKeyword < 0) {
+    return indexForFunctionKeyword;
+  }
+  indexForMethodDefinition = sources.lastIndexOf('(', indexForMethodDefinition);
+  return indexForFunctionKeyword > indexForMethodDefinition
+      ? indexForFunctionKeyword
+      : indexForMethodDefinition;
+}
+
 /// Returns [TargetLineEntry] which includes the location in the target [line]
 /// number. In particular, the resulting entry is the last entry whose line
 /// number is lower or equal to [line].
diff --git a/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart b/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart
index 6fd9bb0..1e1f94d 100644
--- a/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart
+++ b/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart
@@ -447,10 +447,8 @@
     test('async method call', () async {
       await driver.check(
           breakpointId: 'globalFunctionBP',
-          expression: 'c.asyncMethod(2)',
-          expectedResult: '_Future.new {Symbol(_state): 1, '
-              'Symbol(_resultOrListeners): null, '
-              'Symbol(_zone): _RootZone {}');
+          expression: 'c.asyncMethod(2).runtimeType.toString()',
+          expectedResult: '_Future<int>');
     });
 
     test('extension method call', () async {
@@ -580,10 +578,8 @@
     test('async method call', () async {
       await driver.check(
           breakpointId: 'constructorBP',
-          expression: 'asyncMethod(2)',
-          expectedResult: '_Future.new {Symbol(_state): 1, '
-              'Symbol(_resultOrListeners): null, '
-              'Symbol(_zone): _RootZone {}');
+          expression: 'asyncMethod(2).runtimeType.toString()',
+          expectedResult: '_Future<int>');
     });
 
     test('extension method call', () async {
@@ -679,10 +675,8 @@
     test('awaited method call', () async {
       await driver.check(
           breakpointId: 'bp1',
-          expression: 'c.asyncMethod(1)',
-          expectedResult: '_Future.new {Symbol(_state): 1, '
-              'Symbol(_resultOrListeners): null, '
-              'Symbol(_zone): _RootZone {}');
+          expression: 'c.asyncMethod(1).runtimeType.toString()',
+          expectedResult: '_Future<int>');
     }, skip: "'await' is not yet supported in expression evaluation.");
 
     test('awaited method call', () async {
diff --git a/runtime/vm/heap/scavenger.cc b/runtime/vm/heap/scavenger.cc
index 820eeff..adbac5d 100644
--- a/runtime/vm/heap/scavenger.cc
+++ b/runtime/vm/heap/scavenger.cc
@@ -826,9 +826,15 @@
   void VisitPointers(ObjectPtr* from, ObjectPtr* to) {
     for (ObjectPtr* ptr = from; ptr <= to; ptr++) {
       ObjectPtr raw_obj = *ptr;
-      RELEASE_ASSERT(!raw_obj->untag()->IsCardRemembered());
       RELEASE_ASSERT(raw_obj->untag()->IsRemembered());
       RELEASE_ASSERT(raw_obj->IsOldObject());
+
+      RELEASE_ASSERT(!raw_obj->untag()->IsCardRemembered());
+      if (raw_obj.GetClassId() == kArrayCid) {
+        const uword length =
+            Smi::Value(static_cast<UntaggedArray*>(raw_obj.untag())->length());
+        RELEASE_ASSERT(!Array::UseCardMarkingForAllocation(length));
+      }
       in_store_buffer_->Add(raw_obj);
     }
   }
diff --git a/tools/VERSION b/tools/VERSION
index 8cc8b18..28ecc51 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 245
+PRERELEASE 246
 PRERELEASE_PATCH 0
\ No newline at end of file