Allow CALLEE_IS_FORCE_INLINE precedent over CALLEE_DOES_NOT_RETURN#14586
Allow CALLEE_IS_FORCE_INLINE precedent over CALLEE_DOES_NOT_RETURN#14586AndyAyersMS merged 2 commits intodotnet:masterfrom
Conversation
04d699a to
3be2dd3
Compare
It does look correct but I'm not convinced that using "forceinline" to control stacktraces is the right thing to do. It normally works the other way around - you use "no inline" to ensure that a particular method does show up in the stack trace. All the time. That's because "no inline" can normally be relied on, it always works unless the compiler is dumb. That's not the case with "forceinline", it is an optimization hint and there's no guarantee that the compiler will respect it. When an optimization is not performed the "normal" outcome is a drop in performance, not a change in observable behavior. I'm not very familiar with |
Line numbers go off if you separate the restore and throw #14564 (comment) Though ideally its what I'd like to do; however it should still tend to inline for upstack (would need api review for exposing the exception and its behaviour fixed) |
I think that's fine; the issue is currently "no return" is the equivalent of "no inline"; so its more a way of removing the "no inline", without changing the method to return something or making it more complicated so it drops the "no return" - at which point it probably wouldn't inline anyway :) |
|
Agree with @mikedn -- not convinced this particular use case makes sense. The runtime should have various bits of magic to make exceptions appear "as if" they were raised in the caller frame which might be more applicable here. Also somewhere down the road we might get around to creating synthetic frames for inlined methods. The jit has most of this info today, but has no way to pass it back to the runtime. At any rate, the idea of allowing force inline to override the inliner's "profitability" checks is sound; the aggressive inline annotation should basically mean "inline if at all possible". I generally don't like to suppress observations, but instead suppress their effects. So I would have implemented this by modifying case InlineObservation::CALLEE_NUMBER_OF_BASIC_BLOCKS:
...
if (m_IsNoReturn && (basicBlockCount == 1)) // && !m_IsForceInline
{
SetNever(InlineObservation::CALLEE_DOES_NOT_RETURN);
} |
Depends on the context. It looks like you are trying to cleanup some stacktraces and you want to rely on a mechanism (inlining) that works only when optimizations are enabled. So in Debug builds you get messy stacktraces and in Release builds you get clean stacktraces. That's sort of upside down. |
|
FWIW I think the long term solution to this class of issue is to modify how we generate the textual form of stacktraces that developers read rather than imposing constraints on codegen. However as an interim step I don't see anything wrong with adjusting the underlying code if those changes aren't causing concerns in other aspects of design/performance/etc. More discussion is in #14564 if you want to see it. |
I don't think its the long term solution; however EDI is used quite a lot by aspnet and they and users are already having issue with the async stack trace length and the "no return" change adds another entry in each step
Its a compromise, in Debug you are dealing with one stack trace at a time; in Release you might be logging thousands or hundreds of thousands; increasing data volumes and making it harder to spot patterns in aggregate. Will add comment that its a temporary work around. EDI aside; not sure the non-specified "no-return" should take precedence over the specified "aggressive inline"; i.e. have no opt out.
m_IsForceInline set prior to the observation? I'm guessing so as is attribute vs method body processing Will change, is much better |
This change is unlikely to fix aspnet cases for most users. aspnet should be R2R precompiled in most cases. The R2R precompilation prohibits cross-module inlining. |
|
Formatting fix #14602 |
Most of the aspnet stack traces would be cleaned up by #14564 Have removed the EDI change from this PR - is a separate issue |
Added change for StackTraces that also works for Debug mode #14608 |
cb14727 to
d46784b
Compare
d46784b to
2f4b273
Compare
|
Rebased |
|
Is this still something you're interested in pursuing? As noted above I'd rather not suppress observations as this limits the ability to experiment with policy changes -- instead the policy should decide whether or not an observation implies the inline should fail. So the change should be just a simple edit to the if (!m_IsForceInline && m_IsNoReturn && (basicBlockCount == 1))
{
SetNever(InlineObservation::CALLEE_DOES_NOT_RETURN);
} |
Yes, more for the principle at this stage rather than any particular use case, now 😄 Should be able to opt-out in some way. Made the change |
|
Centos failure @dotnet-bot test CentOS7.1 x64 Checked Innerloop Build and Test |
AndyAyersMS
left a comment
There was a problem hiding this comment.
I think this is a reasonable change; aggressive inline should override the jit heuristics when safe to do so.
|
@benaadams thanks! |
Currently
CALLEE_DOES_NOT_RETURNwill take precedent overCALLEE_IS_FORCE_INLINEthis can be undesirable as there is no way to get a non-returning method to then inline.Resolves: https://github.com/dotnet/coreclr/issues/14585
@AndyAyersMS @mikedn is this a correct approach?