On Aug 12, 2019, at 11:17 AM, Dan Smith <[email protected]> wrote:

>> 
>> 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.

Yes it does. I think we need to consider (a) classifying equals methods which 
are well behaved and maybe (b) allowing the spec to open up loopholes for 
inexact execution of equals as a way of simplifying online classification.

The JIT optimization requires skipping the SAME== check if the equals method 
will also carry that burden. For that to be valid we need to ensure that 
applying equals of the same value to itself is a constant true with no side 
effects. This is easy to argue for IMO since that is part of the contract of 
Object::equals. What’s harder is to carve the spec so that equals methods which 
violate it can be covered within the limits of the spec. I’d like the JIT to 
have latitude under the JVMS to run such methods at will after SAME== is true 
and accept their side effects as part of the indeterminate behavior that occurs 
when an object fails its contract. 

If I can’t get that latitude, there are other things we can do to special case 
Object::equals, but more transparently to the JVMS. The simplest is to compile 
two versions, one fused with SAME== and one not. The first one replaces uses of 
LIFE, transparently. No spec impact. Maybe the compiled method has two entry 
points. Call the two compile units C::equals and C::equals/LIFE. The latter 
prepends a SAME== rest to the former. Since the prepended test is now in the 
same compilation unit, it can be fused and combined with the user-written 
equals logic. It won’t be executed redundantly out of line. 

Reply via email to