[vm] Look for the recognized pragma in the unboxer and signature shaker.

This removes the conservative exclusion of everything below num in the
unboxer, and it allows some methods marked as entry points to not be
entry points, as they are not actually referred explicitly in VM code.

TEST=Existing test suite.
Change-Id: If465b9081ac278a105ba99c23a49f5516b7bfbc0
Cq-Do-Not-Cancel-Tryjobs: true
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/169401
Commit-Queue: Aske Simon Christensen <askesc@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
diff --git a/pkg/front_end/testcases/nnbd/issue42546.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue42546.dart.outline.expect
index 0857ca0..de61651 100644
--- a/pkg/front_end/testcases/nnbd/issue42546.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/issue42546.dart.outline.expect
@@ -28,19 +28,19 @@
 
 
 Extra constant evaluation status:
-Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:662:13 -> SymbolConstant(#catchError)
-Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:662:13 -> ListConstant(const <Type*>[])
-Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:662:13 -> SymbolConstant(#test)
-Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:699:13 -> SymbolConstant(#whenComplete)
-Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:699:13 -> ListConstant(const <Type*>[])
-Evaluated: MapLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:699:13 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
-Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:726:13 -> SymbolConstant(#timeout)
-Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:726:13 -> ListConstant(const <Type*>[])
-Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:726:13 -> SymbolConstant(#onTimeout)
-Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:623:13 -> SymbolConstant(#then)
-Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:623:13 -> SymbolConstant(#onError)
-Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:710:13 -> SymbolConstant(#asStream)
-Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:710:13 -> ListConstant(const <Type*>[])
-Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:710:13 -> ListConstant(const <dynamic>[])
-Evaluated: MapLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:710:13 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:661:13 -> SymbolConstant(#catchError)
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:661:13 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:661:13 -> SymbolConstant(#test)
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:698:13 -> SymbolConstant(#whenComplete)
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:698:13 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:698:13 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:725:13 -> SymbolConstant(#timeout)
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:725:13 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:725:13 -> SymbolConstant(#onTimeout)
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:622:13 -> SymbolConstant(#then)
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:622:13 -> SymbolConstant(#onError)
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:709:13 -> SymbolConstant(#asStream)
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:709:13 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:709:13 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:709:13 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
 Extra constant evaluation: evaluated: 61, effectively constant: 15
diff --git a/pkg/vm/lib/transformations/pragma.dart b/pkg/vm/lib/transformations/pragma.dart
index ce3055b..d27f3d8 100644
--- a/pkg/vm/lib/transformations/pragma.dart
+++ b/pkg/vm/lib/transformations/pragma.dart
@@ -12,11 +12,14 @@
 const kNonNullableResultType = "vm:non-nullable-result-type";
 const kResultTypeUsesPassedTypeArguments =
     "result-type-uses-passed-type-arguments";
+const kRecognizedPragmaName = "vm:recognized";
 
 abstract class ParsedPragma {}
 
 enum PragmaEntryPointType { Default, GetterOnly, SetterOnly, CallOnly }
 
+enum PragmaRecognizedType { AsmIntrinsic, GraphIntrinsic, Other }
+
 class ParsedEntryPointPragma extends ParsedPragma {
   final PragmaEntryPointType type;
   ParsedEntryPointPragma(this.type);
@@ -38,6 +41,11 @@
   ParsedNonNullableResultType();
 }
 
+class ParsedRecognized extends ParsedPragma {
+  final PragmaRecognizedType type;
+  ParsedRecognized(this.type);
+}
+
 abstract class PragmaAnnotationParser {
   /// May return 'null' if the annotation does not represent a recognized
   /// @pragma.
@@ -118,6 +126,22 @@
             "pragma: $options";
       case kNonNullableResultType:
         return new ParsedNonNullableResultType();
+      case kRecognizedPragmaName:
+        PragmaRecognizedType type;
+        if (options is StringConstant) {
+          if (options.value == "asm-intrinsic") {
+            type = PragmaRecognizedType.AsmIntrinsic;
+          } else if (options.value == "graph-intrinsic") {
+            type = PragmaRecognizedType.GraphIntrinsic;
+          } else if (options.value == "other") {
+            type = PragmaRecognizedType.Other;
+          }
+        }
+        if (type == null) {
+          throw "ERROR: Unsupported option to '$kRecognizedPragmaName' "
+              "pragma: $options";
+        }
+        return new ParsedRecognized(type);
       default:
         return null;
     }
diff --git a/pkg/vm/lib/transformations/type_flow/native_code.dart b/pkg/vm/lib/transformations/type_flow/native_code.dart
index ba8a56d..2a67d18 100644
--- a/pkg/vm/lib/transformations/type_flow/native_code.dart
+++ b/pkg/vm/lib/transformations/type_flow/native_code.dart
@@ -217,6 +217,22 @@
   bool isMemberReferencedFromNativeCode(Member member) =>
       _membersReferencedFromNativeCode.contains(member);
 
+  PragmaRecognizedType recognizedType(Member member) {
+    for (var annotation in member.annotations) {
+      ParsedPragma pragma = _matcher.parsePragma(annotation);
+      if (pragma is ParsedRecognized) {
+        return pragma.type;
+      }
+    }
+    return null;
+  }
+
+  bool isRecognized(Member member, [List<PragmaRecognizedType> expectedTypes]) {
+    PragmaRecognizedType type = recognizedType(member);
+    return type != null &&
+        (expectedTypes == null || expectedTypes.contains(type));
+  }
+
   /// Simulate the execution of a native method by adding its entry points
   /// using [entryPointsListener]. Returns result type of the native method.
   TypeExpr handleNativeProcedure(
diff --git a/pkg/vm/lib/transformations/type_flow/signature_shaking.dart b/pkg/vm/lib/transformations/type_flow/signature_shaking.dart
index e1a947c..096acaf 100644
--- a/pkg/vm/lib/transformations/type_flow/signature_shaking.dart
+++ b/pkg/vm/lib/transformations/type_flow/signature_shaking.dart
@@ -160,6 +160,7 @@
         shaker.typeFlowAnalysis.isTearOffTaken(member) ||
         shaker.typeFlowAnalysis.nativeCodeOracle
             .isMemberReferencedFromNativeCode(member) ||
+        shaker.typeFlowAnalysis.nativeCodeOracle.isRecognized(member) ||
         getExternalName(member) != null) {
       info.eligible = false;
     }
diff --git a/pkg/vm/lib/transformations/type_flow/unboxing_info.dart b/pkg/vm/lib/transformations/type_flow/unboxing_info.dart
index f105c4f..792dc99 100644
--- a/pkg/vm/lib/transformations/type_flow/unboxing_info.dart
+++ b/pkg/vm/lib/transformations/type_flow/unboxing_info.dart
@@ -6,6 +6,7 @@
 import 'package:kernel/core_types.dart';
 import 'package:kernel/external_name.dart' show getExternalName;
 import 'package:vm/metadata/procedure_attributes.dart';
+import 'package:vm/transformations/pragma.dart';
 import 'package:vm/transformations/type_flow/analysis.dart';
 import 'package:vm/transformations/type_flow/calls.dart';
 import 'package:vm/transformations/type_flow/native_code.dart';
@@ -199,18 +200,11 @@
     // have boxed parameters and return values.
     return _isNative(member) ||
         _nativeCodeOracle.isMemberReferencedFromNativeCode(member) ||
-        _isEnclosingClassSubtypeOfNum(member);
+        _nativeCodeOracle.isRecognized(member, const [
+          PragmaRecognizedType.AsmIntrinsic,
+          PragmaRecognizedType.Other
+        ]);
   }
 
   bool _isNative(Member member) => getExternalName(member) != null;
-
-  // TODO(dartbug.com/33549): Calls to these methods could be replaced by
-  // CheckedSmiOpInstr, so in order to allow the parameters and return
-  // value to be unboxed, the slow path for such instructions should be
-  // updated to be consistent with the representations from the target interface.
-  bool _isEnclosingClassSubtypeOfNum(Member member) {
-    return (member.enclosingClass != null &&
-        ConeType(_typeHierarchy.getTFClass(member.enclosingClass))
-            .isSubtypeOf(_typeHierarchy, _coreTypes.numClass));
-  }
 }
diff --git a/runtime/vm/compiler/recognized_methods_list.h b/runtime/vm/compiler/recognized_methods_list.h
index 57b4bee..1f50840 100644
--- a/runtime/vm/compiler/recognized_methods_list.h
+++ b/runtime/vm/compiler/recognized_methods_list.h
@@ -13,7 +13,7 @@
 // debug mode to get the correct fingerprint from the mismatch error.
 #define OTHER_RECOGNIZED_LIST(V)                                               \
   V(::, identical, ObjectIdentical, 0x8fd6ea77)                                \
-  V(ClassID, getID, ClassIDgetID, 0x0401ffcc)                                  \
+  V(ClassID, getID, ClassIDgetID, 0x0401ffad)                                  \
   V(Object, Object., ObjectConstructor, 0x89c467da)                            \
   V(List, ., ListFactory, 0xbec87d52)                                          \
   V(_List, ., ObjectArrayAllocate, 0x6de199c0)                                 \
@@ -192,7 +192,7 @@
   V(::, reachabilityFence, ReachabilityFence, 0xad39d0c5)                      \
   V(_Utf8Decoder, _scan, Utf8DecoderScan, 0x288d0097)                          \
   V(_Future, timeout, FutureTimeout, 0xdea67277)                               \
-  V(Future, wait, FutureWait, 0x6c0c32b4)                                      \
+  V(Future, wait, FutureWait, 0x6c0c3295)                                      \
 
 // List of intrinsics:
 // (class-name, function-name, intrinsification method, fingerprint).
@@ -388,10 +388,10 @@
   V(::, _setAsyncThreadStackTrace, SetAsyncThreadStackTrace, 0x39346972)       \
 
 #define INTERNAL_LIB_INTRINSIC_LIST(V)                                         \
-  V(::, allocateOneByteString, AllocateOneByteString, 0xc86bec19)              \
-  V(::, allocateTwoByteString, AllocateTwoByteString, 0xd03127b6)              \
-  V(::, writeIntoOneByteString, WriteIntoOneByteString, 0xe0d28326)            \
-  V(::, writeIntoTwoByteString, WriteIntoTwoByteString, 0xd82789ef)            \
+  V(::, allocateOneByteString, AllocateOneByteString, 0xc86bebfa)              \
+  V(::, allocateTwoByteString, AllocateTwoByteString, 0xd0312797)              \
+  V(::, writeIntoOneByteString, WriteIntoOneByteString, 0xe0d28307)            \
+  V(::, writeIntoTwoByteString, WriteIntoTwoByteString, 0xd82789d0)            \
 
 #define ALL_INTRINSICS_NO_INTEGER_LIB_LIST(V)                                  \
   ASYNC_LIB_INTRINSIC_LIST(V)                                                  \
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 443daa2..b654d69 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -464,7 +464,6 @@
   V(controller, "controller")                                                  \
   V(current_character, ":current_character")                                   \
   V(current_position, ":current_position")                                     \
-  V(getID, "getID")                                                            \
   V(hashCode, "get:hashCode")                                                  \
   V(identityHashCode, "identityHashCode")                                      \
   V(index_temp, ":index_temp")                                                 \
@@ -486,7 +485,6 @@
   V(start_index_param, ":start_index_param")                                   \
   V(string_param, ":string_param")                                             \
   V(string_param_length, ":string_param_length")                               \
-  V(timeout, "timeout")                                                        \
   V(toString, "toString")                                                      \
   V(vm_prefer_inline, "vm:prefer-inline")                                      \
   V(vm_entry_point, "vm:entry-point")                                          \
diff --git a/sdk/lib/_internal/vm/lib/class_id_fasta.dart b/sdk/lib/_internal/vm/lib/class_id_fasta.dart
index 1028083..006314b 100644
--- a/sdk/lib/_internal/vm/lib/class_id_fasta.dart
+++ b/sdk/lib/_internal/vm/lib/class_id_fasta.dart
@@ -7,7 +7,6 @@
 @pragma("vm:entry-point")
 class ClassID {
   @pragma("vm:recognized", "other")
-  @pragma("vm:entry-point", "call")
   @pragma("vm:exact-result-type", "dart:core#_Smi")
   static int getID(Object value) native "ClassID_getID";
 
diff --git a/sdk/lib/_internal/vm/lib/internal_patch.dart b/sdk/lib/_internal/vm/lib/internal_patch.dart
index c303442..1566701 100644
--- a/sdk/lib/_internal/vm/lib/internal_patch.dart
+++ b/sdk/lib/_internal/vm/lib/internal_patch.dart
@@ -37,13 +37,11 @@
 
 /// The returned string is a [_OneByteString] with uninitialized content.
 @pragma("vm:recognized", "asm-intrinsic")
-@pragma("vm:entry-point", "call")
 String allocateOneByteString(int length)
     native "Internal_allocateOneByteString";
 
 /// The [string] must be a [_OneByteString]. The [index] must be valid.
 @pragma("vm:recognized", "asm-intrinsic")
-@pragma("vm:entry-point", "call")
 void writeIntoOneByteString(String string, int index, int codePoint)
     native "Internal_writeIntoOneByteString";
 
@@ -61,13 +59,11 @@
 
 /// The returned string is a [_TwoByteString] with uninitialized content.
 @pragma("vm:recognized", "asm-intrinsic")
-@pragma("vm:entry-point", "call")
 String allocateTwoByteString(int length)
     native "Internal_allocateTwoByteString";
 
 /// The [string] must be a [_TwoByteString]. The [index] must be valid.
 @pragma("vm:recognized", "asm-intrinsic")
-@pragma("vm:entry-point", "call")
 void writeIntoTwoByteString(String string, int index, int codePoint)
     native "Internal_writeIntoTwoByteString";
 
diff --git a/sdk/lib/async/future.dart b/sdk/lib/async/future.dart
index 0d64fc8..ed9a850 100644
--- a/sdk/lib/async/future.dart
+++ b/sdk/lib/async/future.dart
@@ -362,7 +362,6 @@
    * uncaught asynchronous error.
    */
   @pragma("vm:recognized", "other")
-  @pragma("vm:entry-point")
   static Future<List<T>> wait<T>(Iterable<Future<T>> futures,
       {bool eagerError = false, void cleanUp(T successValue)?}) {
     // This is a VM recognised method, and the _future variable is deliberately