Skip to content

Improve Objects.equal specialization #10320

@niloc132

Description

@niloc132

The static method Objects.equals(Object,Object) emulation has a non-standard overload equals(String,String), intended to capture via Java's standard compile time polymorphism. This is great when the two arguments are declared to be Strings in the original Java source, but GWT already has a mechanism to pick a more specialized method, and it can kick in after a few rounds of compilation, allowing a variable declared as Object but always assigned to a String value to take advantage of this.

Additionally, this would make it possible for generated record type equals(Object) methods to automatically dispatch to the expected String specialization without having to statically look up the correct implementation.

We can't just rename equals(String,String) to equalsString(String,String) and add the @SpecializeMethod annotation on equals(Object,Object) as SpecializeMethod's javadoc notes:

* The annotated method must call the target method directly, and the compiler
* must not inline the target method to prevent it from being pruned while it
* still might be used.

This is a new note that I added recently as part of solving another bug, see #10165 / #10055. Applying this requirement would increase compiled size of equals(Object,Object) by adding an extra unpruneable instanceof - so while this is possible, it probably isn't the best plan.

The requirement exists so that the compiler is able to leave the specialization without pruning it because it still has at least one use. MethodInliner is already prevented from inlining away the original implementation until we're confident that the specialization cannot be applied. Then, we remove all specializations and prune one more time.

DeadCodeElimination performing constant folding through static method calls on constants also has a similar limitation (or at least ought to) - if the method is inlined away before DCE can examining the call to see if it applies to constants and can be computed at compile time, then the optimization cannot take place. #10255 is intended to improve this situation, and the draft fix works by marking certain method calls as capable of being statically evaluated, then uses the RemoveSpecializations pass to also remove that marker as well. This suggests that it might be worth also running MethodInliner again after specializations are removed, something also included in that draft.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions