summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Roland Levillain <rpl@google.com> 2017-06-27 18:13:16 +0000
committer android-build-merger <android-build-merger@google.com> 2017-06-27 18:13:16 +0000
commit9862c1775b95d4b0fe5fdfc905d0dc29cb633210 (patch)
tree2b15d89a092ddcf56907de7aab38984116670ddd
parent0bc16ebfbc81644cf53c6d748edf199763619db2 (diff)
parent2ed6cce6fcfd031b0f9d83111f01b6b48ead1a32 (diff)
Only look for method optimization annotations in the bootstrap class loader.
am: 2ed6cce6fc Change-Id: I36ab21fcd4943316ae6b1a4873f9bd0531494b44
-rw-r--r--runtime/art_method.cc16
-rw-r--r--runtime/art_method.h5
-rw-r--r--runtime/dex_file_annotations.cc58
-rw-r--r--runtime/dex_file_annotations.h11
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints.cc5
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.