Version 2.14.0-192.0.dev

Merge commit '7d44c20f2cecf21bafdcd3a3b54afede4b39ccae' into 'dev'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4d0c75a..70d7ff1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -186,7 +186,7 @@
     }
     ```
 
-## 2.13.2 - 2021-06-09
+## 2.13.3 - 2021-06-10
 
 This is a patch release that fixes:
 
diff --git a/pkg/front_end/test/binary_md_dill_reader.dart b/pkg/front_end/test/binary_md_dill_reader.dart
index d9a3d0e..7894e3c 100644
--- a/pkg/front_end/test/binary_md_dill_reader.dart
+++ b/pkg/front_end/test/binary_md_dill_reader.dart
@@ -6,6 +6,74 @@
 
 import "dart:math" as math;
 
+main() {
+  List<String> test = BinaryMdDillReader._getGenerics("Pair<A, B>");
+  if (test.length != 2 || test[0] != "A" || test[1] != "B") {
+    throw "Expected [A, B] got $test";
+  }
+
+  test = BinaryMdDillReader._getGenerics("List<Expression>");
+  if (test.length != 1 || test[0] != "Expression") {
+    throw "Expected [Expression] got $test";
+  }
+
+  test = BinaryMdDillReader._getGenerics("List<Pair<FileOffset, Expression>>");
+  if (test.length != 1 || test[0] != "Pair<FileOffset, Expression>") {
+    throw "Expected [Pair<FileOffset, Expression>] got $test";
+  }
+
+  test = BinaryMdDillReader._getGenerics("RList<Pair<UInt32, UInt32>>");
+  if (test.length != 1 || test[0] != "Pair<UInt32, UInt32>") {
+    throw "Expected [Pair<UInt32, UInt32>] got $test";
+  }
+
+  test =
+      BinaryMdDillReader._getGenerics("List<Pair<FieldReference, Expression>>");
+  if (test.length != 1 || test[0] != "Pair<FieldReference, Expression>") {
+    throw "Expected [Pair<FieldReference, Expression>] got $test";
+  }
+
+  test = BinaryMdDillReader._getGenerics(
+      "List<Pair<ConstantReference, ConstantReference>>");
+  if (test.length != 1 ||
+      test[0] != "Pair<ConstantReference, ConstantReference>") {
+    throw "Expected [Pair<ConstantReference, ConstantReference>] got $test";
+  }
+
+  test = BinaryMdDillReader._getGenerics(
+      "List<Pair<FieldReference, ConstantReference>>");
+  if (test.length != 1 ||
+      test[0] != "Pair<FieldReference, ConstantReference>") {
+    throw "Expected [Pair<FieldReference, ConstantReference>] got $test";
+  }
+
+  test = BinaryMdDillReader._getGenerics("Option<List<DartType>>");
+  if (test.length != 1 || test[0] != "List<DartType>") {
+    throw "Expected [List<DartType>] got $test";
+  }
+
+  test = BinaryMdDillReader._getGenerics("Foo<Bar<Baz>>");
+  if (test.length != 1 || test[0] != "Bar<Baz>") {
+    throw "Expected [Bar<Baz>] got $test";
+  }
+
+  test = BinaryMdDillReader._getGenerics("Foo<A, B<C, D>, E>");
+  if (test.length != 3 ||
+      test[0] != "A" ||
+      test[1] != "B<C, D>" ||
+      test[2] != "E") {
+    throw "Expected [A, B<C, D>, E] got $test";
+  }
+
+  test = BinaryMdDillReader._getGenerics("Foo<A, B<C, D<E<F<G>>>>, H>");
+  if (test.length != 3 ||
+      test[0] != "A" ||
+      test[1] != "B<C, D<E<F<G>>>>" ||
+      test[2] != "H") {
+    throw "Expected [A, B<C, D<E<F<G>>>>, H] got $test";
+  }
+}
+
 class BinaryMdDillReader {
   final String _binaryMdContent;
 
@@ -236,33 +304,50 @@
     return result;
   }
 
+  static const int $COMMA = 44;
+  static const int $LT = 60;
+  static const int $GT = 62;
+
   /// Extract the generics used in an input type, e.g. turns
   ///
-  /// * "Pair<A, B>" into ["A", "B"]
-  /// * "List<Expression>" into ["Expression"]
+  /// * "Pair<A, B>" into ["A", "B"].
+  /// * "List<Expression>" into ["Expression"].
+  /// * "Foo<Bar<Baz>>" into ["Bar<Baz>"].
+  /// * "Foo<A, B<C, D>, E>" into ["A", "B<C, D>", "E"].
   ///
   /// Note that the input string *has* to use generics, i.e. have '<' and '>'
   /// in it.
-  /// Also note that nested generics isn't really supported
-  /// (e.g. Foo<Bar<Baz>>).
-  List<String> _getGenerics(String s) {
+  static List<String> _getGenerics(String s) {
     s = s.substring(s.indexOf("<") + 1, s.lastIndexOf(">"));
-    if (s.contains("<")) {
-      if (s == "Pair<FileOffset, Expression>") {
-        return ["Pair<FileOffset, Expression>"];
-      } else if (s == "Pair<UInt32, UInt32>") {
-        return ["Pair<UInt32, UInt32>"];
-      } else if (s == "Pair<FieldReference, Expression>") {
-        return ["Pair<FieldReference, Expression>"];
-      } else if (s == "Pair<ConstantReference, ConstantReference>") {
-        return ["Pair<ConstantReference, ConstantReference>"];
-      } else if (s == "Pair<FieldReference, ConstantReference>") {
-        return ["Pair<FieldReference, ConstantReference>"];
+    // Check that any '<' and '>' are balanced and split entries on comma for
+    // the outermost parameters.
+    int ltCount = 0;
+    int gtCount = 0;
+    int depth = 0;
+    int lastPos = 0;
+
+    List<int> codeUnits = s.codeUnits;
+    List<String> result = [];
+    for (int i = 0; i < codeUnits.length; i++) {
+      int codeUnit = codeUnits[i];
+      if (codeUnit == $LT) {
+        ltCount++;
+        depth++;
+      } else if (codeUnit == $GT) {
+        gtCount++;
+        depth--;
+      } else if (codeUnit == $COMMA && depth == 0) {
+        result.add(s.substring(lastPos, i).trim());
+        lastPos = i + 1;
       }
-      throw "Doesn't supported nested generics (input: $s).";
     }
 
-    return s.split(",").map((untrimmed) => untrimmed.trim()).toList();
+    if (ltCount != gtCount) {
+      throw "Unbalanced '<' and '>': $s";
+    }
+    assert(depth == 0);
+    result.add(s.substring(lastPos, codeUnits.length).trim());
+    return result;
   }
 
   /// Parses a line of binary.md content for a "current class" into the
diff --git a/pkg/vm/lib/transformations/ffi_use_sites.dart b/pkg/vm/lib/transformations/ffi_use_sites.dart
index 1754be3..b213615 100644
--- a/pkg/vm/lib/transformations/ffi_use_sites.dart
+++ b/pkg/vm/lib/transformations/ffi_use_sites.dart
@@ -268,7 +268,7 @@
                     funcType.returnType, currentLibrary.isNonNullableByDefault),
                 node.fileOffset,
                 1,
-                node.location.file);
+                node.location?.file);
             return node;
           }
           node.arguments.positional.add(NullLiteral()..parent = node);
@@ -281,7 +281,7 @@
                     funcType.returnType, currentLibrary.isNonNullableByDefault),
                 node.fileOffset,
                 1,
-                node.location.file);
+                node.location?.file);
             return node;
           }
 
@@ -293,7 +293,7 @@
               !(exceptionalReturn is ConstantExpression &&
                   exceptionalReturn.constant is PrimitiveConstant)) {
             diagnosticReporter.report(messageFfiExpectedConstant,
-                node.fileOffset, 1, node.location.file);
+                node.fileOffset, 1, node.location?.file);
             return node;
           }
 
@@ -302,7 +302,7 @@
               (exceptionalReturn is ConstantExpression &&
                   exceptionalReturn.constant is NullConstant)) {
             diagnosticReporter.report(messageFfiExceptionalReturnNull,
-                node.fileOffset, 1, node.location.file);
+                node.fileOffset, 1, node.location?.file);
             return node;
           }
 
@@ -316,7 +316,7 @@
                     funcType.returnType, currentLibrary.isNonNullableByDefault),
                 exceptionalReturn.fileOffset,
                 1,
-                exceptionalReturn.location.file);
+                exceptionalReturn.location?.file);
             return node;
           }
         }
@@ -771,7 +771,7 @@
             nativeType, currentLibrary.isNonNullableByDefault),
         node.fileOffset,
         1,
-        node.location.file);
+        node.location?.file);
     throw _FfiStaticTypeError();
   }
 
@@ -788,7 +788,7 @@
               nativeType, currentLibrary.isNonNullableByDefault),
           node.fileOffset,
           1,
-          node.location.file);
+          node.location?.file);
       throw _FfiStaticTypeError();
     }
   }
@@ -815,7 +815,7 @@
         templateFfiNotStatic.withArguments(fromFunctionMethod.name.text),
         node.fileOffset,
         1,
-        node.location.file);
+        node.location?.file);
     throw _FfiStaticTypeError();
   }
 
@@ -866,7 +866,7 @@
               .withArguments(extended.name),
           klass.fileOffset,
           1,
-          klass.location.file);
+          klass.location?.file);
       throw _FfiStaticTypeError();
     }
   }
@@ -902,7 +902,7 @@
           templateFfiExpectedConstantArg.withArguments('isLeaf'),
           node.fileOffset,
           1,
-          node.location.file);
+          node.location?.file);
       // Throw so we don't get another error about not replacing
       // `lookupFunction`, which will shadow the above error.
       throw _FfiStaticTypeError();
@@ -924,14 +924,14 @@
       if (returnType is InterfaceType) {
         if (returnType.classNode == handleClass) {
           diagnosticReporter.report(messageFfiLeafCallMustNotReturnHandle,
-              node.fileOffset, 1, node.location.file);
+              node.fileOffset, 1, node.location?.file);
         }
       }
       // Check if any of the argument types are Handle.
       for (InterfaceType param in functionType.positionalParameters) {
         if (param.classNode == handleClass) {
           diagnosticReporter.report(messageFfiLeafCallMustNotTakeHandle,
-              node.fileOffset, 1, node.location.file);
+              node.fileOffset, 1, node.location?.file);
         }
       }
     }
diff --git a/tests/standalone/check_for_aot_snapshot_jit_test.dart b/tests/standalone/check_for_aot_snapshot_jit_test.dart
index a1dd29d..d8b817c 100644
--- a/tests/standalone/check_for_aot_snapshot_jit_test.dart
+++ b/tests/standalone/check_for_aot_snapshot_jit_test.dart
@@ -6,22 +6,38 @@
 import 'package:expect/expect.dart';
 import 'package:path/path.dart' as path;
 
+final _execSuffix = Platform.isWindows ? '.exe' : '';
+final _batchSuffix = Platform.isWindows ? '.bat' : '';
+
 main() {
   final buildDir = path.dirname(Platform.executable);
   final sdkDir = path.dirname(path.dirname(buildDir));
   final platformDill = path.join(buildDir, 'vm_platform_strong.dill');
-  final genSnapshot = path.join(buildDir, 'gen_snapshot');
+  final genKernel =
+      path.join(sdkDir, 'pkg', 'vm', 'tool', 'gen_kernel$_batchSuffix');
+  Expect.isTrue(File(genKernel).existsSync(),
+      "Can't locate gen_kernel$_batchSuffix on this platform");
+  Expect.isTrue(File(genKernel).existsSync(),
+      "Can't locate gen_kernel$_batchSuffix on this platform");
+  // Currently gen_snapshot is only in buildDir/clang_x64 on Mac ARM64.
+  final genSnapshot = Platform.isMacOS && buildDir.endsWith('XARM64')
+      ? path.join(buildDir, 'clang_x64', 'gen_snapshot$_execSuffix')
+      : path.join(buildDir, 'gen_snapshot$_execSuffix');
+  Expect.isTrue(File(genSnapshot).existsSync(),
+      "Can't locate gen_snapshot$_execSuffix on this platform");
 
-  final exePath = Platform.resolvedExecutable;
-  final genSnapshotPath =
-      Uri.parse(Platform.executable).resolve('gen_snapshot').path;
-  final powTest = Platform.script.resolve('pow_test.dart').path;
+  final exePath = path.join(buildDir, 'dart$_execSuffix');
+  Expect.isTrue(File(exePath).existsSync(),
+      "Can't locate dart$_execSuffix on this platform");
+  final powTest = path.join(sdkDir, 'tests', 'standalone_2', 'pow_test.dart');
+  Expect.isTrue(File(powTest).existsSync(),
+      "Can't locate dart$_execSuffix on this platform");
   final d = Directory.systemTemp.createTempSync('aot_tmp');
   final kernelOutput = d.uri.resolve('pow_test.dill').path;
   final aotOutput = d.uri.resolve('pow_test.aot').path;
 
   final genKernelResult = runAndPrintOutput(
-    'pkg/vm/tool/gen_kernel',
+    genKernel,
     [
       '--aot',
       '--platform=$platformDill',
@@ -44,20 +60,32 @@
   Expect.equals(genAotResult.exitCode, 0);
   print("Ran successfully.\n");
 
-  final runAotResult = runAndPrintOutput(
+  final runAotDirectlyResult = runAndPrintOutput(
+    exePath,
+    [
+      aotOutput,
+    ],
+  );
+  Expect.equals(runAotDirectlyResult.exitCode, 255);
+  Expect.contains(
+      "pow_test.aot is an AOT snapshot and should be run with 'dartaotruntime'",
+      runAotDirectlyResult.stderr);
+  print('Got expected error result.');
+
+  final runAotUsingCommandResult = runAndPrintOutput(
     exePath,
     [
       'run',
       aotOutput,
     ],
   );
-  Expect.equals(runAotResult.exitCode, 255);
-  Expect.stringContainsInOrder(
-    runAotResult.stderr,
-    [
-      "pow_test.aot is an AOT snapshot and should be run with 'dartaotruntime'",
-    ],
-  );
+  Expect.equals(runAotUsingCommandResult.exitCode, 255);
+  Expect.containsOneOf(<String>[
+    "pow_test.aot is an AOT snapshot and should be run with 'dartaotruntime'",
+    // If dartdev itself failed, can happen on SIMARM as not enough is built
+    // to run it.
+    "Failed to start the Dart CLI isolate",
+  ], runAotUsingCommandResult.stderr);
   print('Got expected error result.');
 }
 
diff --git a/tests/standalone/standalone_vm.status b/tests/standalone/standalone_vm.status
index 0be969a..6a36f12 100644
--- a/tests/standalone/standalone_vm.status
+++ b/tests/standalone/standalone_vm.status
@@ -3,6 +3,7 @@
 # BSD-style license that can be found in the LICENSE file.
 
 [ $arch == ia32 ]
+check_for_aot_snapshot_jit_test: SkipByDesign # No AOT mode on IA32.
 link_natives_lazily_test: SkipByDesign # Not supported.
 no_allow_absolute_addresses_test: SkipByDesign # Not supported.
 
diff --git a/tests/standalone_2/check_for_aot_snapshot_jit_test.dart b/tests/standalone_2/check_for_aot_snapshot_jit_test.dart
index dc6dbc1..e9c3e24 100644
--- a/tests/standalone_2/check_for_aot_snapshot_jit_test.dart
+++ b/tests/standalone_2/check_for_aot_snapshot_jit_test.dart
@@ -8,22 +8,36 @@
 import 'package:expect/expect.dart';
 import 'package:path/path.dart' as path;
 
+final _execSuffix = Platform.isWindows ? '.exe' : '';
+final _batchSuffix = Platform.isWindows ? '.bat' : '';
+
 main() {
   final buildDir = path.dirname(Platform.executable);
   final sdkDir = path.dirname(path.dirname(buildDir));
   final platformDill = path.join(buildDir, 'vm_platform_strong.dill');
-  final genSnapshot = path.join(buildDir, 'gen_snapshot');
+  final genKernel =
+      path.join(sdkDir, 'pkg', 'vm', 'tool', 'gen_kernel$_batchSuffix');
+  Expect.isTrue(File(genKernel).existsSync(),
+      "Can't locate gen_kernel$_batchSuffix on this platform");
+  // Currently gen_snapshot is only in buildDir/clang_x64 on Mac ARM64.
+  final genSnapshot = Platform.isMacOS && buildDir.endsWith('XARM64')
+      ? path.join(buildDir, 'clang_x64', 'gen_snapshot$_execSuffix')
+      : path.join(buildDir, 'gen_snapshot$_execSuffix');
+  Expect.isTrue(File(genSnapshot).existsSync(),
+      "Can't locate gen_snapshot$_execSuffix on this platform");
 
-  final exePath = Platform.resolvedExecutable;
-  final genSnapshotPath =
-      Uri.parse(Platform.executable).resolve('gen_snapshot').path;
-  final powTest = Platform.script.resolve('pow_test.dart').path;
+  final exePath = path.join(buildDir, 'dart$_execSuffix');
+  Expect.isTrue(File(exePath).existsSync(),
+      "Can't locate dart$_execSuffix on this platform");
+  final powTest = path.join(sdkDir, 'tests', 'standalone_2', 'pow_test.dart');
+  Expect.isTrue(File(powTest).existsSync(),
+      "Can't locate dart$_execSuffix on this platform");
   final d = Directory.systemTemp.createTempSync('aot_tmp');
   final kernelOutput = d.uri.resolve('pow_test.dill').path;
   final aotOutput = d.uri.resolve('pow_test.aot').path;
 
   final genKernelResult = runAndPrintOutput(
-    'pkg/vm/tool/gen_kernel',
+    genKernel,
     [
       '--aot',
       '--platform=$platformDill',
@@ -46,20 +60,32 @@
   Expect.equals(genAotResult.exitCode, 0);
   print("Ran successfully.\n");
 
-  final runAotResult = runAndPrintOutput(
+  final runAotDirectlyResult = runAndPrintOutput(
+    exePath,
+    [
+      aotOutput,
+    ],
+  );
+  Expect.equals(runAotDirectlyResult.exitCode, 255);
+  Expect.contains(
+      "pow_test.aot is an AOT snapshot and should be run with 'dartaotruntime'",
+      runAotDirectlyResult.stderr);
+  print('Got expected error result.');
+
+  final runAotUsingCommandResult = runAndPrintOutput(
     exePath,
     [
       'run',
       aotOutput,
     ],
   );
-  Expect.equals(runAotResult.exitCode, 255);
-  Expect.stringContainsInOrder(
-    runAotResult.stderr,
-    [
-      "pow_test.aot is an AOT snapshot and should be run with 'dartaotruntime'",
-    ],
-  );
+  Expect.equals(runAotUsingCommandResult.exitCode, 255);
+  Expect.containsOneOf(<String>[
+    "pow_test.aot is an AOT snapshot and should be run with 'dartaotruntime'",
+    // If dartdev itself failed, can happen on SIMARM as not enough is built
+    // to run it.
+    "Failed to start the Dart CLI isolate",
+  ], runAotUsingCommandResult.stderr);
   print('Got expected error result.');
 }
 
diff --git a/tests/standalone_2/standalone_2_vm.status b/tests/standalone_2/standalone_2_vm.status
index 0727563..4d8d63c 100644
--- a/tests/standalone_2/standalone_2_vm.status
+++ b/tests/standalone_2/standalone_2_vm.status
@@ -3,6 +3,7 @@
 # BSD-style license that can be found in the LICENSE file.
 
 [ $arch == ia32 ]
+check_for_aot_snapshot_jit_test: SkipByDesign # No AOT mode on IA32.
 link_natives_lazily_test: SkipByDesign # Not supported.
 no_allow_absolute_addresses_test: SkipByDesign # Not supported.
 
diff --git a/tools/VERSION b/tools/VERSION
index 9251a79..4caf537 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 191
+PRERELEASE 192
 PRERELEASE_PATCH 0
\ No newline at end of file