Open gacholio opened 5 years ago
Related to https://github.com/eclipse/openj9/issues/771
This will eventually require some JIT work to handle resolved methods which get deleted.
Experiments show that the the JVMTI can_maintain_original_method_order sorts the methods in the class according to the original class file (i.e. if the capability is acquired, and a redefinition reorders the methods in a class, the JVMTI GetClassMethods calls returns the original order [returns the same both before and after the reordering]).
It's not clear what this will mean in the presence of added and removed methods.
Some questions we need answered:
Obvious alternatives are: use placeholder method to throw, continue running the deleted method, re-resolve.
If a method is resolved, and a new method which would have been resolved is added, do we keep running the resolved method, or "correct" the invoke?
Perhaps if this capability is acquired, we cannot add/remove private.
Certainly not interested in trying to maintain ordering for deletion and re-addition of the same method.
Perhaps more than one, if we are to allow final/static.
Testing on Oracle openjdk10, the VM allows the addition (but not deletion) of private final methods.
Based on one testcase, the newly-added method does not cause re-resolution. The testcase is:
A public m() B extends A C extends B public m() { super.m() }
Where the super call targets A (not B as the compiler would generate).
The super call resolves to A.m(). If B is replaced adding "private final m()", the super call continues to run A.m(). If B.m() were present during resolution, it would be targetted.
Also, as expected, "resolve failed" state is not saved for method resolutions, which means that adding methods can cause previous failures to succeed the next time around.
A B extends A C extends B public m() { super.m() }
The super targets B in this case.
The super call fails with NoSuchMethodError (as it should). If B is replaced adding "private final m()", the super call then fails with IllegalAccessError, meaning the resolution was attempted again.
Also worth noting that the newly-added method breaks the ordering enforcement for can_maintain_original_method_order:
methods before:
<init>()V
<end>
methods after:
m()V
<init>()V
<end>
So m() was not added to the end as would be expected.
Looks like the order of the new class file is obeyed in the addition case:
methods before:
<init>()V
<end>
methods after:
m2()V
<init>()V
m()V
<end>
-Xfuture has no effect on the ability to add private final methods.
Also verified Oracle only allows addition of:
The addition or removal of methods which do not affect the shape of the vTable should be allowed in fast HCR.
Methods which never appear in the vTable are:
Methods which do not need to appear in the vTable but currently do:
New final methods should follow the invokeprivate path. This is likely a matter of removing their vTable modifier and modifying the restrictions on which methods can use invokeprivate during resolution.