-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
JIT: revise how the jit tracks use of generics context #34827
JIT: revise how the jit tracks use of generics context #34827
Conversation
The generics context is reported by the jit specially whenever it feeds into runtime lookups, as expansion of those lookups can expose pointers into runtime data structures, and we don't want those data structures to be collected if jitted code is still using them. Sometimes uses of the context are optimized away, and reporting costs code size and GC space, so we don't want to report the context unless there is an actual use. This change revises how the jit keeps track of context use -- instead of trying to incrementally ref count uses of the generics context, we now just leverage existing passes which do local accounting. Initial motivation for this came from dotnet#34641 where the context use was over-reported, but investigation showed we also some times under-report as the context var could be cloned without changing the ref count. So this change fixes both under and over reporting. Closes dotnet#34641.
cc @dotnet/jit-contrib There were more cases of under-reporting than over-reporting, so a slight code size increase overall.
|
@dotnet/jit-contrib PTAL |
@BruceForstall maybe you can look this over. There might be some "cheaper" way to identify |
Will try to look soon |
src/coreclr/src/jit/compiler.h
Outdated
@@ -3127,7 +3125,7 @@ class Compiler | |||
|
|||
#endif // defined(DEBUG) && defined(TARGET_X86) | |||
|
|||
unsigned lvaGenericsContextUseCount; | |||
unsigned lvaGenericsContextInUse; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unsigned lvaGenericsContextInUse; | |
bool lvaGenericsContextInUse; |
src/coreclr/src/jit/compiler.hpp
Outdated
@@ -1944,14 +1943,12 @@ inline bool Compiler::lvaKeepAliveAndReportThis() | |||
// because collectible types need the generics context when gc-ing. | |||
if (genericsContextIsThis) | |||
{ | |||
const bool isUsed = lvaGenericsContextUseCount > 0; | |||
const bool isUsed = lvaGenericsContextInUse; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can just use lvaGenericsContextInUse
without introducing isUsed
.
The only thing I could think of would be to add a "pass-through" node above it. That would mean having to add handling for that wherever these might be encountered, so it might be worse. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good overall. Left a few minor suggestions.
JITDUMP("Reporting this as generic context: %u refs%s\n", lvaGenericsContextUseCount, | ||
mustKeep ? ", must keep" : ""); | ||
|
||
JITDUMP("Reporting this as generic context: %s\n", mustKeep ? "must keep" : "referenced"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You kept the JITDUMP
here but removed it a few lines above and in lvaReportParamTypeArg()
. It would be better to be consistent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure.
@@ -3127,7 +3125,7 @@ class Compiler | |||
|
|||
#endif // defined(DEBUG) && defined(TARGET_X86) | |||
|
|||
unsigned lvaGenericsContextUseCount; | |||
bool lvaGenericsContextInUse; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super nit: You are using "generics context" and "generic context" inconsistently in var names and comments in this change. I think it should be "generic context".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are many many uses of "generics context" so it seems simplest to standardize on that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm many votes in both camps. There are 137 case-insensitive uses of
generic.*(context|ctxt)
and 77 uses of
generics.*(context|ctxt)
The "S" variant appears in enums in corinfo.h so can't easily be updated. But we can fix other appearances if you think it's worthwhile.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably not worth cleaning this up in this PR.
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bool reportParamTypeArg = lvaReportParamTypeArg(); | |
if (lvaKeepAliveAndReportThis()) | |
{ | |
lvaGetDesc(0u)->lvImplicitlyReferenced = reportParamTypeArg; | |
} | |
else if (reportParamTypeArg) | |
{ | |
// We should have a context arg. | |
assert(info.compTypeCtxtArg != BAD_VAR_NUM); | |
lvaGetDesc(info.compTypeCtxtArg)->lvImplicitlyReferenced = true; | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will update.
Reran diffs; similar to the above. |
The generics context is reported by the jit specially whenever it feeds into
runtime lookups, as expansion of those lookups can expose pointers into runtime
data structures, and we don't want those data structures to be collected if
jitted code is still using them.
Sometimes uses of the context are optimized away, and reporting costs
code size and GC space, so we don't want to report the context unless there
is an actual use.
This change revises how the jit keeps track of context use -- instead of trying
to incrementally ref count uses of the generics context, we now just leverage
existing passes which do local accounting.
Initial motivation for this came from #34641 where the context use was
over-reported, but investigation showed we also some times under-report as
the context var could be cloned without changing the ref count.
So this change fixes both under and over reporting.
Closes #34641.