Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Classes needed for lambda merging in ProGuard #36

Open
wants to merge 40 commits into
base: master
Choose a base branch
from

Conversation

heckej
Copy link
Contributor

@heckej heckej commented Jun 9, 2022

This will add visitors that are used to implement lambda merging in ProGuard (see pull request for ProGuard: Implementation of lambda merging for Kotlin lambda classes #257).

Masrepus and others added 30 commits December 24, 2021 13:56
…code attribute

Summary: Methods can sometimes have empty code attributes, if Dex2Pro skips them due to some failure. Unfortunately, this made the DominatorCalculator crash with an ArrayIndexOutOfBoundsException. This has been fixed by making the analysis skip empty code attributes.

Test Plan: New unit test

Reviewers: james.hamilton, dennis.titze

Reviewed By: dennis.titze

Differential Revision: http://phabricator.guardsquare.com/D10236
… targets

Summary: When searching for call targets in superinterfaces the call resolver previously didn't enforce that any potential target must be non-abstract. Also, if any other resolution path results in a call to an abstract method, this is now logged as an error to catch bugs earlier.

Test Plan: Existing tests

Reviewers: james.hamilton, carlo.alberto.pozzoli, dennis.titze

Reviewed By: dennis.titze

Differential Revision: http://phabricator.guardsquare.com/D10245
Test Plan: existing tests

Reviewers: samuel.hopstock

Reviewed By: samuel.hopstock

Differential Revision: http://phabricator.guardsquare.com/D10254
Summary: Previously an error was logged when the call target turned out to be an abstract method. Unfortunately, things like `myList.iterator().hasNext()` validly target an abstract method, which doesn't warrant an error log message. Keeping the logging in would create tons of log spam.

Test Plan: N/A

Reviewers: dennis.titze

Reviewed By: dennis.titze

Differential Revision: http://phabricator.guardsquare.com/D10252
…hen count has changed

New classes: ModifiedAllInnerClassesInfoVisitor
src/main/java/proguard/classfile/ClassConstants.java Outdated Show resolved Hide resolved
@@ -0,0 +1,27 @@
package proguard.classfile.attribute.visitor;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add the ProGuardCORE header to all the classes?


@Override
public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant) {
utf8Constant.setString(utf8Constant.getString().replace(originalType, replacingType));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we should be using a ConstantPoolEditor to add a new constant. You can use a ConstantPoolShrinker after to remove unused ones.

        programMember.u2nameIndex =
            new ConstantPoolEditor(programClass).addUtf8Constant(newName);

import proguard.classfile.constant.Constant;
import proguard.classfile.constant.visitor.ConstantVisitor;

public class ClassReferenceFinder implements ConstantVisitor
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be replacable by the following Filter class which can delegate to another ClassVisitor if the the class is referenced.

It's extracted from proguard.backport.StaticInterfaceMethodConverter.MyReferencedClassFilter in ProGuard.

Usable like the following:

        this.programClassPool.classesAccept(
                new ClassNameFilter(regularExpression,
                new ReferencedClassFilter(
                    lambdaClass,
                    enclosingMethodUpdater)));

But I see that currentLambdaClass gets updated, so might not work. Can also be used with a ClassCounter:

ClassCounter counter = new ClassCounter();
programClass.accept(new ReferencedClassFilter(currentLambdaClass, counter))
package proguard.classfile.visitor;

import proguard.classfile.*;
import proguard.classfile.constant.*;
import proguard.classfile.constant.visitor.ConstantVisitor;
import proguard.classfile.visitor.ClassVisitor;

/**
 * This ClassVisitor delegates its visits to classes that
 * reference a given class via any RefConstant.
 */
public class ReferencedClassFilter
    implements ClassVisitor,
               ConstantVisitor
{
    private final Clazz        referencedClass;
    private final ClassVisitor classVisitor;

    private boolean referenceClassFound;


    public ReferencedClassFilter(Clazz referencedClass,
                                 ClassVisitor classVisitor)
    {
        this.referencedClass = referencedClass;
        this.classVisitor = classVisitor;
    }


    // Implementations for ClassVisitor.


    @Override
    public void visitAnyClass(Clazz clazz) {}


    @Override
    public void visitProgramClass(ProgramClass programClass)
    {
        referenceClassFound = false;
        programClass.constantPoolEntriesAccept(this);

        if (referenceClassFound)
        {
            programClass.accept(classVisitor);
        }
    }


    // Implementations for ConstantVisitor.


    public void visitAnyConstant(Clazz clazz, Constant constant) {}


    public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
    {
        if (refConstant.referencedClass == referencedClass)
        {
            referenceClassFound = true;
        }
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants