RFR: 8272564: Incorrect attribution of method invocations of Object methods on interfaces [v2]
jlahoda at openjdk.java.net
Thu Sep 9 11:34:04 UTC 2021
On Tue, 7 Sep 2021 10:23:49 GMT, Maurizio Cimadamore <mcimadamore at openjdk.org> wrote:
>> Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision:
>> Removing unnecessary method call.
> The implementation logic seems to be moving in the right direction.It is true that interface do not inherit members for `Object` - but the JLS is set up in a strange way:
> If an interface has no direct superinterface types, then the interface implicitly declares a public abstract member method m with signature s, return type r, and throws clause t corresponding to each public instance method m with signature s, return type r, and throws clause t declared in Object (§4.3.2), unless an abstract method with the same signature, same return type, and a compatible throws clause is explicitly declared by the interface.
> This seems to suggest that resolution should return `I.toString` even if `I` does NOT declare a `toString` method. That makes sense, after all, implementations of `I` will _always_ have some toString(). This is not what your fallback Object lookup in `findMethod` does.
> I also suggest running benchmarks, as the effect of these changes would be to generate invokeinterface where we used to have invokevirtual. VM should be smart enough to figure that one out, but better check.
Thanks for the comment @mcimadamore!
In https://github.com/openjdk/jdk/pull/5165/commits/16ed87f33afd14d2d0513f11c83d8b14232c4aca, I changed the code to generate `invokeinterface` for methods from j.l.Object if invoked on an interface. I ran a JMH benchmark, and it does not seem to cause much issues for the sustained case:
Benchmark (p) Mode Cnt Score Error Units
MyBenchmark.testNewDesugaring param thrpt 25 280021515.383 ± 11477634.990 ops/s
MyBenchmark.testOldDesugaring param thrpt 25 272013631.484 ± 9960654.146 ops/s
I also tried the benchmarks, but the results are more unclear there.
I tried to split the loop for the current type and the superclasses, but in the end it didn't look very nice, so I skipped that for now. I can push the code somewhere, if desired.
More information about the compiler-dev