Skip to content

Delegate null-check-then-equals to Objects.equals #132

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

Open
wants to merge 1 commit into
base: 2.13.x
Choose a base branch
from

Conversation

retronym
Copy link
Owner

@retronym retronym commented May 26, 2025

Motivation is to remove avoidable synthetic branches/instructions
for null data that are intepreted as uncovered code by JaCoCo etc.

Bytecode is also reduced.

Note that if either operand is potential Number or Character,
the backend delegates to BoxesRuntime.equals which handles Scala
semantic edge cases for boxed primitives. This PR does not change
that at all.

Before:

  public boolean test1(java.lang.String, java.lang.String);
    descriptor: (Ljava/lang/String;Ljava/lang/String;)Z
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=2, locals=4, args_size=3
         0: aload_1
         1: aload_2
         2: astore_3
         3: dup
         4: ifnonnull     15
         7: pop
         8: aload_3
         9: ifnull        22
        12: goto          26
        15: aload_3
        16: invokevirtual #20                 // Method java/lang/Object.equals:(Ljava/lang/Object;)Z
        19: ifeq          26
        22: iconst_1
        23: goto          27
        26: iconst_0
        27: ireturn

After

  public boolean test1(java.lang.String, java.lang.String);
    descriptor: (Ljava/lang/String;Ljava/lang/String;)Z
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=2, locals=3, args_size=3
         0: aload_1
         1: aload_2
         2: invokestatic  #22                 // Method java/util/Objects.equals:(Ljava/lang/Object;Ljava/lang/Object;)Z
         5: ifeq          12
         8: iconst_1
         9: goto          13
        12: iconst_0
        13: ireturn

@retronym retronym force-pushed the backend/use-object-equals branch from a97507d to aaf9a88 Compare May 26, 2025 02:48
Motivation is to remove avoidable synthetic branches/instructions
for null data that are intepreted as uncovered code by JaCoCo etc.

Bytecode is also reduced.

Note that if either operand is potential `Number` or `Character`,
the backend delegates to `BoxesRuntime.equals` which handles Scala
semantic edge cases for boxed primitives. This PR does not change
that at all.

Before:

```
  public boolean test1(java.lang.String, java.lang.String);
    descriptor: (Ljava/lang/String;Ljava/lang/String;)Z
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=2, locals=4, args_size=3
         0: aload_1
         1: aload_2
         2: astore_3
         3: dup
         4: ifnonnull     15
         7: pop
         8: aload_3
         9: ifnull        22
        12: goto          26
        15: aload_3
        16: invokevirtual #20                 // Method java/lang/Object.equals:(Ljava/lang/Object;)Z
        19: ifeq          26
        22: iconst_1
        23: goto          27
        26: iconst_0
        27: ireturn
```

After

```
  public boolean test1(java.lang.String, java.lang.String);
    descriptor: (Ljava/lang/String;Ljava/lang/String;)Z
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=2, locals=3, args_size=3
         0: aload_1
         1: aload_2
         2: invokestatic  #22                 // Method java/util/Objects.equals:(Ljava/lang/Object;Ljava/lang/Object;)Z
         5: ifeq          12
         8: iconst_1
         9: goto          13
        12: iconst_0
        13: ireturn
```
@retronym retronym force-pushed the backend/use-object-equals branch from aaf9a88 to ca6bdd4 Compare May 26, 2025 06:04
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.

1 participant