Use strcmp() for checking @{Fast,Critical}Native annotations.
Instead of looking up the descriptor in boot class path
loader (where @{Fast,Critical}Native are guaranteed to
be already resolved) and then checking if it's the
@{Fast,Critical}Native annotation, just check the
descriptor with strcmp().
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Bug: 65574695
Change-Id: I765590d039981d169fb3c606b6166580a84303b6
diff --git a/runtime/art_method.cc b/runtime/art_method.cc
index b5e0f66..8709643 100644
--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -429,30 +429,15 @@
}
bool ArtMethod::IsAnnotatedWithFastNative() {
- return IsAnnotatedWith(WellKnownClasses::dalvik_annotation_optimization_FastNative,
- DexFile::kDexVisibilityBuild,
- /* lookup_in_resolved_boot_classes */ true);
+ ScopedObjectAccess soa(Thread::Current());
+ return annotations::HasFastNativeMethodBuildAnnotation(
+ *GetDexFile(), GetClassDef(), GetDexMethodIndex());
}
bool ArtMethod::IsAnnotatedWithCriticalNative() {
- return IsAnnotatedWith(WellKnownClasses::dalvik_annotation_optimization_CriticalNative,
- DexFile::kDexVisibilityBuild,
- /* lookup_in_resolved_boot_classes */ true);
-}
-
-bool ArtMethod::IsAnnotatedWith(jclass klass,
- uint32_t visibility,
- bool lookup_in_resolved_boot_classes) {
- Thread* self = Thread::Current();
- ScopedObjectAccess soa(self);
- StackHandleScope<1> shs(self);
-
- ObjPtr<mirror::Class> annotation = soa.Decode<mirror::Class>(klass);
- DCHECK(annotation->IsAnnotation());
- Handle<mirror::Class> annotation_handle(shs.NewHandle(annotation));
-
- return annotations::IsMethodAnnotationPresent(
- this, annotation_handle, visibility, lookup_in_resolved_boot_classes);
+ ScopedObjectAccess soa(Thread::Current());
+ return annotations::HasCriticalNativeMethodBuildAnnotation(
+ *GetDexFile(), GetClassDef(), GetDexMethodIndex());
}
static uint32_t GetOatMethodIndexFromMethodIndex(const DexFile& dex_file,
diff --git a/runtime/art_method.h b/runtime/art_method.h
index ca2e34e..8927481 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -751,11 +751,6 @@
private:
uint16_t FindObsoleteDexClassDefIndex() REQUIRES_SHARED(Locks::mutator_lock_);
- // If `lookup_in_resolved_boot_classes` is true, look up any of the
- // method's annotations' classes in the bootstrap class loader's
- // resolved types; otherwise, resolve them as a side effect.
- bool IsAnnotatedWith(jclass klass, uint32_t visibility, bool lookup_in_resolved_boot_classes);
-
static constexpr size_t PtrSizedFieldsOffset(PointerSize pointer_size) {
// Round up to pointer size for padding field. Tested in art_method.cc.
return RoundUp(offsetof(ArtMethod, hotness_count_) + sizeof(hotness_count_),
diff --git a/runtime/dex_file_annotations.cc b/runtime/dex_file_annotations.cc
index 845202f..5496efd 100644
--- a/runtime/dex_file_annotations.cc
+++ b/runtime/dex_file_annotations.cc
@@ -261,32 +261,38 @@
return nullptr;
}
-const DexFile::AnnotationSetItem* FindAnnotationSetForMethod(ArtMethod* method)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- if (method->IsProxyMethod()) {
- return nullptr;
- }
- const DexFile* dex_file = method->GetDexFile();
+const DexFile::AnnotationSetItem* FindAnnotationSetForMethod(const DexFile& dex_file,
+ const DexFile::ClassDef& class_def,
+ uint32_t method_index) {
const DexFile::AnnotationsDirectoryItem* annotations_dir =
- dex_file->GetAnnotationsDirectory(method->GetClassDef());
+ dex_file.GetAnnotationsDirectory(class_def);
if (annotations_dir == nullptr) {
return nullptr;
}
const DexFile::MethodAnnotationsItem* method_annotations =
- dex_file->GetMethodAnnotations(annotations_dir);
+ dex_file.GetMethodAnnotations(annotations_dir);
if (method_annotations == nullptr) {
return nullptr;
}
- uint32_t method_index = method->GetDexMethodIndex();
uint32_t method_count = annotations_dir->methods_size_;
for (uint32_t i = 0; i < method_count; ++i) {
if (method_annotations[i].method_idx_ == method_index) {
- return dex_file->GetMethodAnnotationSetItem(method_annotations[i]);
+ return dex_file.GetMethodAnnotationSetItem(method_annotations[i]);
}
}
return nullptr;
}
+inline const DexFile::AnnotationSetItem* FindAnnotationSetForMethod(ArtMethod* method)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (method->IsProxyMethod()) {
+ return nullptr;
+ }
+ return FindAnnotationSetForMethod(*method->GetDexFile(),
+ method->GetClassDef(),
+ method->GetDexMethodIndex());
+}
+
const DexFile::ParameterAnnotationsItem* FindAnnotationsItemForMethod(ArtMethod* method)
REQUIRES_SHARED(Locks::mutator_lock_) {
const DexFile* dex_file = method->GetDexFile();
@@ -764,8 +770,7 @@
const ClassData& klass,
const DexFile::AnnotationSetItem* annotation_set,
uint32_t visibility,
- Handle<mirror::Class> annotation_class,
- bool lookup_in_resolved_boot_classes = false)
+ Handle<mirror::Class> annotation_class)
REQUIRES_SHARED(Locks::mutator_lock_) {
const DexFile& dex_file = klass.GetDexFile();
for (uint32_t i = 0; i < annotation_set->size_; ++i) {
@@ -778,35 +783,19 @@
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Thread* self = Thread::Current();
mirror::Class* resolved_class;
- if (lookup_in_resolved_boot_classes) {
- // Note: We cannot use ClassLinker::LookupResolvedType() because the current DexCache
- // may not be registered with the boot class path ClassLoader and we must not pollute
- // the DexCache with classes that are not in the associated ClassLoader's ClassTable.
- const char* descriptor = dex_file.StringByTypeIdx(dex::TypeIndex(type_index));
- ObjPtr<mirror::Class> looked_up_class =
- class_linker->LookupClass(self, descriptor, /* class_loader */ nullptr);
- resolved_class = looked_up_class.Ptr();
- if (resolved_class == nullptr) {
- // If `resolved_class` is null, this is fine: just ignore that
- // annotation item. We expect this to happen, as we do not
- // attempt to resolve the annotation's class in this code path.
- continue;
- }
- } else {
- StackHandleScope<2> hs(self);
- resolved_class = class_linker->ResolveType(
- klass.GetDexFile(),
- dex::TypeIndex(type_index),
- hs.NewHandle(klass.GetDexCache()),
- hs.NewHandle(klass.GetClassLoader()));
- if (resolved_class == nullptr) {
- std::string temp;
- LOG(WARNING) << StringPrintf("Unable to resolve %s annotation class %d",
- klass.GetRealClass()->GetDescriptor(&temp), type_index);
- CHECK(self->IsExceptionPending());
- self->ClearException();
- continue;
- }
+ StackHandleScope<2> hs(self);
+ resolved_class = class_linker->ResolveType(
+ klass.GetDexFile(),
+ dex::TypeIndex(type_index),
+ hs.NewHandle(klass.GetDexCache()),
+ hs.NewHandle(klass.GetClassLoader()));
+ if (resolved_class == nullptr) {
+ std::string temp;
+ LOG(WARNING) << StringPrintf("Unable to resolve %s annotation class %d",
+ klass.GetRealClass()->GetDescriptor(&temp), type_index);
+ CHECK(self->IsExceptionPending());
+ self->ClearException();
+ continue;
}
if (resolved_class == annotation_class.Get()) {
return annotation_item;
@@ -822,8 +811,8 @@
uint32_t visibility,
Handle<mirror::Class> annotation_class)
REQUIRES_SHARED(Locks::mutator_lock_) {
- const DexFile::AnnotationItem* annotation_item =
- GetAnnotationItemFromAnnotationSet(klass, annotation_set, visibility, annotation_class);
+ const DexFile::AnnotationItem* annotation_item = GetAnnotationItemFromAnnotationSet(
+ klass, annotation_set, visibility, annotation_class);
if (annotation_item == nullptr) {
return nullptr;
}
@@ -1235,21 +1224,74 @@
bool IsMethodAnnotationPresent(ArtMethod* method,
Handle<mirror::Class> annotation_class,
- uint32_t visibility /* = DexFile::kDexVisibilityRuntime */,
- bool lookup_in_resolved_boot_classes /* = false */) {
+ uint32_t visibility /* = DexFile::kDexVisibilityRuntime */) {
const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method);
if (annotation_set == nullptr) {
return false;
}
- const DexFile::AnnotationItem* annotation_item =
- GetAnnotationItemFromAnnotationSet(ClassData(method),
- annotation_set,
- visibility,
- annotation_class,
- lookup_in_resolved_boot_classes);
+ const DexFile::AnnotationItem* annotation_item = GetAnnotationItemFromAnnotationSet(
+ ClassData(method), annotation_set, visibility, annotation_class);
return annotation_item != nullptr;
}
+static void DCheckNativeAnnotation(const char* descriptor, jclass cls) {
+ if (kIsDebugBuild) {
+ ScopedObjectAccess soa(Thread::Current());
+ ObjPtr<mirror::Class> klass = soa.Decode<mirror::Class>(cls);
+ ClassLinker* linker = Runtime::Current()->GetClassLinker();
+ // Lookup using the boot class path loader should yield the annotation class.
+ CHECK_EQ(klass, linker->LookupClass(soa.Self(), descriptor, /* class_loader */ nullptr));
+ }
+}
+
+// Check whether a method from the `dex_file` with the given `annotation_set`
+// is annotated with `annotation_descriptor` with build visibility.
+static bool IsMethodBuildAnnotationPresent(const DexFile& dex_file,
+ const DexFile::AnnotationSetItem& annotation_set,
+ const char* annotation_descriptor,
+ jclass annotation_class) {
+ for (uint32_t i = 0; i < annotation_set.size_; ++i) {
+ const DexFile::AnnotationItem* annotation_item = dex_file.GetAnnotationItem(&annotation_set, i);
+ if (!IsVisibilityCompatible(annotation_item->visibility_, DexFile::kDexVisibilityBuild)) {
+ continue;
+ }
+ const uint8_t* annotation = annotation_item->annotation_;
+ uint32_t type_index = DecodeUnsignedLeb128(&annotation);
+ const char* descriptor = dex_file.StringByTypeIdx(dex::TypeIndex(type_index));
+ if (strcmp(descriptor, annotation_descriptor) == 0) {
+ DCheckNativeAnnotation(descriptor, annotation_class);
+ return true;
+ }
+ }
+ return false;
+}
+
+uint32_t HasFastNativeMethodBuildAnnotation(const DexFile& dex_file,
+ const DexFile::ClassDef& class_def,
+ uint32_t method_index) {
+ const DexFile::AnnotationSetItem* annotation_set =
+ FindAnnotationSetForMethod(dex_file, class_def, method_index);
+ return annotation_set != nullptr &&
+ IsMethodBuildAnnotationPresent(
+ dex_file,
+ *annotation_set,
+ "Ldalvik/annotation/optimization/FastNative;",
+ WellKnownClasses::dalvik_annotation_optimization_FastNative);
+}
+
+uint32_t HasCriticalNativeMethodBuildAnnotation(const DexFile& dex_file,
+ const DexFile::ClassDef& class_def,
+ uint32_t method_index) {
+ const DexFile::AnnotationSetItem* annotation_set =
+ FindAnnotationSetForMethod(dex_file, class_def, method_index);
+ return annotation_set != nullptr &&
+ IsMethodBuildAnnotationPresent(
+ dex_file,
+ *annotation_set,
+ "Ldalvik/annotation/optimization/CriticalNative;",
+ WellKnownClasses::dalvik_annotation_optimization_CriticalNative);
+}
+
mirror::Object* GetAnnotationForClass(Handle<mirror::Class> klass,
Handle<mirror::Class> annotation_class) {
ClassData data(klass);
diff --git a/runtime/dex_file_annotations.h b/runtime/dex_file_annotations.h
index e108882..04ff3a1 100644
--- a/runtime/dex_file_annotations.h
+++ b/runtime/dex_file_annotations.h
@@ -72,9 +72,18 @@
// side effect.
bool IsMethodAnnotationPresent(ArtMethod* method,
Handle<mirror::Class> annotation_class,
- uint32_t visibility = DexFile::kDexVisibilityRuntime,
- bool lookup_in_resolved_boot_classes = false)
+ uint32_t visibility = DexFile::kDexVisibilityRuntime)
REQUIRES_SHARED(Locks::mutator_lock_);
+// Check whether a method from the `dex_file` with the given `method_index`
+// is annotated with @dalvik.annotation.optimization.FastNative with build visibility.
+uint32_t HasFastNativeMethodBuildAnnotation(const DexFile& dex_file,
+ const DexFile::ClassDef& class_def,
+ uint32_t method_index);
+// Check whether a method from the `dex_file` with the given `method_index`
+// is annotated with @dalvik.annotation.optimization.CriticalNative with build visibility.
+uint32_t HasCriticalNativeMethodBuildAnnotation(const DexFile& dex_file,
+ const DexFile::ClassDef& class_def,
+ uint32_t method_index);
// Class annotations.
mirror::Object* GetAnnotationForClass(Handle<mirror::Class> klass,
diff --git a/runtime/image.cc b/runtime/image.cc
index aae572b..cf5feac 100644
--- a/runtime/image.cc
+++ b/runtime/image.cc
@@ -26,7 +26,7 @@
namespace art {
const uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' };
-const uint8_t ImageHeader::kImageVersion[] = { '0', '4', 'A', '\0' }; // VarHandle fence intrinsics
+const uint8_t ImageHeader::kImageVersion[] = { '0', '5', '0', '\0' }; // strcmp() @FastNative.
ImageHeader::ImageHeader(uint32_t image_begin,
uint32_t image_size,