RFR: 8274983: C1 optimizes the invocation of private interface methods

Xin Liu xliu at openjdk.java.net
Wed Nov 24 07:55:02 UTC 2021


On Sat, 20 Nov 2021 10:49:12 GMT, Dean Long <dlong at openjdk.org> wrote:

>> hi, @dean-long,
>> 
>> I think C1 covers all cases as long as the target method is loaded. I have seen cases which target methods haven't been loaded in startup time, but they are rare. 
>> 
>> ciMethod::can_be_statically_bound() return true if the method is private or final. The matrix shows the modifiers of target methods.
>> 
>> |                 | final | private | 
>> |-----------------|-------|---------|
>> | invokevirtual   | 1     | 2       | 
>> | invokespecial   | N/A1    | 3       |
>> | invokeinterface | N/A2    | 4       | 
>> 
>> 1. generates the optimized virtual call because [x->target_is_final()](https://github.com/openjdk/jdk/blob/master/src/hotspot/share/c1/c1_LIRGenerator.cpp#L2799) is true.
>> 2. transforms to `invokespecial` [here](https://github.com/openjdk/jdk/blob/master/src/hotspot/share/c1/c1_GraphBuilder.cpp#L1885) ,  then it will be case 3. 
>> 3. generates the optimize virtual call because `x->code() == Bytecodes::_invokespecial` is true.
>> 4. is what this patch covers. 
>> 
>> NA-1. I think it's impossible for javac.  it would be an optimized virtual call like case 3 even it existed.
>> NA-2: it's an illegal modifier for an interface method.
>>  https://docs.oracle.com/javase/specs/jls/se17/html/jls-9.html#jls-InterfaceMethodModifier
>
> Thanks @navyxliu.  I wonder if we can do 2) and 3) for invokeinterface, simplying the patch.  Something like:
> 
> 
>   // Some methods are obviously bindable without any type checks so
>   // convert them directly to an invokespecial or invokestatic.
>   if (target->is_loaded() && !target->is_abstract() && target->can_be_statically_bound()) {
>     switch (bc_raw) {
>     case Bytecodes::_invokevirtual:
>     case Bytecodes::_invokeinterface:: // XXX add invokeinterface here
>       code = Bytecodes::_invokespecial;
>       break;
> 
> [...]
> 
>   // invoke-special-super
>   if (code == Bytecodes::_invokespecial && !target->is_object_initializer()) { // XXX use "code" here
>     ciInstanceKlass* sender_klass = calling_klass;
>     if (sender_klass->is_interface()) {
> 
> [...]
> 
> What do you think?

hi, @dean-long , 
I update the PR.  The new revision generate Invoke HIR with code == Invokespecial. I don't need to touch the LIR part, so I revert them. 

I call `c->set_incompatible_class_change_check()` instead of set_invokespecial_receiver_check(). this will call a runtime to throw ICCError directly. Before that,  it went to uncommon_trap and reinterpreted the bytecode.

-------------

PR: https://git.openjdk.java.net/jdk/pull/6445


More information about the hotspot-compiler-dev mailing list