[vm] Support redirecting external const factories

This CL introduces the first combination of `external const factory`
with `@patch const factory (.*) = (.*)`. This specific combination was
never used in the core libraries, and did not work.

Half of the fix is a missing flag from the CFE:
https://dart-review.googlesource.com/c/sdk/+/187440

The other half of the fix is matching on the
kRedirectingFactoryConstructor tag, and allowing constructor names
in procedure targets (even though we never compile those expressions
because they are invalid).

Bug: https://github.com/dart-lang/sdk/issues/45101

TEST=Using redirecting const factory in patch file in core lib.
TEST=tests/ffi(_2)/*

Change-Id: I5524bde928290bf32aaea9170eda1f2d03127fa6
Cq-Include-Trybots: luci.dart.try:benchmark-linux-try,front-end-linux-release-x64-try,vm-kernel-linux-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/187003
Commit-Queue: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
Reviewed-by: Clement Skau <cskau@google.com>
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.expect
index 910440d..fa7c510 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.expect
@@ -24,4 +24,4 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_struct_inline_array.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:107:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/ffi_patch.dart:133:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.transformed.expect
index 494a391..77d29d6 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.transformed.expect
@@ -50,4 +50,4 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_struct_inline_array.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:107:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/ffi_patch.dart:133:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.expect
index e502c15..5125b89 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.expect
@@ -24,4 +24,4 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_struct_inline_array.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:107:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/ffi_patch.dart:133:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.transformed.expect
index c9607e0..bd41225 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.transformed.expect
@@ -50,4 +50,4 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_struct_inline_array.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:107:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/ffi_patch.dart:133:9)
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 1bb096e..e3708c8 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -229,7 +229,8 @@
 
     bool has_field_initializers = false;
     for (intptr_t i = 0; i < list_length; ++i) {
-      if (PeekTag() == kRedirectingInitializer) {
+      if (PeekTag() == kRedirectingInitializer ||
+          PeekTag() == kRedirectingFactoryConstructor) {
         is_redirecting_constructor = true;
       } else if (PeekTag() == kFieldInitializer) {
         has_field_initializers = true;
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index 06aeae2..1da5a95 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -433,15 +433,18 @@
 }
 
 const String& TranslationHelper::DartProcedureName(NameIndex procedure) {
-  ASSERT(IsProcedure(procedure));
+  ASSERT(IsProcedure(procedure) || IsConstructor(procedure));
   if (IsSetter(procedure)) {
     return DartSetterName(procedure);
   } else if (IsGetter(procedure)) {
     return DartGetterName(procedure);
   } else if (IsFactory(procedure)) {
     return DartFactoryName(procedure);
-  } else {
+  } else if (IsMethod(procedure)) {
     return DartMethodName(procedure);
+  } else {
+    ASSERT(IsConstructor(procedure));
+    return DartConstructorName(procedure);
   }
 }
 
diff --git a/sdk/lib/_internal/vm/lib/ffi_patch.dart b/sdk/lib/_internal/vm/lib/ffi_patch.dart
index ed93ed2..38dbcda 100644
--- a/sdk/lib/_internal/vm/lib/ffi_patch.dart
+++ b/sdk/lib/_internal/vm/lib/ffi_patch.dart
@@ -122,6 +122,15 @@
       throw RangeError.range(index, 0, _size);
     }
   }
+
+  @patch
+  const factory Array(int dimension1) = _ArraySize<T>;
+}
+
+class _ArraySize<T extends NativeType> implements Array<T> {
+  final int dimension1;
+
+  const _ArraySize(this.dimension1);
 }
 
 /// Returns an integer encoding the ABI used for size and alignment
diff --git a/sdk/lib/ffi/ffi.dart b/sdk/lib/ffi/ffi.dart
index e747811..8510065 100644
--- a/sdk/lib/ffi/ffi.dart
+++ b/sdk/lib/ffi/ffi.dart
@@ -97,14 +97,7 @@
   /// ```
   ///
   /// Do not invoke in normal code.
-  const factory Array(int dimension1) = _ArraySize<T>;
-}
-
-// TODO(http://dartbug.com/45101): Move to ffi_patch.dart.
-class _ArraySize<T extends NativeType> implements Array<T> {
-  final int dimension1;
-
-  const _ArraySize(this.dimension1);
+  external const factory Array(int dimension1);
 }
 
 /// Extension on [Pointer] specialized for the type argument [NativeFunction].