Megamorphic virtual call optimization in Java

351 views
Skip to first unread message

r r

unread,
Feb 5, 2022, 6:26:54 AM2/5/22
to mechanical-sympathy
Hello,
we know that there are some techniques that make virtual calls not so expensive in JVM like Inline Cache or Polymorphic Inline Cache. 

Let's consider the following situation:

Base is an interface. 

public void f(Base[] b) {
    for(int i = 0; i < b.length; i++) {
          b[i].m();   
    }
}

I see from my profiler that calling virtual (interface) method is relatively expensive.
f is on the hot path and it was compiled to machine code (C2) but I see that call to m is a real virtual call. It means that it was not optimised by JVM. 

The question is, how to deal with a such situation? Obviously, I cannot make the method m not virtual here because it requires a serious redesign. 

Can I do anything or I have to accept it? I was thinking how to "force" or "convince" a JVM to 

1. use polymorphic inline cache here - the number of different types in b is quite low - between 4-5 types.
2. to unroll this loop - length of b is also relatively small. After an unroll it is possible that Inline Cache will be helpful here.

Thanks in advance for any advices.
Regards,

Greg Young

unread,
Feb 5, 2022, 6:30:38 AM2/5/22
to mechanica...@googlegroups.com
which jvm?

--
You received this message because you are subscribed to the Google Groups "mechanical-sympathy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mechanical-symp...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/mechanical-sympathy/9b52b34e-6388-4cba-b89e-ce7521109cban%40googlegroups.com.


--
Studying for the Turing test

r r

unread,
Feb 5, 2022, 6:35:31 AM2/5/22
to mechanical-sympathy
JVM 11+ (OpenJDK / Zulu)

Remi Forax

unread,
Feb 5, 2022, 6:46:18 AM2/5/22
to mechanical-sympathy
I've recently implemented a small library for that kind of stuff.

The idea is to see b[i].m() or f(Base[] b) as a method call and extract constants from that method call, the library allows you to choose if a value is a constant or f(value) is a constant (in case of the array Base[].length is a constant) and to decide the policy when it's not a real constant (fail, use a monomorphic inlining cache or use a polymorphic inlining cache).

It uses java.lang.invoke under the hood so everything tend to be inlined.

Thanks in advance for any advices.
Regards,

regards,
Rémi

Gil Tene

unread,
Feb 5, 2022, 12:38:11 PM2/5/22
to mechanical-sympathy
You might want to give it a spin on Prime (Zing) 11 and see what you get, the Falcon JIT in Prime will do polymorphic guarded in-line caching for up to 6 implementers by default, I believe (as is configurable to higher if needed). This is exactly the sort of thing that capability is meant for.

r r

unread,
Feb 8, 2022, 6:51:25 AM2/8/22
to mechanical-sympathy
Thanks for your responses :)
Reply all
Reply to author
Forward
0 new messages