Revert "[VM] Add @pragma annotations on Field, make @pragma annotations work generally"

This reverts commit 2de63ac01c3f092b24da50d1080617f3244e7b05.

Reason for revert: This triggers shutdown deadlocks for some reason:

#0  0xf7782cd9 __kernel_vsyscall
#1  0xf7753d0b pthread_cond_wait@@GLIBC_2.3.2
#2  0x0108a515 dart::Monitor::WaitMicros(long long)
#3  0x0108a467 dart::Monitor::Wait(long long)
#4  0x00fe9048 dart::KernelIsolate::Shutdown()
#5  0x00f99ae4 dart::Dart::Cleanup()
#6  0x01278fce Dart_Cleanup
#7  0x00dd347e dart::bin::main(int, char**)
#8  0x00dd3d64 main
#9  0xf745caf3 __libc_start_main
#10 0x00dd2021 _start
TID 30443:
#0  0xf7782cd9 __kernel_vsyscall
#1  0xf7531ee6 epoll_wait
#2  0x00ddab61 dart::bin::EventHandlerImplementation::Poll(unsigned int)
#3  0x00dfb2d4 dart::bin::ThreadStart(void*)
#4  0xf774ff72 start_thread
#5  0xf753143e __clone
TID 30444:
#0  0xf7782cd9 __kernel_vsyscall
#1  0xf7753d0b pthread_cond_wait@@GLIBC_2.3.2
#2  0x0108a515 dart::Monitor::WaitMicros(long long)
#3  0x0108a467 dart::Monitor::Wait(long long)
#4  0x012484d8 dart::BackgroundCompiler::Run()
#5  0x01248a37 dart::BackgroundCompilerTask::Run()
#6  0x0112203a dart::ThreadPool::Worker::Loop()
#7  0x01121efe dart::ThreadPool::Worker::Main(unsigned int)
#8  0x01089e73 dart::ThreadStart(void*)
#9  0xf774ff72 start_thread
#10 0xf753143e __clone

Original change's description:
> [VM] Add @pragma annotations on Field, make @pragma annotations work generally
> 
> Currently the @pramga('vm:exact-result-type') annotation only works if
> the function is a recognized method.  This change changes that to make
> the VM just look if a function has the annotation (no matter if it's
> also in the list of recognized methods or not).
> 
> Furthermore this CL adds a "has_pragma" bit to [Field] objects, similar
> to how we have it on [Function]/[Class]es.  This allows annotating
> fields with types, as we do with function return types.
> 
> Furthermore this CL lets the type propgagator use
> @pragma('vm:exact-result-type') annotations to narrow the [CompileType]
> set on [LoadFieldInstr]s.
> 
> Since the @pragma is a general feature, this CL moves the
> `Function::FindPragma()` to `Library::FindPragma` (which is where any
> other metadata lookup happens).  We also let the `FindPragma` accept any
> of Class/Function/Field objects.
> 
> Furthermore this CL adds a bailout if we try to evaluate metadata in
> the background compiler, since the background compiler is not allowed
> to execute generated code. The bailout should trigger a re-compilation
> on the mutator thread.
> 
> Furthermore the `FindPragma()` function is fixed to handle the case
> when the evaluation of the metadata results in e.g. a language error.
> In this case we simply claim to not have found a pragma annotation.
> 
> Issue https://github.com/dart-lang/sdk/issues/31954
> 
> Change-Id: I0900a80d5ae0f3e8d09baf13cba1b20dd974df31
> Reviewed-on: https://dart-review.googlesource.com/c/84037
> Commit-Queue: Martin Kustermann <kustermann@google.com>
> Reviewed-by: Alexander Markov <alexmarkov@google.com>
> Reviewed-by: Vyacheslav Egorov <vegorov@google.com>

TBR=vegorov@google.com,kustermann@google.com,alexmarkov@google.com,sjindel@google.com

Change-Id: Ic0d22d32b0eea3a76ec245cabab0006f97ca1b05
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://dart-review.googlesource.com/c/84622
Reviewed-by: Martin Kustermann <kustermann@google.com>
diff --git a/runtime/bin/platform_patch.dart b/runtime/bin/platform_patch.dart
index 99b4e7c..dd7d88a 100644
--- a/runtime/bin/platform_patch.dart
+++ b/runtime/bin/platform_patch.dart
@@ -5,7 +5,6 @@
 // part of "common_patch.dart";
 
 @patch
-@pragma("vm:entry-point")
 class _Platform {
   @patch
   static int _numberOfProcessors() native "Platform_NumberOfProcessors";
diff --git a/runtime/bin/process_patch.dart b/runtime/bin/process_patch.dart
index 373eb7d..375fb93 100644
--- a/runtime/bin/process_patch.dart
+++ b/runtime/bin/process_patch.dart
@@ -192,7 +192,6 @@
   static _currentRss() native "ProcessInfo_CurrentRSS";
 }
 
-@pragma("vm:entry-point")
 class _ProcessStartStatus {
   @pragma("vm:entry-point", "set")
   int _errorCode; // Set to OS error code if process start failed.
diff --git a/runtime/bin/secure_socket_patch.dart b/runtime/bin/secure_socket_patch.dart
index 876e789..5d61f88 100644
--- a/runtime/bin/secure_socket_patch.dart
+++ b/runtime/bin/secure_socket_patch.dart
@@ -64,7 +64,6 @@
  * are backed by an external C array of bytes, so that both Dart code and
  * native code can access the same data.
  */
-@pragma("vm:entry-point")
 class _SecureFilterImpl extends NativeFieldWrapperClass1
     implements _SecureFilter {
   // Performance is improved if a full buffer of plaintext fits
diff --git a/runtime/docs/compiler/result_type_pragma.md b/runtime/docs/compiler/result_type_pragma.md
index 8c72b13..2bc5032 100644
--- a/runtime/docs/compiler/result_type_pragma.md
+++ b/runtime/docs/compiler/result_type_pragma.md
@@ -5,9 +5,6 @@
 the return type in the signature of the method. There are three limitations on
 this pragma:
 
-Similarly if a field is marked with the same annotation it must be guaranteed
-that a load from the field returns in the specified exact result type.
-
 0. The Dart object returned by the method at runtime must have exactly the type
 specified in the annotation (not a subtype).
 
@@ -35,11 +32,6 @@
 
 @pragma('vm:exact-result-type', B)
 A foo() native 'foo_impl';
-
-class C {
-  @pragma('vm:exact-result-type', int)
-  final int value;
-}
 ```
 
 ### Reference to type via path
@@ -47,10 +39,4 @@
 ```dart
 @pragma('vm:exact-result-type', 'dart:core#_Smi');
 int foo() native 'foo_impl';
-
-class C {
-  @pragma('vm:exact-result-type', 'dart:core#_Smi')
-  final int value;
-}
-
 ```
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index daa7248..f9f3441 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -1001,7 +1001,7 @@
         s->Write<int32_t>(field->ptr()->kernel_offset_);
 #endif
       }
-      s->Write<uint16_t>(field->ptr()->kind_bits_);
+      s->Write<uint8_t>(field->ptr()->kind_bits_);
     }
   }
 
@@ -1053,7 +1053,7 @@
         field->ptr()->kernel_offset_ = d->Read<int32_t>();
 #endif
       }
-      field->ptr()->kind_bits_ = d->Read<uint16_t>();
+      field->ptr()->kind_bits_ = d->Read<uint8_t>();
     }
   }
 
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index 009dc8c..216bdb5 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -1019,22 +1019,20 @@
     while (it.HasNext()) {
       cls = it.GetNextClass();
 
-      // Check for @pragma on the class itself.
       if (cls.has_pragma()) {
+        // Check for @pragma on the class itself.
         metadata ^= lib.GetMetadata(cls);
         if (metadata_defines_entrypoint() == EntryPointPragma::kAlways) {
           AddInstantiatedClass(cls);
         }
-      }
 
-      // Check for @pragma on any fields in the class.
-      members = cls.fields();
-      implicit_getters = GrowableObjectArray::New(members.Length());
-      implicit_setters = GrowableObjectArray::New(members.Length());
-      implicit_static_getters = GrowableObjectArray::New(members.Length());
-      for (intptr_t k = 0; k < members.Length(); ++k) {
-        field ^= members.At(k);
-        if (field.has_pragma()) {
+        // Check for @pragma on any fields in the class.
+        members = cls.fields();
+        implicit_getters = GrowableObjectArray::New(members.Length());
+        implicit_setters = GrowableObjectArray::New(members.Length());
+        implicit_static_getters = GrowableObjectArray::New(members.Length());
+        for (intptr_t k = 0; k < members.Length(); ++k) {
+          field ^= members.At(k);
           metadata ^= lib.GetMetadata(field);
           if (metadata.IsNull()) continue;
           EntryPointPragma pragma = metadata_defines_entrypoint();
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index 0f4e459..7133e1f 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -1188,11 +1188,8 @@
 CompileType PolymorphicInstanceCallInstr::ComputeType() const {
   if (IsSureToCallSingleRecognizedTarget()) {
     const Function& target = *targets_.TargetAt(0)->target;
-    if (target.has_pragma()) {
-      const intptr_t cid = MethodRecognizer::ResultCidFromPragma(target);
-      if (cid != kDynamicCid) {
-        return CompileType::FromCid(cid);
-      }
+    if (target.recognized_kind() != MethodRecognizer::kUnknown) {
+      return CompileType::FromCid(MethodRecognizer::ResultCid(target));
     }
   }
 
@@ -1214,11 +1211,8 @@
     return *inferred_type;
   }
 
-  if (function_.has_pragma()) {
-    const intptr_t cid = MethodRecognizer::ResultCidFromPragma(function_);
-    if (cid != kDynamicCid) {
-      return CompileType::FromCid(cid);
-    }
+  if (function_.recognized_kind() != MethodRecognizer::kUnknown) {
+    return CompileType::FromCid(MethodRecognizer::ResultCid(function_));
   }
 
   const Isolate* isolate = Isolate::Current();
@@ -1332,15 +1326,8 @@
     return CompileType::Dynamic();
   }
 
-  bool is_nullable = CompileType::kNullable;
-  if (field_ != nullptr && field_->has_pragma()) {
-    const intptr_t cid = MethodRecognizer::ResultCidFromPragma(*field_);
-    if (cid != kDynamicCid) {
-      return CompileType::FromCid(cid);
-    }
-  }
-
   const Isolate* isolate = Isolate::Current();
+  bool is_nullable = CompileType::kNullable;
   intptr_t cid = kDynamicCid;
   const AbstractType* abstract_type = NULL;
   if (isolate->can_use_strong_mode_types() ||
@@ -1353,7 +1340,7 @@
   if ((field_ != NULL) && (field_->guarded_cid() != kIllegalCid) &&
       (field_->guarded_cid() != kDynamicCid)) {
     cid = field_->guarded_cid();
-    is_nullable = is_nullable && field_->is_nullable();
+    is_nullable = field_->is_nullable();
     abstract_type = nullptr;  // Cid is known, calculate abstract type lazily.
   } else {
     cid = result_cid_;
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 77ebfa6..4f8b6dd 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -1642,30 +1642,25 @@
 Fragment StreamingFlowGraphBuilder::BuildEntryPointsIntrospection() {
   if (!FLAG_enable_testing_pragmas) return Drop();
 
-  auto& function = Function::Handle(Z, parsed_function()->function().raw());
+  Function& function = Function::Handle(parsed_function()->function().raw());
 
   if (function.IsImplicitClosureFunction()) {
-    const auto& parent = Function::Handle(Z, function.parent_function());
-    const auto& func_name = String::Handle(Z, parent.name());
-    const auto& owner = Class::Handle(Z, parent.Owner());
+    const Function& parent =
+        Function::ZoneHandle(Z, function.parent_function());
+    const String& func_name = String::ZoneHandle(Z, parent.name());
+    const Class& owner = Class::ZoneHandle(Z, parent.Owner());
     function = owner.LookupFunction(func_name);
   }
 
-  auto& tmp = Object::Handle(Z);
-  tmp = function.Owner();
-  tmp = Class::Cast(tmp).library();
-  auto& library = Library::Cast(tmp);
-
-  Object& options = Object::Handle(Z);
-  if (!library.FindPragma(H.thread(), function, Symbols::vm_trace_entrypoints(),
-                          &options) ||
+  Object& options = Object::Handle();
+  if (!function.FindPragma(I, Symbols::vm_trace_entrypoints(), &options) ||
       options.IsNull() || !options.IsClosure()) {
     return Drop();
   }
-  auto& closure = Closure::ZoneHandle(Z, Closure::Cast(options).raw());
+  Closure& closure = Closure::ZoneHandle(Z, Closure::Cast(options).raw());
   LocalVariable* entry_point_num = MakeTemporary();
 
-  auto& function_name = String::ZoneHandle(
+  String& function_name = String::ZoneHandle(
       Z, String::New(function.ToLibNamePrefixedQualifiedCString(), Heap::kOld));
   if (parsed_function()->function().IsImplicitClosureFunction()) {
     function_name = String::Concat(
@@ -1683,7 +1678,7 @@
   call_hook += Constant(Function::ZoneHandle(Z, closure.function()));
   call_hook += B->ClosureCall(TokenPosition::kNoSource,
                               /*type_args_len=*/0, /*argument_count=*/3,
-                              /*argument_names=*/Array::ZoneHandle(Z));
+                              /*argument_names=*/Array::Handle());
   call_hook += Drop();  // result of closure call
   call_hook += Drop();  // entrypoint number
   return call_hook;
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index d797a9b..b8b5bff 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -551,8 +551,8 @@
     call->set_is_known_list_constructor(true);
     return;
   }
-  if (target.has_pragma()) {
-    intptr_t recognized_cid = MethodRecognizer::ResultCidFromPragma(target);
+  if (target.recognized_kind() != MethodRecognizer::kUnknown) {
+    intptr_t recognized_cid = MethodRecognizer::ResultCid(target);
     if (recognized_cid != kDynamicCid) {
       ASSERT((result_type == NULL) || (result_type->cid == kDynamicCid) ||
              (result_type->cid == recognized_cid));
diff --git a/runtime/vm/compiler/method_recognizer.cc b/runtime/vm/compiler/method_recognizer.cc
index 93f483c..82bf802 100644
--- a/runtime/vm/compiler/method_recognizer.cc
+++ b/runtime/vm/compiler/method_recognizer.cc
@@ -35,32 +35,20 @@
   }
 }
 
-intptr_t MethodRecognizer::ResultCidFromPragma(
-    const Object& function_or_field) {
-  // TODO(vm-team): The caller should only call us if the
-  // function_or_field.has_pragma(). If this method turns out to be a
-  // performance problem nonetheless, we could consider adding a cache.
-  auto T = Thread::Current();
-  auto Z = T->zone();
-  bool is_recognized_method = false;
-  auto& klass = Class::Handle(Z);
-  if (function_or_field.IsFunction()) {
-    auto& function = Function::Cast(function_or_field);
-    ASSERT(function.has_pragma());
-    is_recognized_method =
-        function.recognized_kind() != MethodRecognizer::kUnknown;
-    klass = function.Owner();
-  } else {
-    auto& field = Field::Cast(function_or_field);
-    ASSERT(field.has_pragma());
-    klass = field.Owner();
-  }
-  auto& library = Library::Handle(Z, klass.library());
-  const bool can_use_pragma = library.IsAnyCoreLibrary();
+intptr_t MethodRecognizer::ResultCid(const Function& function) {
+  // Use the 'vm:exact-result-type' annotation if available. This can only be
+  // used within the core library, see 'result_type_pragma.md', detail 1.2 for
+  // explanation.
+  Class& cls = Thread::Current()->ClassHandle();
+  Library& lib = Thread::Current()->LibraryHandle();
+  cls = function.Owner();
+  lib = cls.library();
+  const bool can_use_pragma = lib.IsAnyCoreLibrary();
+  cls = Class::null();
   if (can_use_pragma) {
-    auto& option = Object::Handle(Z);
-    if (library.FindPragma(T, function_or_field,
-                           Symbols::vm_exact_result_type(), &option)) {
+    Isolate* I = Isolate::Current();
+    auto& option = Object::Handle();
+    if (function.FindPragma(I, Symbols::vm_exact_result_type(), &option)) {
       if (option.IsType()) {
         return Type::Cast(option).type_class_id();
       } else if (option.IsString()) {
@@ -80,13 +68,17 @@
           }
         }
         if (!parse_failure && library_end > 0) {
-          auto& tmp = String::Handle(Z);
-          tmp = String::SubString(str, 0, library_end, Heap::kOld);
-          library = Library::LookupLibrary(Thread::Current(), tmp);
-          if (!library.IsNull()) {
-            tmp = String::SubString(str, library_end + 1,
-                                    str.Length() - library_end - 1, Heap::kOld);
-            klass = library.LookupClassAllowPrivate(tmp);
+          auto& libraryUri = String::Handle(
+              String::SubString(str, 0, library_end, Heap::kOld));
+          auto& className = String::Handle(
+              String::SubString(str, library_end + 1,
+                                str.Length() - library_end - 1, Heap::kOld));
+
+          Library& lib = Library::Handle(
+              Library::LookupLibrary(Thread::Current(), libraryUri));
+          if (!lib.IsNull()) {
+            Class& klass =
+                Class::Handle(lib.LookupClassAllowPrivate(className));
             if (!klass.IsNull()) {
               return klass.id();
             }
@@ -96,15 +88,13 @@
     }
   }
 
-  // Sanity check that all recognized methods which have a non-kDynamicCid were
-  // already recognized via @pragmas()s.
-  if (FLAG_strong && is_recognized_method) {
-    const auto& function = Function::Cast(function_or_field);
-    switch (function.recognized_kind()) {
+  // No result-type annotation can be used, so fall back on the table of
+  // recognized methods.
+  switch (function.recognized_kind()) {
 #define DEFINE_CASE(cname, fname, ename, result_type, fingerprint)             \
   case k##ename: {                                                             \
     const intptr_t cid = k##result_type##Cid;                                  \
-    if (cid != kDynamicCid) {                                                  \
+    if (FLAG_strong && cid != kDynamicCid) {                                   \
       String& err = String::Handle();                                          \
       err = function.QualifiedScrubbedName();                                  \
       err = String::Concat(                                                    \
@@ -118,14 +108,11 @@
     }                                                                          \
     return cid;                                                                \
   }
-      RECOGNIZED_LIST(DEFINE_CASE)
+    RECOGNIZED_LIST(DEFINE_CASE)
 #undef DEFINE_CASE
-      default:
-        return kDynamicCid;
-    }
+    default:
+      return kDynamicCid;
   }
-
-  return kDynamicCid;
 }
 
 intptr_t MethodRecognizer::MethodKindToReceiverCid(Kind kind) {
diff --git a/runtime/vm/compiler/method_recognizer.h b/runtime/vm/compiler/method_recognizer.h
index f25d177..d53528c 100644
--- a/runtime/vm/compiler/method_recognizer.h
+++ b/runtime/vm/compiler/method_recognizer.h
@@ -560,15 +560,7 @@
   static bool AlwaysInline(const Function& function);
   static bool PolymorphicTarget(const Function& function);
   static intptr_t NumArgsCheckedForStaticCall(const Function& function);
-
-  // Try to find an annotation of the form
-  //   @pragma("vm:exact-result-type", int)
-  //   @pragma("vm:exact-result-type", "dart:core#_Smi")
-  // and return the exact cid if found or kDynamicCid otherwise.
-  //
-  // See [result_type_pragma.md].
-  static intptr_t ResultCidFromPragma(const Object& function_or_field);
-
+  static intptr_t ResultCid(const Function& function);
   static intptr_t MethodKindToReceiverCid(Kind kind);
   static const char* KindToCString(Kind kind);
 
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index a3a90e1..e3dd575 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -5048,7 +5048,7 @@
         "because it was not annotated with @pragma('vm:entry-point').\n"
         "ERROR: See "
         "https://github.com/dart-lang/sdk/blob/master/runtime/docs/compiler/"
-        "aot/entry_point_pragma.md\n",
+        "aot/entry_point_pragma.md",
         String::Handle(klass.UserVisibleName()).ToCString());
     UNREACHABLE();
   }
diff --git a/runtime/vm/kernel.cc b/runtime/vm/kernel.cc
index 324fb2e..9fb8cfd 100644
--- a/runtime/vm/kernel.cc
+++ b/runtime/vm/kernel.cc
@@ -6,7 +6,6 @@
 
 #include "vm/compiler/frontend/constant_evaluator.h"
 #include "vm/compiler/frontend/kernel_translation_helper.h"
-#include "vm/compiler/jit/compiler.h"
 #include "vm/longjump.h"
 #include "vm/object_store.h"
 #include "vm/parser.h"  // For Parser::kParameter* constants.
@@ -453,11 +452,6 @@
 
 RawObject* EvaluateMetadata(const Field& metadata_field,
                             bool is_annotations_offset) {
-  if (Compiler::IsBackgroundCompilation()) {
-    Compiler::AbortBackgroundCompilation(
-        DeoptId::kNone, "Cannot evaluate annotations in background compiler.");
-  }
-
   LongJumpScope jump;
   if (setjmp(*jump.Set()) == 0) {
     Thread* thread = Thread::Current();
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index b68203a..6a818a9 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -953,6 +953,9 @@
       ReadVMAnnotations(annotation_count, &native_name_unused,
                         &is_potential_native_unused, &has_pragma_annotation);
     }
+    if (has_pragma_annotation) {
+      toplevel_class.set_has_pragma(true);
+    }
     field_helper.SetJustRead(FieldHelper::kAnnotations);
 
     field_helper.ReadUntilExcluding(FieldHelper::kType);
@@ -966,7 +969,6 @@
         Field::NewTopLevel(name, is_final, field_helper.IsConst(), script_class,
                            field_helper.position_, field_helper.end_position_));
     field.set_kernel_offset(field_offset);
-    field.set_has_pragma(has_pragma_annotation);
     const AbstractType& type = T.BuildType();  // read type.
     field.SetFieldType(type);
     ReadInferredType(field, field_offset + library_kernel_offset_);
@@ -1342,6 +1344,9 @@
         ReadVMAnnotations(annotation_count, &native_name_unused,
                           &is_potential_native_unused, &has_pragma_annotation);
       }
+      if (has_pragma_annotation) {
+        klass.set_has_pragma(true);
+      }
       field_helper.SetJustRead(FieldHelper::kAnnotations);
 
       field_helper.ReadUntilExcluding(FieldHelper::kType);
@@ -1361,7 +1366,6 @@
                      field_helper.IsConst(), is_reflectable, script_class, type,
                      field_helper.position_, field_helper.end_position_));
       field.set_kernel_offset(field_offset);
-      field.set_has_pragma(has_pragma_annotation);
       ReadInferredType(field, field_offset + library_kernel_offset_);
       CheckForInitializer(field);
       field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index ea2e5c4..091451f 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -2914,40 +2914,27 @@
   return result.raw();
 }
 
-bool Library::FindPragma(Thread* T,
-                         const Object& obj,
-                         const String& pragma_name,
-                         Object* options) const {
-  auto I = T->isolate();
-  auto Z = T->zone();
-  auto& lib = Library::Handle(Z);
-  if (obj.IsClass()) {
-    auto& klass = Class::Cast(obj);
-    if (!klass.has_pragma()) return false;
-    lib = klass.library();
-  } else if (obj.IsFunction()) {
-    auto& function = Function::Cast(obj);
-    if (!function.has_pragma()) return false;
-    lib = Class::Handle(Z, function.Owner()).library();
-  } else if (obj.IsField()) {
-    auto& field = Field::Cast(obj);
-    if (!field.has_pragma()) return false;
-    lib = Class::Handle(Z, field.Owner()).library();
-  } else {
-    UNREACHABLE();
-  }
+bool Function::FindPragma(Isolate* I,
+                          const String& pragma_name,
+                          Object* options) const {
+  if (!has_pragma()) return false;
 
-  Object& metadata_obj = Object::Handle(Z, lib.GetMetadata(obj));
-  if (metadata_obj.IsNull() || !metadata_obj.IsArray()) return false;
+  auto& klass = Class::Handle(Owner());
+  auto& lib = Library::Handle(klass.library());
 
-  auto& metadata = Array::Cast(metadata_obj);
-  auto& pragma_class = Class::Handle(Z, I->object_store()->pragma_class());
+  auto& pragma_class =
+      Class::Handle(Isolate::Current()->object_store()->pragma_class());
   auto& pragma_name_field =
-      Field::Handle(Z, pragma_class.LookupField(Symbols::name()));
+      Field::Handle(pragma_class.LookupField(Symbols::name()));
   auto& pragma_options_field =
-      Field::Handle(Z, pragma_class.LookupField(Symbols::options()));
+      Field::Handle(pragma_class.LookupField(Symbols::options()));
 
-  auto& pragma = Object::Handle(Z);
+  Array& metadata = Array::Handle();
+  metadata ^= lib.GetMetadata(Function::Handle(raw()));
+
+  if (metadata.IsNull()) return false;
+
+  auto& pragma = Object::Handle();
   for (intptr_t i = 0; i < metadata.Length(); ++i) {
     pragma = metadata.At(i);
     if (pragma.clazz() != pragma_class.raw() ||
@@ -8706,7 +8693,6 @@
                           const Object& owner,
                           TokenPosition token_pos,
                           TokenPosition end_token_pos) {
-  result.set_kind_bits(0);
   result.set_name(name);
   result.set_is_static(is_static);
   if (!is_static) {
@@ -8723,7 +8709,6 @@
   result.set_is_unboxing_candidate(true);
   result.set_initializer_changed_after_initialization(false);
   result.set_kernel_offset(0);
-  result.set_has_pragma(false);
   result.set_static_type_exactness_state(
       StaticTypeExactnessState::NotTracking());
   Isolate* isolate = Isolate::Current();
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 70164b9..b58ee61 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -2274,6 +2274,8 @@
   // Return true if any parent function of this function is generic.
   bool HasGenericParent() const;
 
+  bool FindPragma(Isolate* I, const String& pragma_name, Object* options) const;
+
   // Not thread-safe; must be called in the main thread.
   // Sets function's code and code's function.
   void InstallOptimizedCode(const Code& code) const;
@@ -3216,13 +3218,6 @@
         value, raw_ptr()->kind_bits_));
   }
 
-  bool has_pragma() const {
-    return HasPragmaBit::decode(raw_ptr()->kind_bits_);
-  }
-  void set_has_pragma(bool value) const {
-    set_kind_bits(HasPragmaBit::update(value, raw_ptr()->kind_bits_));
-  }
-
   intptr_t kernel_offset() const {
 #if defined(DART_PRECOMPILED_RUNTIME)
     return 0;
@@ -3480,24 +3475,22 @@
     kReflectableBit,
     kDoubleInitializedBit,
     kInitializerChangedAfterInitializatonBit,
-    kHasPragmaBit,
   };
-  class ConstBit : public BitField<uint16_t, bool, kConstBit, 1> {};
-  class StaticBit : public BitField<uint16_t, bool, kStaticBit, 1> {};
-  class FinalBit : public BitField<uint16_t, bool, kFinalBit, 1> {};
+  class ConstBit : public BitField<uint8_t, bool, kConstBit, 1> {};
+  class StaticBit : public BitField<uint8_t, bool, kStaticBit, 1> {};
+  class FinalBit : public BitField<uint8_t, bool, kFinalBit, 1> {};
   class HasInitializerBit
-      : public BitField<uint16_t, bool, kHasInitializerBit, 1> {};
+      : public BitField<uint8_t, bool, kHasInitializerBit, 1> {};
   class UnboxingCandidateBit
-      : public BitField<uint16_t, bool, kUnboxingCandidateBit, 1> {};
-  class ReflectableBit : public BitField<uint16_t, bool, kReflectableBit, 1> {};
+      : public BitField<uint8_t, bool, kUnboxingCandidateBit, 1> {};
+  class ReflectableBit : public BitField<uint8_t, bool, kReflectableBit, 1> {};
   class DoubleInitializedBit
-      : public BitField<uint16_t, bool, kDoubleInitializedBit, 1> {};
+      : public BitField<uint8_t, bool, kDoubleInitializedBit, 1> {};
   class InitializerChangedAfterInitializatonBit
-      : public BitField<uint16_t,
+      : public BitField<uint8_t,
                         bool,
                         kInitializerChangedAfterInitializatonBit,
                         1> {};
-  class HasPragmaBit : public BitField<uint16_t, bool, kHasPragmaBit, 1> {};
 
   // Update guarded cid and guarded length for this field. Returns true, if
   // deoptimization of dependent code is required.
@@ -3530,7 +3523,7 @@
   void set_end_token_pos(TokenPosition token_pos) const {
     StoreNonPointer(&raw_ptr()->end_token_pos_, token_pos);
   }
-  void set_kind_bits(uint16_t value) const {
+  void set_kind_bits(uint8_t value) const {
     StoreNonPointer(&raw_ptr()->kind_bits_, value);
   }
 
@@ -3820,11 +3813,6 @@
                          const Function& to_fun) const;
   RawObject* GetMetadata(const Object& obj) const;
 
-  bool FindPragma(Thread* T,
-                  const Object& object,
-                  const String& pragma_name,
-                  Object* options) const;
-
   RawClass* toplevel_class() const { return raw_ptr()->toplevel_class_; }
   void set_toplevel_class(const Class& value) const;
 
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index cdb5d63..a617d89 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -1218,7 +1218,7 @@
   // field.
   int8_t static_type_exactness_state_;
 
-  uint16_t kind_bits_;  // static, final, const, has initializer....
+  uint8_t kind_bits_;  // static, final, const, has initializer....
 
   friend class CidRewriteVisitor;
 };