diff options
| author | 2017-06-27 18:13:16 +0000 | |
|---|---|---|
| committer | 2017-06-27 18:13:16 +0000 | |
| commit | 9862c1775b95d4b0fe5fdfc905d0dc29cb633210 (patch) | |
| tree | 2b15d89a092ddcf56907de7aab38984116670ddd | |
| parent | 0bc16ebfbc81644cf53c6d748edf199763619db2 (diff) | |
| parent | 2ed6cce6fcfd031b0f9d83111f01b6b48ead1a32 (diff) | |
Only look for method optimization annotations in the bootstrap class loader.
am: 2ed6cce6fc
Change-Id: I36ab21fcd4943316ae6b1a4873f9bd0531494b44
| -rw-r--r-- | runtime/art_method.cc | 16 | ||||
| -rw-r--r-- | runtime/art_method.h | 5 | ||||
| -rw-r--r-- | runtime/dex_file_annotations.cc | 58 | ||||
| -rw-r--r-- | runtime/dex_file_annotations.h | 11 | ||||
| -rw-r--r-- | runtime/entrypoints/quick/quick_trampoline_entrypoints.cc | 5 |
5 files changed, 68 insertions, 27 deletions
diff --git a/runtime/art_method.cc b/runtime/art_method.cc index 7de8916ad5..67038b4c4b 100644 --- a/runtime/art_method.cc +++ b/runtime/art_method.cc @@ -403,15 +403,19 @@ bool ArtMethod::IsOverridableByDefaultMethod() { bool ArtMethod::IsAnnotatedWithFastNative() { return IsAnnotatedWith(WellKnownClasses::dalvik_annotation_optimization_FastNative, - DexFile::kDexVisibilityBuild); + DexFile::kDexVisibilityBuild, + /* lookup_in_resolved_boot_classes */ true); } bool ArtMethod::IsAnnotatedWithCriticalNative() { return IsAnnotatedWith(WellKnownClasses::dalvik_annotation_optimization_CriticalNative, - DexFile::kDexVisibilityBuild); + DexFile::kDexVisibilityBuild, + /* lookup_in_resolved_boot_classes */ true); } -bool ArtMethod::IsAnnotatedWith(jclass klass, uint32_t visibility) { +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); @@ -420,10 +424,8 @@ bool ArtMethod::IsAnnotatedWith(jclass klass, uint32_t visibility) { DCHECK(annotation->IsAnnotation()); Handle<mirror::Class> annotation_handle(shs.NewHandle(annotation)); - // Note: Resolves any method annotations' classes as a side-effect. - // -- This seems allowed by the spec since it says we can preload any classes - // referenced by another classes's constant pool table. - return annotations::IsMethodAnnotationPresent(this, annotation_handle, visibility); + return annotations::IsMethodAnnotationPresent( + this, annotation_handle, visibility, lookup_in_resolved_boot_classes); } static uint32_t GetOatMethodIndexFromMethodIndex(const DexFile& dex_file, diff --git a/runtime/art_method.h b/runtime/art_method.h index d8dfdd7959..c5d344290c 100644 --- a/runtime/art_method.h +++ b/runtime/art_method.h @@ -714,7 +714,10 @@ class ArtMethod FINAL { private: uint16_t FindObsoleteDexClassDefIndex() REQUIRES_SHARED(Locks::mutator_lock_); - bool IsAnnotatedWith(jclass klass, uint32_t visibility); + // 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. diff --git a/runtime/dex_file_annotations.cc b/runtime/dex_file_annotations.cc index f21f1a2704..2b81f0a99a 100644 --- a/runtime/dex_file_annotations.cc +++ b/runtime/dex_file_annotations.cc @@ -751,7 +751,8 @@ const DexFile::AnnotationItem* GetAnnotationItemFromAnnotationSet( const ClassData& klass, const DexFile::AnnotationSetItem* annotation_set, uint32_t visibility, - Handle<mirror::Class> annotation_class) + Handle<mirror::Class> annotation_class, + bool lookup_in_resolved_boot_classes = false) REQUIRES_SHARED(Locks::mutator_lock_) { const DexFile& dex_file = klass.GetDexFile(); for (uint32_t i = 0; i < annotation_set->size_; ++i) { @@ -761,19 +762,37 @@ const DexFile::AnnotationItem* GetAnnotationItemFromAnnotationSet( } const uint8_t* annotation = annotation_item->annotation_; uint32_t type_index = DecodeUnsignedLeb128(&annotation); - StackHandleScope<2> hs(Thread::Current()); - mirror::Class* resolved_class = Runtime::Current()->GetClassLinker()->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(Thread::Current()->IsExceptionPending()); - Thread::Current()->ClearException(); - continue; + mirror::Class* resolved_class; + if (lookup_in_resolved_boot_classes) { + ObjPtr<mirror::Class> looked_up_class = + Runtime::Current()->GetClassLinker()->LookupResolvedType( + klass.GetDexFile(), + dex::TypeIndex(type_index), + klass.GetDexCache(), + // Force the use of the bootstrap class loader. + static_cast<mirror::ClassLoader*>(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(Thread::Current()); + resolved_class = Runtime::Current()->GetClassLinker()->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(Thread::Current()->IsExceptionPending()); + Thread::Current()->ClearException(); + continue; + } } if (resolved_class == annotation_class.Get()) { return annotation_item; @@ -1200,15 +1219,20 @@ mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForMethod(ArtMethod* return GetSignatureValue(ClassData(method), annotation_set); } -bool IsMethodAnnotationPresent(ArtMethod* method, Handle<mirror::Class> annotation_class, - uint32_t visibility /* = DexFile::kDexVisibilityRuntime */) { +bool IsMethodAnnotationPresent(ArtMethod* method, + Handle<mirror::Class> annotation_class, + uint32_t visibility /* = DexFile::kDexVisibilityRuntime */, + bool lookup_in_resolved_boot_classes /* = false */) { 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); + annotation_set, + visibility, + annotation_class, + lookup_in_resolved_boot_classes); return annotation_item != nullptr; } diff --git a/runtime/dex_file_annotations.h b/runtime/dex_file_annotations.h index 651c9844eb..e1088823c3 100644 --- a/runtime/dex_file_annotations.h +++ b/runtime/dex_file_annotations.h @@ -65,8 +65,15 @@ bool GetParametersMetadataForMethod(ArtMethod* method, REQUIRES_SHARED(Locks::mutator_lock_); mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForMethod(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_); -bool IsMethodAnnotationPresent(ArtMethod* method, Handle<mirror::Class> annotation_class, - uint32_t visibility = DexFile::kDexVisibilityRuntime) +// Check whether `method` is annotated with `annotation_class`. +// 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; if it is false (default value), resolve them as a +// 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_); // Class annotations. diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc index c3fd2a099d..44bd40fa52 100644 --- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc @@ -2087,6 +2087,11 @@ extern "C" TwoWordReturn artQuickGenericJniTrampoline(Thread* self, ArtMethod** self->SetTopOfStack(sp); uint32_t shorty_len = 0; const char* shorty = called->GetShorty(&shorty_len); + // Optimization annotations lookup does not try to resolve classes, + // as this may throw an exception, which is not supported by the + // Generic JNI trampoline at this stage; instead, method's + // annotations' classes are looked up in the bootstrap class + // loader's resolved types (which won't trigger an exception). bool critical_native = called->IsAnnotatedWithCriticalNative(); // ArtMethod::IsAnnotatedWithCriticalNative should not throw // an exception; clear it if it happened anyway. |