Equality for values -- new analysis, same conclusion

Dan Smith daniel.smith at oracle.com
Tue Aug 13 17:03:19 UTC 2019


> On Aug 12, 2019, at 12:17 PM, Dan Smith <daniel.smith at oracle.com> wrote:
> 
>> On Aug 10, 2019, at 12:57 PM, John Rose <john.r.rose at oracle.com <mailto:john.r.rose at oracle.com>> wrote:
>>> 
>>> - As a fast path for deeper equality comparisons (a == b || a.equals(b)), since the contract of equals() requires that == objects are equals().
>> 
>> This is what I call L.I.F.E., the Legacy Idiom For Equality.  ID== is good here too.  FAST== would be fine here, and a JIT could perform that strength reduction if it notices that the == expression is post-dominated by Object.equals (on the false path).  I think that’s usually detectable.
>> 
> 
> Major caveat for this kind of optimization: it relies on a "well-behaved" 'equals' method. If 'equals' can thrown an exception or have some other side effect (even indirectly) when a == b, we can't just blindly execute that code.
> 
> Maybe the optimization you envision is able to cope with these possibilities. JIT is a mystery to me. But it seems like something that needs careful attention.

Want to expand on this, because I'm not sure my description was clear, and it seems like a serious constraint.

Example:

inline class Dollar {
    public static int EQUALS_COUNTER = 0;

    public final long cents;

    public Dollar(long cents) { this.cents = cents; }

    boolean equals(Object o) {
        if (!(o instanceof Dollar)) return false;
        EQUALS_COUNTER++;
        return cents == ((Dollar) o).cents;
    }
}

class Test {
    public static int COMPARE_COUNTER = 0;

    static void compare(Dollar d1, Dollar d2) {
        if (d1 == d2 || d1.equals(d2)) COMPARE_COUNTER++;
    }

    public static void main(String... args) {
        Dollar d1 = new Dollar(100);
        Dollar d2 = new Dollar(100);
        compare(d1, d2);
        System.out.println("compare: " + COMPARE_COUNTER + "; equals: " + EQUALS_COUNTER);
    }
}

Using SAME== semantics, the output should be:

compare: 1; equals: 0

I worry that, for certain optimization strategies that claim to implement SAME== semantics, the output will be:

compare: 1; equals: 1



More information about the valhalla-spec-observers mailing list