Disallow nop guards for interface call sites #16122
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
...unless inliner has already proved that the receiver is an instance of a particular class that implements the expected interface. (However, it appears that it is currently difficult or maybe impossible to get such a bound despite
tryToRefineReceiverClassBasedOnResolvedTypeArgInfo()
).A passing
vgnop
-based interface guard can guarantee the receiver type is as expected by the inlined body, but only if we already know before the guard that the receiver implements the expected interface. Here, an interface type bound is insufficient to know that, because bytecode verification does not guarantee any particular receiver type atinvokeinterface
.As such, in the absence of a class (i.e. non-interface) type bound on the receiver, all targets must use profiled guard. Additionally, the profiled guard must ensure on the hot side that the receiver is an instance of the interface expected at this call site.
There was one circumstance where it was possible to generate a profiled guard with method test for a method defined by a class that does not implement the interface. Inliner now uses a VFT test instead in this situation. Only hot compilations performed during startup are affected.
It was also possible to generate an interface (nop) guard for a single implementer method defined by a class that does not implement the interface. Since this must now be a profiled guard, inliner will only accept single implementers defined by classes that do implement the interface. Others will be rejected in the hope that it will be possible to generate a VFT test based on profiling.
Without these precautions, it would be possible for the JIT to inline a single implementing method with a nop guard, and for execution to flow into the inlined body with a receiver that is not an instance of the class expected by the inlined code. The inlined code could then access fields of the receiver as though it were of the expected type.
This series has a few additional changes mainly to reduce the performance impact of all of the additional profiled guards: