Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent JIT bodies from strictly outliving methods inlined into them #7673

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

jdmpapin
Copy link
Contributor

This is largely in preparation for constant references, but it should also have benefits for code motion. For more detail, see the Motivation section of the doc comment for RetainedMethodSet.

Much of this commit is OMR::RetainedMethodSet, which describes a set of methods that will remain loaded under certain assumptions. This is a base class that is meant to be subclassed in any downstream project that allows methods to be dynamically unloaded.

During inlining, each TR_CallSite and TR_CallTarget will now have an associated RetainedMethodSet. Often, all methods named at call sites and all selected call targets can be established to outlive their callers, and transitively the outermost method. In this case, nothing of note happens.

However, sometimes a call site is refined based on a known object, and the refined method is not already known to outlive its caller. In this case, a nested RetainedMethodSet is created to represent the refined method (in addition to the surrounding inline context). Any further nested call sites and call targets can therefore take this refined method for granted. If the call site is actually inlined, then we record a "keepalive" for the refined method. The idea of a keepalive is that the JIT compiler should create an additional reference to prevent that method from being unloaded as long as the JIT body is still valid. In this commit, no such reference is created because we do not yet have a mechanism to do so. They will be implemented later as extra constant references. In the meantime, the JIT will simply assume that anything covered by a keepalive will remain loaded on its own. This assumption isn't great, but it's essentially the same as our existing pervasive assumption that known object indices will remain accurate.

Similarly, sometimes a call target is selected based on profiling or a single implementer, and the target method is not already known to outlive the base method named at the call site. In this case, a nested RetainedMethodSet is created to represent the target method (in addition to the surrounding inline context). Any further nested call sites and call targets can therefore take this target method for granted. If the call target is actually inlined, then we record a "bond" for the target method. The idea of a bond is to limit the lifetime of the JIT body to prevent it from strictly outliving the inlined method. This should be accomplished in a downstream project by creating an unload assumption so that when the inlined method is unloaded, the JIT body will be invalidated (similarly to preexistence).

If the dontInlineUnloadableMethods option is set, then instead of requesting bonds, inliner will refuse to inline targets that would required them. In this case, assertions check after optimization that no inlined method will be unexpectedly unloaded.

This is largely in preparation for constant references, but it should
also have benefits for code motion. For more detail, see the Motivation
section of the doc comment for RetainedMethodSet.

Much of this commit is OMR::RetainedMethodSet, which describes a set of
methods that will remain loaded under certain assumptions. This is a
base class that is meant to be subclassed in any downstream project that
allows methods to be dynamically unloaded.

During inlining, each TR_CallSite and TR_CallTarget will now have an
associated RetainedMethodSet. Often, all methods named at call sites
and all selected call targets can be established to outlive their
callers, and transitively the outermost method. In this case, nothing of
note happens.

However, sometimes a call site is refined based on a known object, and
the refined method is not already known to outlive its caller. In this
case, a nested RetainedMethodSet is created to represent the refined
method (in addition to the surrounding inline context). Any further
nested call sites and call targets can therefore take this refined
method for granted. If the call site is actually inlined, then we record
a "keepalive" for the refined method. The idea of a keepalive is that
the JIT compiler should create an additional reference to prevent that
method from being unloaded as long as the JIT body is still valid. In
this commit, no such reference is created because we do not yet have a
mechanism to do so. They will be implemented later as extra constant
references. In the meantime, the JIT will simply assume that anything
covered by a keepalive will remain loaded on its own. This assumption
isn't great, but it's essentially the same as our existing pervasive
assumption that known object indices will remain accurate.

Similarly, sometimes a call target is selected based on profiling or a
single implementer, and the target method is not already known to
outlive the base method named at the call site. In this case, a nested
RetainedMethodSet is created to represent the target method (in addition
to the surrounding inline context). Any further nested call sites and
call targets can therefore take this target method for granted. If the
call target is actually inlined, then we record a "bond" for the target
method. The idea of a bond is to limit the lifetime of the JIT body to
prevent it from strictly outliving the inlined method. This should be
accomplished in a downstream project by creating an unload assumption so
that when the inlined method is unloaded, the JIT body will be
invalidated (similarly to preexistence).

If the dontInlineUnloadableMethods option is set, then instead of
requesting bonds, inliner will refuse to inline targets that would
required them. In this case, assertions check after optimization that no
inlined method will be unexpectedly unloaded.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants