[vm] Avoid expensive runtime function type checks in Future implementation

The `_FutureListener.callback` field is used for multiple purposes
(possibly to save memory by avoiding additional fields) so it cannot
have a specific function type.

This causes the `Function?` typed `_FutureListener.callback` field to be
casted to proper function types such as `T Function(S)`.
=> Those runtime type checks are very expensive.

To avoid introducing more fields we use an `unsafeCast<T>()` for those
casts, since the implementation guarantees they are going to suceed.

Issue https://github.com/dart-lang/sdk/issues/48225

TEST=ci

Change-Id: I6f0cc87600462c8ca5baceeb511ce8a06c61237e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/230240
Reviewed-by: Nicholas Shahan <nshahan@google.com>
Reviewed-by: Lasse Nielsen <lrn@google.com>
Commit-Queue: Martin Kustermann <kustermann@google.com>
diff --git a/pkg/front_end/testcases/general/external_import.dart.weak.expect b/pkg/front_end/testcases/general/external_import.dart.weak.expect
index 0d7662f..5e7e2df 100644
--- a/pkg/front_end/testcases/general/external_import.dart.weak.expect
+++ b/pkg/front_end/testcases/general/external_import.dart.weak.expect
@@ -37,5 +37,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///external_import.dart:
-- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:92:9)
+- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:109:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/external_import.dart.weak.modular.expect b/pkg/front_end/testcases/general/external_import.dart.weak.modular.expect
index 0d7662f..5e7e2df 100644
--- a/pkg/front_end/testcases/general/external_import.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/general/external_import.dart.weak.modular.expect
@@ -37,5 +37,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///external_import.dart:
-- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:92:9)
+- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:109:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/external_import.dart.weak.transformed.expect b/pkg/front_end/testcases/general/external_import.dart.weak.transformed.expect
index 0d7662f..5e7e2df 100644
--- a/pkg/front_end/testcases/general/external_import.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/external_import.dart.weak.transformed.expect
@@ -37,5 +37,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///external_import.dart:
-- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:92:9)
+- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:109:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.expect b/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.expect
index 7670aed..b24cb95 100644
--- a/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.expect
+++ b/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.expect
@@ -42,5 +42,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///native_is_illegal.dart:
-- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:92:9)
+- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:109:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.modular.expect b/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.modular.expect
index 7670aed..b24cb95 100644
--- a/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.modular.expect
@@ -42,5 +42,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///native_is_illegal.dart:
-- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:92:9)
+- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:109:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.transformed.expect b/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.transformed.expect
index 7670aed..b24cb95 100644
--- a/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.transformed.expect
@@ -42,5 +42,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///native_is_illegal.dart:
-- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:92:9)
+- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:109:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/internal_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/internal_patch.dart
index f4ab556..ca3bd4f 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/internal_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/internal_patch.dart
@@ -62,3 +62,6 @@
 
 @patch
 bool isSentinel(dynamic value) => throw UnsupportedError('isSentinel');
+
+@patch
+T unsafeCast<T>(dynamic v) => v;
diff --git a/sdk/lib/_internal/js_runtime/lib/internal_patch.dart b/sdk/lib/_internal/js_runtime/lib/internal_patch.dart
index 9bf6da6..ef27959 100644
--- a/sdk/lib/_internal/js_runtime/lib/internal_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/internal_patch.dart
@@ -73,3 +73,7 @@
 @patch
 @pragma('dart2js:tryInline')
 bool isSentinel(dynamic value) => isJsSentinel(value);
+
+@patch
+@pragma('dart2js:tryInline')
+T unsafeCast<T>(dynamic v) => v;
diff --git a/sdk/lib/_internal/vm/lib/internal_patch.dart b/sdk/lib/_internal/vm/lib/internal_patch.dart
index b8141d6..3d7a3cd8f 100644
--- a/sdk/lib/_internal/vm/lib/internal_patch.dart
+++ b/sdk/lib/_internal/vm/lib/internal_patch.dart
@@ -156,13 +156,9 @@
   return newStack;
 }
 
-// This function can be used to skip implicit or explicit checked down casts in
-// the parts of the core library implementation where we know by construction the
-// type of a value.
-//
-// Important: this is unsafe and must be used with care.
+@patch
 @pragma("vm:external-name", "Internal_unsafeCast")
-external T unsafeCast<T>(Object? v);
+external T unsafeCast<T>(dynamic v);
 
 // This function can be used to keep an object alive till that point.
 @pragma("vm:recognized", "other")
diff --git a/sdk/lib/async/async.dart b/sdk/lib/async/async.dart
index 0b16dae..ca05fc6 100644
--- a/sdk/lib/async/async.dart
+++ b/sdk/lib/async/async.dart
@@ -114,7 +114,8 @@
         printToZone,
         printToConsole,
         Since,
-        typeAcceptsNull;
+        typeAcceptsNull,
+        unsafeCast;
 
 part 'async_error.dart';
 part 'broadcast_stream_controller.dart';
diff --git a/sdk/lib/async/future_impl.dart b/sdk/lib/async/future_impl.dart
index 4d13cc8..26cfecd 100644
--- a/sdk/lib/async/future_impl.dart
+++ b/sdk/lib/async/future_impl.dart
@@ -4,15 +4,6 @@
 
 part of dart.async;
 
-/// The onValue and onError handlers return either a value or a future
-typedef FutureOr<T> _FutureOnValue<S, T>(S value);
-
-/// Test used by [Future.catchError] to handle skip some errors.
-typedef bool _FutureErrorTest(Object error);
-
-/// Used by [WhenFuture].
-typedef dynamic _FutureAction();
-
 abstract class _Completer<T> implements Completer<T> {
   final _Future<T> future = new _Future<T>();
 
@@ -106,7 +97,7 @@
         state = (errorCallback == null) ? stateThen : stateThenOnerror;
 
   _FutureListener.thenAwait(
-      this.result, _FutureOnValue<S, T> onValue, Function errorCallback)
+      this.result, FutureOr<T> Function(S) onValue, Function errorCallback)
       : callback = onValue,
         errorCallback = errorCallback,
         state = stateThenOnerror;
@@ -127,19 +118,19 @@
 
   FutureOr<T> Function(S) get _onValue {
     assert(handlesValue);
-    return callback as dynamic;
+    return unsafeCast<FutureOr<T> Function(S)>(callback);
   }
 
   Function? get _onError => errorCallback;
 
-  _FutureErrorTest get _errorTest {
+  bool Function(Object) get _errorTest {
     assert(hasErrorTest);
-    return callback as dynamic;
+    return unsafeCast<bool Function(Object)>(callback);
   }
 
-  _FutureAction get _whenCompleteAction {
+  dynamic Function() get _whenCompleteAction {
     assert(handlesComplete);
-    return callback as dynamic;
+    return unsafeCast<dynamic Function()>(callback);
   }
 
   /// Whether this listener has an error callback.
diff --git a/sdk/lib/internal/internal.dart b/sdk/lib/internal/internal.dart
index 5d38bd8..a7a7eda 100644
--- a/sdk/lib/internal/internal.dart
+++ b/sdk/lib/internal/internal.dart
@@ -35,6 +35,23 @@
 // execution mode.
 external bool typeAcceptsNull<T>();
 
+/// Unsafely treats [value] as type [T].
+///
+/// An unsafe cast allows casting any value to any type,
+/// without any runtime type checks.
+///
+/// Can be used internally in platform library implementations of
+/// data structures, where a value is known to have a type different
+/// from its static type (like knowing that a string is definitely
+/// a "_OneByteString" or that the value stored into a heterogenous
+/// list is really a value of the surrounding map).
+///
+/// Must only be used for casts which would definitely *succeed*
+/// as a normal cast.
+///
+/// Should only be used for performance in performance critical code.
+external T unsafeCast<T>(dynamic value);
+
 // Powers of 10 up to 10^22 are representable as doubles.
 // Powers of 10 above that are only approximate due to lack of precission.
 // Used by double-parsing.