diff options
author | 2017-11-08 14:32:33 +0000 | |
---|---|---|
committer | 2017-11-08 14:50:56 +0000 | |
commit | 0db16e00e3927445585a588499731c58c1ae1bef (patch) | |
tree | 9d151a03534703642d20cd2265260ff13c7592a4 | |
parent | a3c21d9c0552a04dfa69817b991b8e902cd0d6d6 (diff) |
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
-rw-r--r-- | runtime/art_method.cc | 27 | ||||
-rw-r--r-- | runtime/art_method.h | 5 | ||||
-rw-r--r-- | runtime/dex_file_annotations.cc | 144 | ||||
-rw-r--r-- | runtime/dex_file_annotations.h | 15 | ||||
-rw-r--r-- | runtime/image.cc | 2 |
5 files changed, 112 insertions, 81 deletions
diff --git a/runtime/art_method.cc b/runtime/art_method.cc index b5e0f66575..8709643c3e 100644 --- a/runtime/art_method.cc +++ b/runtime/art_method.cc @@ -429,30 +429,15 @@ bool ArtMethod::IsPolymorphicSignature() { } 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 ca2e34e071..8927481e46 100644 --- a/runtime/art_method.h +++ b/runtime/art_method.h @@ -751,11 +751,6 @@ class ArtMethod FINAL { 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 845202ff72..5496efd108 100644 --- a/runtime/dex_file_annotations.cc +++ b/runtime/dex_file_annotations.cc @@ -261,32 +261,38 @@ const uint8_t* SearchEncodedAnnotation(const DexFile& dex_file, 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 DexFile::AnnotationItem* GetAnnotationItemFromAnnotationSet( 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 @@ const DexFile::AnnotationItem* GetAnnotationItemFromAnnotationSet( 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 @@ mirror::Object* GetAnnotationObjectFromAnnotationSet( 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 @@ mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForMethod(ArtMethod* 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 e1088823c3..04ff3a11a5 100644 --- a/runtime/dex_file_annotations.h +++ b/runtime/dex_file_annotations.h @@ -72,9 +72,18 @@ mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForMethod(ArtMethod* // side effect. bool IsMethodAnnotationPresent(ArtMethod* method, Handle<mirror::Class> annotation_class, - uint32_t visibility = DexFile::kDexVisibilityRuntime, - bool lookup_in_resolved_boot_classes = false) - REQUIRES_SHARED(Locks::mutator_lock_); + 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 aae572b68d..cf5feaca56 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, |