Record @{Fast,Critical}Native in method's access flags.

Repurpose the old kAccFastNative flag (which wasn't actually
used for some time) and define a new kAccCriticalNative flag
to record the native method's annotation-based kind. This
avoids repeated determination of the kind from GenericJNI.
And making two transitions to runnable and back (using the
ScopedObjectAccess) from GenericJniMethodEnd() for normal
native methods just to determine that we need to transition
to runnable was really weird.

Since the IsFastNative() function now records the presence
of the @FastNative annotation, synchronized @FastNative
method calls now avoid thread state transitions.

When initializing the Runtime without a boot image, the
WellKnowClasses may not yet be initialized, so relax the
DCheckNativeAnnotation() to take that into account.

Also revert
    https://android-review.googlesource.com/509715
as the annotation checks are now much faster.

Bug: 65574695
Bug: 35644369
Test: m test-art-host-gtest
Test: testrunner.py --host
Change-Id: I2fc5ba192b9ce710a0e9202977b4f9543e387efe
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index a9d27ef..32d0bbe 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -46,6 +46,7 @@
 #include "dex/verified_method.h"
 #include "dex_compilation_unit.h"
 #include "dex_file-inl.h"
+#include "dex_file_annotations.h"
 #include "dex_instruction-inl.h"
 #include "driver/compiler_options.h"
 #include "gc/accounting/card_table-inl.h"
@@ -511,40 +512,11 @@
         InstructionSetHasGenericJniStub(driver->GetInstructionSet())) {
       // Leaving this empty will trigger the generic JNI version
     } else {
-      // Look-up the ArtMethod associated with this code_item (if any)
-      // -- It is later used to lookup any [optimization] annotations for this method.
-      ScopedObjectAccess soa(self);
-
-      // TODO: Lookup annotation from DexFile directly without resolving method.
-      ArtMethod* method =
-          Runtime::Current()->GetClassLinker()->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>(
-              dex_file,
-              method_idx,
-              dex_cache,
-              class_loader,
-              /* referrer */ nullptr,
-              invoke_type);
-
       // Query any JNI optimization annotations such as @FastNative or @CriticalNative.
-      Compiler::JniOptimizationFlags optimization_flags = Compiler::kNone;
-      if (UNLIKELY(method == nullptr)) {
-        // Failed method resolutions happen very rarely, e.g. ancestor class cannot be resolved.
-        DCHECK(self->IsExceptionPending());
-        self->ClearException();
-      } else if (method->IsAnnotatedWithFastNative()) {
-        // TODO: Will no longer need this CHECK once we have verifier checking this.
-        CHECK(!method->IsAnnotatedWithCriticalNative());
-        optimization_flags = Compiler::kFastNative;
-      } else if (method->IsAnnotatedWithCriticalNative()) {
-        // TODO: Will no longer need this CHECK once we have verifier checking this.
-        CHECK(!method->IsAnnotatedWithFastNative());
-        optimization_flags = Compiler::kCriticalNative;
-      }
+      access_flags |= annotations::GetNativeMethodAnnotationAccessFlags(
+          dex_file, dex_file.GetClassDef(class_def_idx), method_idx);
 
-      compiled_method = driver->GetCompiler()->JniCompile(access_flags,
-                                                          method_idx,
-                                                          dex_file,
-                                                          optimization_flags);
+      compiled_method = driver->GetCompiler()->JniCompile(access_flags, method_idx, dex_file);
       CHECK(compiled_method != nullptr);
     }
   } else if ((access_flags & kAccAbstract) != 0) {