Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save 3Nigma/eded1949ca36f51c6bc8 to your computer and use it in GitHub Desktop.
Save 3Nigma/eded1949ca36f51c6bc8 to your computer and use it in GitHub Desktop.

Revisions

  1. 3Nigma created this gist Jun 11, 2014.
    108 changes: 108 additions & 0 deletions <Android-ART>\compiler\compiler_driver.cc
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,108 @@
    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);
    }
    }