[Nestmates] RFR: 8189163: [Nestmates] Updated invokeInterface selection/resolution rules

David Holmes david.holmes at oracle.com
Mon Mar 5 06:54:48 UTC 2018

Bug: https://bugs.openjdk.java.net/browse/JDK-8189163
webrev: http://cr.openjdk.java.net/~dholmes/8189163/webrev/
VM Spec update: 

The "resolution" part of this is actually already addressed by virtue of 
being able to use invokeinterface for private interface methods.

This part addresses the key spec change in relation to existing method 
selection rules for invokeinterface - which is intended to bring it into 
line with how invokevirtual already behaves. The key points to note in 
method selection are:

1. If the resolved method is private then the selected method is always 
the resolved method. (And that is always the implementation in the 
interface when dealing with invokeinterface.)

2. A private method never overrides any method by the same 
name/signature in the inheritance hierarchy.

The key consequence of (2) is that private methods are skipped when 
selecting the method to call when the resolved method is not private. So 
in the past, for example, if you were looking for an implementation of a 
public interface method m() in a class C, and you found a private 
definition of m(), you would "select" it and then throw 
IllegalAccessError. Under the new rules you skip-over/ignore it and so 
continue looking for a suitable m() implementation.

In terms of implementing this change there were three very similar and 
very small changes to cause private methods to be skipped:

1. src/hotspot/share/interpreter/linkResolver.cpp: 

More appropriately named "select_interface_method", in this method we 
now call LinkResolver::lookup_instance_method_klasses with the 
"skip_private" flag.

The bulk of the changes in LinkResolver and src/hotspot/share/oops/* are 
simply to expose the PrivateLookupMode parameter so that it can be 
passed through explicitly to uncached_lookup_method and 
find_instance_method. By default we assume "find_private", so we did not 
have to modify all the existing callsites.

2.  src/hotspot/share/oops/klassVtable.cpp: 

When initializing the itable for a class, skip private class methods as 
they can never be the implementation of an interface method.

3.  src/hotspot/share/code/dependencies.cpp: bool is_witness(Klass* k)

When looking for an implementation for "m" in k to see if the uniqueness 
of "m" has changed, skip private methods as they cannot override the 
known "m" and so do not affect its uniqueness.

The change in src/hotspot/share/prims/methodHandles.cpp corrects a 
terminology issue whereby a private interface method is referred to as a 
"default method", which it is not.


There are two new tests:

- runtime/Nestmates/methodSelection/TestInterfaceMethodSelection.java
- runtime/Nestmates/methodSelection/TestMethodSelection.java

Although only invokeinterface selection rules changed, I wrote the 
equivalent invokevirtual version as a sanity check. The tests start from 
a known resolved method and then tests the selection process for 
private/public variants of a method in a hierarchy of 2 or 3. There is 
very elaborate documentation in the tests explaining exactly what they 
do (and don't do). The obvious variants of these tests with different 
resolution and accessibility are already tested elsewhere, so I did not 
duplicate that effort.

The following existing tests had to be modified:

- compiler/jsr292/methodHandleExceptions/TestAMEnotNPE.java

The cases which previously selected a private class method and then 
threw IllegalAccessError, no longer do that. Whether a test case results 
in a successful call or an exception depends on the overall structure of 
the test case.

- runtime/SelectionResolution/classes/selectionresolution/Template.java

As discussed in the open issue:


the selectionResolution tests need to be updated for the changes 
delivered in Nestmates. Unfortunately they are very difficult tests to 
refactor and so at this stage the failing tests have been excluded. In 
this particular case I was able to make an adjustment at the second 
level in the Template IfaceMethodrefSelectionOverrideNonPublic by 
commenting out all the cases involving private interface methods. That 
meant that, compared to commenting out the top-level tests, instead of 
reducing the test count by 7800, it only reduced by 2600.

  - jtreg hotspot/runtime
  - hs-tier1-2
  - jdk tier1-3
  - internal resolution/selection tests


More information about the valhalla-dev mailing list