Created
June 11, 2014 08:49
-
-
Save 3Nigma/eded1949ca36f51c6bc8 to your computer and use it in GitHub Desktop.
Method used to analyze the triggering of the new "return-void-barrier" opcode in Google's Android ART distribution
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
static void ResolveClassFieldsAndMethods(const ParallelCompilationManager* manager, | |
size_t class_def_index) | |
LOCKS_EXCLUDED(Locks::mutator_lock_) { | |
ATRACE_CALL(); | |
Thread* self = Thread::Current(); | |
jobject jclass_loader = manager->GetClassLoader(); | |
const DexFile& dex_file = *manager->GetDexFile(); | |
ClassLinker* class_linker = manager->GetClassLinker(); | |
// If an instance field is final then we need to have a barrier on the return, static final | |
// fields are assigned within the lock held for class initialization. Conservatively assume | |
// constructor barriers are always required. | |
bool requires_constructor_barrier = true; | |
// Method and Field are the worst. We can't resolve without either | |
// context from the code use (to disambiguate virtual vs direct | |
// method and instance vs static field) or from class | |
// definitions. While the compiler will resolve what it can as it | |
// needs it, here we try to resolve fields and methods used in class | |
// definitions, since many of them many never be referenced by | |
// generated code. | |
const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index); | |
if (!SkipClass(class_linker, jclass_loader, dex_file, class_def)) { | |
ScopedObjectAccess soa(self); | |
StackHandleScope<2> hs(soa.Self()); | |
Handle<mirror::ClassLoader> class_loader( | |
hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader))); | |
Handle<mirror::DexCache> dex_cache(hs.NewHandle(class_linker->FindDexCache(dex_file))); | |
// Resolve the class. | |
mirror::Class* klass = class_linker->ResolveType(dex_file, class_def.class_idx_, dex_cache, | |
class_loader); | |
bool resolve_fields_and_methods; | |
if (klass == NULL) { | |
// Class couldn't be resolved, for example, super-class is in a different dex file. Don't | |
// attempt to resolve methods and fields when there is no declaring class. | |
CHECK(soa.Self()->IsExceptionPending()); | |
soa.Self()->ClearException(); | |
resolve_fields_and_methods = false; | |
} else { | |
resolve_fields_and_methods = manager->GetCompiler()->IsImage(); | |
} | |
// Note the class_data pointer advances through the headers, | |
// static fields, instance fields, direct methods, and virtual | |
// methods. | |
const byte* class_data = dex_file.GetClassData(class_def); | |
if (class_data == NULL) { | |
// Empty class such as a marker interface. | |
requires_constructor_barrier = false; | |
} else { | |
ClassDataItemIterator it(dex_file, class_data); | |
while (it.HasNextStaticField()) { | |
if (resolve_fields_and_methods) { | |
mirror::ArtField* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), | |
dex_cache, class_loader, true); | |
if (field == NULL) { | |
CHECK(soa.Self()->IsExceptionPending()); | |
soa.Self()->ClearException(); | |
} | |
} | |
it.Next(); | |
} | |
// We require a constructor barrier if there are final instance fields. | |
requires_constructor_barrier = false; | |
while (it.HasNextInstanceField()) { | |
if ((it.GetMemberAccessFlags() & kAccFinal) != 0) { | |
requires_constructor_barrier = true; | |
} | |
if (resolve_fields_and_methods) { | |
mirror::ArtField* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), | |
dex_cache, class_loader, false); | |
if (field == NULL) { | |
CHECK(soa.Self()->IsExceptionPending()); | |
soa.Self()->ClearException(); | |
} | |
} | |
it.Next(); | |
} | |
if (resolve_fields_and_methods) { | |
while (it.HasNextDirectMethod()) { | |
mirror::ArtMethod* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), | |
dex_cache, class_loader, | |
NullHandle<mirror::ArtMethod>(), | |
it.GetMethodInvokeType(class_def)); | |
if (method == NULL) { | |
CHECK(soa.Self()->IsExceptionPending()); | |
soa.Self()->ClearException(); | |
} | |
it.Next(); | |
} | |
while (it.HasNextVirtualMethod()) { | |
mirror::ArtMethod* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), | |
dex_cache, class_loader, | |
NullHandle<mirror::ArtMethod>(), | |
it.GetMethodInvokeType(class_def)); | |
if (method == NULL) { | |
CHECK(soa.Self()->IsExceptionPending()); | |
soa.Self()->ClearException(); | |
} | |
it.Next(); | |
} | |
DCHECK(!it.HasNext()); | |
} | |
} | |
} | |
if (requires_constructor_barrier) { | |
manager->GetCompiler()->AddRequiresConstructorBarrier(self, &dex_file, class_def_index); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Running
grep -rnw ./ -e "kAccFinal"
inside the android art-platform source tree (v4.4.3) yeilded the following occurances:Further analysis of these results concluded:
class_linker.cc:2324
referes to class declarationsclass_linker.cc:2826
referes to classes (resides in a method calledCreateProxyClass
class_linker.cc:2853
resides in the same area as line 2826class_linker.cc:2863
lays still in theCreateProxyClass
methodclass_linker.cc:3041
referes to a method declaration