RFR: 8266074: Vtable-based CHA implementation

Vladimir Ivanov vlivanov at openjdk.java.net
Fri Apr 30 21:51:54 UTC 2021


On Fri, 30 Apr 2021 21:44:34 GMT, Vladimir Ivanov <vlivanov at openjdk.org> wrote:

>> src/hotspot/share/code/dependencies.cpp line 1521:
>> 
>>> 1519:     selected_method = recv_klass->method_at_itable_or_null(_declaring_klass, _vtable_index,
>>> 1520:                                                            implements_interface); // out parameter
>>> 1521:     assert(implements_interface, "not implemented");
>> 
>> Looking at `recv_klass->method_at_itable_or_null`, I wonder if there can be “holes” in the itable for missing methods.  They would lead to `AME` if called.  They might also trigger your assert here:  `assert(implements_interface, "not implemented")`.  Is there some reason that `select_method` cannot possibly encounter a missing method?
>> 
>> Answer to self:  I don't remember whether the JVM creates itable methods on the fly, but I suppose it does, so the code would see an synthetic abstract method.  (Decades ago we named those Miranda Methods because if you don't have a responding method "one will be provided for you".)  And itables are just aliases of vtable slices, so the miranda placed in the vtable will be seen also in the itable.
>> 
>> (Overall comment on this area of the code:  It looks great, much better than when I touched it last.  Thanks!)
>
> Regarding "holes" in itables: yes, it happens in practice. `select_method` is allowed to return a `NULL` and it is used by `LinkedConcreteMethodFinder` as a sentinel value for `AME` (when placed in `_found_methods` array). That's why `Dependencies::find_unique_concrete_method()` check `participant(0)`:
> 
>    Method* fm = wf.found_method(0);  // Will be NULL if num_parts == 0.
>    Klass*   p = wf.participant(0);   // Will be NULL if num_parts == 0.
>    ...
>    if (Dependencies::is_concrete_method(m, ctxk)) {
>      if (fm == NULL && p == NULL) {
>        // It turns out that m was always the only implementation.
>        fm = m;
>      }
> 
> 
> Now I think that it's not clear enough from the code. I'll elaborate on it in the additional comments.

Regarding the assert: the itable should always be found. First, because only implementors are enumerated during the analysis (currently, subclasses of the unique direct implementor). Second, because itable stubs rely on itable contents when performing receiver subtype checks. So, all superinterfaces should have a corresponding itable present (even an empty one).

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

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


More information about the hotspot-compiler-dev mailing list