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

Fix TailCallStress mode. #40698

Merged
merged 1 commit into from
Aug 15, 2020
Merged

Conversation

erozenfeld
Copy link
Member

@erozenfeld erozenfeld commented Aug 12, 2020

Improve validation of tail calls that are not tail-prefixed in the IL
but are marked as such because of TailCallStress. We now do the same
correctness validation in morph for such tail calls as we do for
implicit tail calls. That blocks tail calls when we have address-taken
locals, struct promoted params, and pinned vars.

Fixes #39398.
Fixes #39309.
Fixes #38892.
Fixes #38889.
Fixes #38887.
Fixes #37117.
Fixes #8017.

@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Aug 12, 2020
@erozenfeld erozenfeld added NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) NO-REVIEW Experimental/testing PR, do NOT review it labels Aug 12, 2020
@erozenfeld
Copy link
Member Author

@erozenfeld
Copy link
Member Author

@erozenfeld
Copy link
Member Author

@AndyAyersMS These changes include switching to always dispatching tail calls via helpers with tailcallstress. Because of that I'm hitting #35687 : JIT\opt\OSR\tailrecursetry\tailrecursetry.cmd fails. #35687 was pushed to future. What do you recommend I should do with this failure? One option is to disable this test under stress.

@AndyAyersMS
Copy link
Member

Yes, you should disable under stress.

@erozenfeld
Copy link
Member Author

Disabled tailrecursetry under stress and rebased.
Started another libraries-jitstress run: https://dev.azure.com/dnceng/public/_build/results?buildId=769705&view=results

@erozenfeld erozenfeld marked this pull request as ready for review August 13, 2020 20:38
@erozenfeld erozenfeld removed NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) NO-REVIEW Experimental/testing PR, do NOT review it labels Aug 13, 2020
@erozenfeld
Copy link
Member Author

I think this is ready for review.

@AndyAyersMS @dotnet/jit-contrib PTAL

Copy link
Member

@AndyAyersMS AndyAyersMS left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this seems like a much better approach.

There is likely some code in the importer we can clean up as a result (see passedStressModeValidation), but no need to do this now.

}

assg = fgMorphTree(assg);
CORINFO_CLASS_HANDLE structHandle = call->gtRetClsHnd;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@erozenfeld Can you please expain what this part does?

Copy link
Contributor

@sandreenko sandreenko Aug 13, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was marking long on x86 as lvIsMultiRegRet that was not expected by decomposeLong (firing an assert).
Right now decomposeLong has its own mechanism to deal with such lclVars.

A long term solution could be to mark long lclVar as lvIsMultiRegRet on x86 and delete the logic from decomposeLong but for now it is not necessary.

@echesakov
Copy link
Contributor

@erozenfeld FYI, related issue #8017

PREFIX_VOLATILE = 0x00001000,
PREFIX_UNALIGNED = 0x00010000,
PREFIX_CONSTRAINED = 0x00100000,
PREFIX_READONLY = 0x01000000
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do these flags only use every forth bit?
i.e. 0x1000, 0x2000, 0x4000, 0x8000

Copy link
Member Author

@erozenfeld erozenfeld Aug 14, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any reason for that. I was just following the existing pattern.

@erozenfeld
Copy link
Member Author

@erozenfeld FYI, related issue #8017

@echesakovMSFT Thank you for pointing that out. I pushed a change to enable GitHub_11408 that is mentioned in #8017.

@erozenfeld
Copy link
Member Author

This failure in libraries-jitstress :
https://helix.dot.net/api/2019-06-17/jobs/ac0b6120-1e47-4e4c-8cab-0080a2f765f7/workitems/System.Threading.Thread.Tests/files/console.1b1c3541.log

C:\h\w\AE050963\w\AB2209B8\e>"C:\h\w\AE050963\p\dotnet.exe" exec --runtimeconfig System.Threading.Thread.Tests.runtimeconfig.json --depsfile System.Threading.Thread.Tests.deps.json xunit.console.dll System.Threading.Thread.Tests.dll -xml testResults.xml -nologo -nocolor -notrait category=IgnoreForCI -notrait category=OuterLoop -notrait category=failing  
  Discovering: System.Threading.Thread.Tests (method display = ClassAndMethod, method display options = None)
  Discovered:  System.Threading.Thread.Tests (found 45 of 49 test cases)
  Starting:    System.Threading.Thread.Tests (parallel test collections = on, max threads = 2)
    System.Threading.Threads.Tests.ThreadTests.ApartmentState_NoAttributePresent_DefaultState_Nano [SKIP]
      Condition(s) not met: "IsWindowsNanoServerAndRemoteExecutorSupported"
    System.Threading.Threads.Tests.ThreadTests.ApartmentStateTest_ChangeBeforeThreadStarted_Windows_Nano_Server [SKIP]
      Condition(s) not met: "IsWindowsNanoServer"
Stack overflow.
   at System.Threading.Threads.Tests.ThreadTests+<>c__DisplayClass2_0.<ConstructorTest>b__4()
   at System.Threading.ThreadHelper.ThreadStart_Context(System.Object)
   at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
   at System.Threading.ThreadHelper.ThreadStart()
----- end Thu 08/13/2020 21:56:29.82 ----- exit code -1073741571 ----------------------------------------------------------

seems to be unrelated. I was able to repro it locally without my changes and without tailcallstress set. It succeeded once but failed with the same "Stack overflow" on subsequent runs.

The stack trace in the debugger is

(5f54.32e0): CLR exception - code e0434352 (first chance)
(5f54.14cc): Stack overflow - code c00000fd (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
coreclr!__chkstk+0x38:
00007ffa`c72ee8d8 41c60300        mov     byte ptr [r11],0 ds:00000039`f2bc6000=00
0:023> !DumpStack
OS Thread Id: 0x14cc (23)
Current frame: coreclr!__chkstk + 0x38 [d:\A01\_work\6\s\src\vctools\crt\vcstartup\src\misc\amd64\chkstk.asm:109]
Child-SP         RetAddr          Caller, Callee
00000039F2BCDDD0 00007ffac6fa0c23 coreclr!ETW::MethodLog::SendMethodDetailsEvent + 0x1b [F:\runtime1\src\coreclr\src\vm\eventtrace.cpp:6341], calling coreclr!__chkstk [d:\A01\_work\6\s\src\vctools\crt\vcstartup\src\misc\amd64\chkstk.asm:67]
00000039F2BCDDE0 00007ffac6fa2059 coreclr!ETW::MethodLog::SendMethodJitStartEvent + 0x109 [F:\runtime1\src\coreclr\src\vm\eventtrace.cpp:6437], calling coreclr!ETW::MethodLog::SendMethodDetailsEvent [F:\runtime1\src\coreclr\src\vm\eventtrace.cpp:6341]
00000039F2BCDE30 00007ffac72fb0c8 coreclr!try_get_function + 0x38 [d:\A01\_work\6\s\src\vctools\crt\vcruntime\src\internal\winapi_downlevel.cpp:198], calling coreclr!invalid_function_sentinel [d:\A01\_work\6\s\src\vctools\crt\vcruntime\src\internal\winapi_downlevel.cpp:79]
00000039F2BCDF10 00007ffac6d864ee coreclr!EEContract::DoChecks + 0xc6 [F:\runtime1\src\coreclr\src\vm\eecontract.cpp:42], calling coreclr!BaseContract::DoChecks [F:\runtime1\src\coreclr\src\inc\contract.inl:25]
00000039F2BCDFB0 00007ffac6f9b1c2 coreclr!ETW::MethodLog::MethodJitting + 0x2ba [F:\runtime1\src\coreclr\src\vm\eventtrace.cpp:5439], calling coreclr!ETW::MethodLog::SendMethodJitStartEvent [F:\runtime1\src\coreclr\src\vm\eventtrace.cpp:6413]
00000039F2BCE160 00007ffac6c8936d coreclr!MethodDesc::JitCompileCodeLockedEventWrapper + 0x2f9 [F:\runtime1\src\coreclr\src\vm\prestub.cpp:876], calling coreclr!ETW::MethodLog::MethodJitting [F:\runtime1\src\coreclr\src\vm\eventtrace.cpp:5425]
00000039F2BCE1D0 00007ffac6ccf03c coreclr!DeadlockAwareLock::EndEnterLock + 0x214 [F:\runtime1\src\coreclr\src\vm\threads.cpp:8263], calling coreclr!DebugOnlyCodeHolder::Leave [F:\runtime1\src\coreclr\src\inc\contract.h:794]
00000039F2BCE1F0 00007ffac6d864ee coreclr!EEContract::DoChecks + 0xc6 [F:\runtime1\src\coreclr\src\vm\eecontract.cpp:42], calling coreclr!BaseContract::DoChecks [F:\runtime1\src\coreclr\src\inc\contract.inl:25]
00000039F2BCE290 00007ffac6c8778c coreclr!MethodDesc::GetMulticoreJitCode + 0xb0 [F:\runtime1\src\coreclr\src\vm\prestub.cpp:603], calling coreclr!EEContract::DoChecks [F:\runtime1\src\coreclr\src\vm\eecontract.cpp:26]
00000039F2BCE350 00007ffac6c88a08 coreclr!MethodDesc::JitCompileCode + 0x4f4 [F:\runtime1\src\coreclr\src\vm\prestub.cpp:795], calling coreclr!MethodDesc::JitCompileCodeLockedEventWrapper [F:\runtime1\src\coreclr\src\vm\prestub.cpp:802]
00000039F2BCE4B0 00007ffac6c8ab29 coreclr!MethodDesc::PrepareILBasedCode + 0x24d [F:\runtime1\src\coreclr\src\vm\prestub.cpp:404], calling coreclr!MethodDesc::JitCompileCode [F:\runtime1\src\coreclr\src\vm\prestub.cpp:693]
00000039F2BCE500 00007ffac6d864ee coreclr!EEContract::DoChecks + 0xc6 [F:\runtime1\src\coreclr\src\vm\eecontract.cpp:42], calling coreclr!BaseContract::DoChecks [F:\runtime1\src\coreclr\src\inc\contract.inl:25]
00000039F2BCE5A0 00007ffac6c8a88d coreclr!MethodDesc::PrepareCode + 0xe9 [F:\runtime1\src\coreclr\src\vm\prestub.cpp:332], calling coreclr!MethodDesc::PrepareILBasedCode [F:\runtime1\src\coreclr\src\vm\prestub.cpp:356]
00000039F2BCE660 00007ffac6b10865 coreclr!CodeVersionManager::PublishVersionableCodeIfNecessary + 0x359 [F:\runtime1\src\coreclr\src\vm\codeversion.cpp:1701], calling coreclr!MethodDesc::PrepareCode [F:\runtime1\src\coreclr\src\vm\prestub.cpp:326]
00000039F2BCE690 00007ffac6a303ed coreclr!CAutoTryCleanup<CLRException::HandlerState>::~CAutoTryCleanup<CLRException::HandlerState> + 0x11 [F:\runtime1\src\coreclr\src\inc\ex.h:608], calling coreclr!CLRException::HandlerState::CleanupTry [F:\runtime1\src\coreclr\src\vm\clrex.cpp:864]
00000039F2BCE6F0 00007ffac6c691cb coreclr!Object::ValidateInner + 0x55b [F:\runtime1\src\coreclr\src\vm\object.cpp:616], calling coreclr!CAutoTryCleanup<CLRException::HandlerState>::~CAutoTryCleanup<CLRException::HandlerState> [F:\runtime1\src\coreclr\src\inc\ex.h:599]
00000039F2BCE800 00007ffac6c29719 coreclr!MethodDesc::ContainsGenericVariables + 0x1c9 [F:\runtime1\src\coreclr\src\vm\method.cpp:900], calling coreclr!MethodDesc::GetNumGenericMethodArgs [F:\runtime1\src\coreclr\src\vm\method.cpp:731]
00000039F2BCE930 00007ffac6c84906 coreclr!MethodDesc::DoPrestub + 0x932 [F:\runtime1\src\coreclr\src\vm\prestub.cpp:2125], calling coreclr!CodeVersionManager::PublishVersionableCodeIfNecessary [F:\runtime1\src\coreclr\src\vm\codeversion.cpp:1641]
00000039F2BCE9F0 00007ffac6aaaac8 coreclr!Module::CheckActivated + 0x1d0 [F:\runtime1\src\coreclr\src\vm\ceeload.cpp:13332], calling coreclr!DomainFile::CheckActivated [F:\runtime1\src\coreclr\src\vm\domainfile.cpp:302]
00000039F2BCEA20 00007ffac6cd8585 coreclr!Thread::SetFrame + 0x3e9 [F:\runtime1\src\coreclr\src\vm\threads.cpp:266], calling ntdll!LdrpDispatchUserCallTarget
00000039F2BCEB30 00007ffac6a3d22e coreclr!AppDomain::CheckCanExecuteManagedCode + 0x1aa [F:\runtime1\src\coreclr\src\vm\appdomain.cpp:2866], calling coreclr!Module::CheckActivated [F:\runtime1\src\coreclr\src\vm\ceeload.cpp:13319]
00000039F2BCEB90 00007ffac6a43d33 coreclr!Thread::EnablePreemptiveGC + 0xdb [F:\runtime1\src\coreclr\src\vm\threads.h:2013], calling coreclr!Thread::TriggersGC [F:\runtime1\src\coreclr\src\vm\threads.h:4079]
00000039F2BCEBC0 00007ffac6a8bc33 coreclr!GCHolderBase::EnterInternalPreemp<1> + 0x1cf [F:\runtime1\src\coreclr\src\vm\threads.h:5504], calling coreclr!Thread::EnablePreemptiveGC [F:\runtime1\src\coreclr\src\vm\threads.h:1986]
00000039F2BCEC20 00007ffac6a8c248 coreclr!GCPreempThreadExists::GCPreempThreadExists + 0x30 [F:\runtime1\src\coreclr\src\vm\threads.h:5731], calling coreclr!GCHolderBase::EnterInternalPreemp<1> [F:\runtime1\src\coreclr\src\vm\threads.h:5485]
00000039F2BCEC70 00007ffac6c8d6f2 coreclr!PreStubWorker + 0x532 [F:\runtime1\src\coreclr\src\vm\prestub.cpp:1952], calling coreclr!MethodDesc::DoPrestub [F:\runtime1\src\coreclr\src\vm\prestub.cpp:2021]
00000039F2BCEE50 00007ffac6dd67f7 coreclr!ForbidGC::~ForbidGC + 0x5b [F:\runtime1\src\coreclr\src\vm\fcall.cpp:189], calling coreclr!Thread::EndNoTriggerGC [F:\runtime1\src\coreclr\src\vm\threads.h:2063]
00000039F2BCEE80 00007ffac715e5e5 coreclr!ThePreStub + 0x55 [F:\runtime1\src\coreclr\src\vm\amd64\ThePreStubAMD64.asm:21], calling coreclr!PreStubWorker [F:\runtime1\src\coreclr\src\vm\prestub.cpp:1869]
00000039F2BCEF30 00007ffac65a2c4a (MethodDesc 00007ffa68821198 + 0xca System.Threading.ThreadHelper.ThreadStart_Context(System.Object))
00000039F2BCEF80 00007ffa68d95a0c (MethodDesc 00007ffa67fbe3e0 + 0x8c System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object))
00000039F2BCEFF0 00007ffac65a2ddd (MethodDesc 00007ffa68821258 + 0x6d System.Threading.ThreadHelper.ThreadStart()), calling (MethodDesc 00007ffa67fbe3e0 + 0 System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object))
00000039F2BCF030 00007ffac715d463 coreclr!CallDescrWorkerInternal + 0x83 [F:\runtime1\src\coreclr\src\vm\amd64\CallDescrWorkerAMD64.asm:100]
00000039F2BCF070 00007ffac6d39a3c coreclr!MethodDescCallSite::CallTargetWorker + 0x884 [F:\runtime1\src\coreclr\src\vm\callhelpers.cpp:552], calling coreclr!CallDescrWorkerWithHandler [F:\runtime1\src\coreclr\src\vm\callhelpers.cpp:54]
00000039F2BCF0E0 00007ffac6d39890 coreclr!MethodDescCallSite::CallTargetWorker + 0x6d8 [F:\runtime1\src\coreclr\src\vm\callhelpers.cpp:386], calling coreclr!__chkstk [d:\A01\_work\6\s\src\vctools\crt\vcstartup\src\misc\amd64\chkstk.asm:67]
00000039F2BCF130 00007ffac6ca4362 coreclr!MetaSig::GetReturnTypeNormalized + 0x32 [F:\runtime1\src\coreclr\src\vm\siginfo.cpp:5194], calling coreclr!SigPointer::PeekElemTypeNormalized [F:\runtime1\src\coreclr\src\vm\siginfo.cpp:2349]
00000039F2BCF270 00007ffac6a468d7 coreclr!ArgIteratorTemplate<ArgIteratorBase>::ForceSigWalk + 0x1b3 [F:\runtime1\src\coreclr\src\vm\callingconvention.h:1733], calling coreclr!MetaSig::Reset [F:\runtime1\src\coreclr\src\vm\siginfo.cpp:880]
00000039F2BCF530 00007ffac6d54ee8 coreclr!ThreadNative::KickOffThread_Worker + 0x788 [F:\runtime1\src\coreclr\src\vm\comsynchronizable.cpp:247], calling coreclr!MethodDescCallSite::CallTargetWorker [F:\runtime1\src\coreclr\src\vm\callhelpers.cpp:264]
00000039F2BCF820 00007ffac6a57caa coreclr!ClrDebugState::LockReleased + 0x8e [F:\runtime1\src\coreclr\src\inc\contract.inl:289], calling coreclr!DbgStateLockData::LockReleased [F:\runtime1\src\coreclr\src\inc\contract.inl:369]
00000039F2BCF860 00007ffac6cd4415 coreclr!ManagedThreadBase_DispatchInner + 0xb9 [F:\runtime1\src\coreclr\src\vm\threads.cpp:7337], calling ntdll!LdrpDispatchUserCallTarget
00000039F2BCF920 00007ffac6cd44d6 coreclr!ManagedThreadBase_DispatchMiddle + 0x76 [F:\runtime1\src\coreclr\src\vm\threads.cpp:7381], calling coreclr!ManagedThreadBase_DispatchInner [F:\runtime1\src\coreclr\src\vm\threads.cpp:7327]
00000039F2BCF9E0 00007ffac6bb2ce1 coreclr!Frame::Push + 0x1a1 [F:\runtime1\src\coreclr\src\vm\frames.cpp:418], calling coreclr!Thread::SetFrame [F:\runtime1\src\coreclr\src\vm\threads.cpp:217]
00000039F2BCFAB0 00007ffac6cd6a3f coreclr!``ManagedThreadBase_DispatchOuter'::`11'::__Body::Run'::`5'::__Body::Run + 0x77 [F:\runtime1\src\coreclr\src\vm\threads.cpp:7540], calling coreclr!ManagedThreadBase_DispatchMiddle [F:\runtime1\src\coreclr\src\vm\threads.cpp:7341]
00000039F2BCFB00 00007ffac6cd6cff coreclr!`ManagedThreadBase_DispatchOuter'::`11'::__Body::Run + 0x7f [F:\runtime1\src\coreclr\src\vm\threads.cpp:7542], calling coreclr!``ManagedThreadBase_DispatchOuter'::`11'::__Body::Run'::`5'::__Body::Run [F:\runtime1\src\coreclr\src\vm\threads.cpp:7538]
00000039F2BCFB70 00007ffac6cd45c3 coreclr!ManagedThreadBase_DispatchOuter + 0xc7 [F:\runtime1\src\coreclr\src\vm\threads.cpp:7564], calling coreclr!`ManagedThreadBase_DispatchOuter'::`11'::__Body::Run [F:\runtime1\src\coreclr\src\vm\threads.cpp:7536]
00000039F2BCFBF0 00007ffac6cd46b2 coreclr!ManagedThreadBase_FullTransition + 0xca [F:\runtime1\src\coreclr\src\vm\threads.cpp:7588], calling coreclr!ManagedThreadBase_DispatchOuter [F:\runtime1\src\coreclr\src\vm\threads.cpp:7493]
00000039F2BCFC40 00007ffac6d864ee coreclr!EEContract::DoChecks + 0xc6 [F:\runtime1\src\coreclr\src\vm\eecontract.cpp:42], calling coreclr!BaseContract::DoChecks [F:\runtime1\src\coreclr\src\inc\contract.inl:25]
00000039F2BCFCE0 00007ffac6d546a4 coreclr!ThreadNative::KickOffThread + 0x1c4 [F:\runtime1\src\coreclr\src\vm\comsynchronizable.cpp:327], calling coreclr!ManagedThreadBase::KickOff [F:\runtime1\src\coreclr\src\vm\threads.cpp:7621]
00000039F2BCFE70 00007ffb39b07bd4 KERNEL32!BaseThreadInitThunk + 0x14, calling ntdll!LdrpDispatchUserCallTarget
00000039F2BCFEA0 00007ffb3b0ace51 ntdll!RtlUserThreadStart + 0x21, calling ntdll!LdrpDispatchUserCallTarget

@AndyAyersMS
Copy link
Member

@erozenfeld anything else you're planning on doing before merging?

@erozenfeld
Copy link
Member Author

@AndyAyersMS Yes, there are 3 failures in libraries-jitstress (Linux x64 and Linux arm64) that I need to investigate. I suspect these may be product bugs exposed by my change to always dispatch tail calls via helpers under tailcallstress. If that's the case I'll remove that change from this PR and address those bugs separately.

@AndyAyersMS
Copy link
Member

Need any help?

@erozenfeld
Copy link
Member Author

No, at the moment I'm not blocked on anything.

@erozenfeld
Copy link
Member Author

If you want, take a look at the issue I described in #40698 (comment) . I was able to repro it on a clean clone without my changes but I only saw it in CI with my changes. It appears to be non-deterministic but fails almost 100% for me.

@erozenfeld
Copy link
Member Author

It may be something similar to #10015

Improve validation of tail calls that are not tail-prefixed in the IL
but are marked as such because of TailCallStress. We now do the same
correctness validation in morph for such tail calls as we do for
implicit tail calls. That blocks tail calls when we have address-taken
locals, struct promoted params, and pinned vars.

Fixes dotnet#39398.
Fixes dotnet#39309.
Fixes dotnet#38892.
Fixes dotnet#38889.
Fixes dotnet#38887.
Fixes dotnet#37117.
Fixes dotnet#8017.
@erozenfeld
Copy link
Member Author

I confirmed that the libraries-jitstress failures were exposed by switching to always dispatching tail calls via helpers under tailcallstress. I removed that change from this PR and will address those failures separately.

Re-started stress jobs.

jitstress: https://dev.azure.com/dnceng/public/_build/results?buildId=771604&view=results
libraries-jitstress: https://dev.azure.com/dnceng/public/_build/results?buildId=771599&view=results

@AndyAyersMS PTAL at the current changes

Copy link
Member

@AndyAyersMS AndyAyersMS left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, just to sum up, the impact is that under tail call stress, we will now

  • validate correctness of "stress" tail calls like we do implicit tail calls
  • dispatch stress tail calls as tail calls via a helper (or as fast tail calls)
  • dispatch implicit tail calls as fast tail calls (reject if requires a helper)

One would hope the parenthetical sets above are empty, and the behavior change from tail call stress mode is to now allow slow implicit tail calls in addition to the tail calls the jit would normally perform. Is that right?

@erozenfeld
Copy link
Member Author

erozenfeld commented Aug 14, 2020

validate correctness of "stress" tail calls like we do implicit tail calls

It's almost the case. This change ensures that the validation we do in morph for implicit tail calls also applies to stress calls.
The remaining difference is in the importer: we do verCheckTailCallConstraint validation for stress calls but don't do it for implicit calls. It shouldn't matter since the checks in impImportCall and in morph should cover verCheckTailCallConstraint checks. As you mentioned in #12833 (comment) and #40698 (review) this is something that needs to be cleaned up.

dispatch stress tail calls as tail calls via a helper (or as fast tail calls)

In the current state that is correct. My initial attempt was to always dispatch stress tail calls via a helper. That uncovered some issues in the new tail calls via helpers mechanism that I'm investigating. Once they are fixed we should switch to dispatching all stress tail calls via a helper.

dispatch implicit tail calls as fast tail calls (reject if requires a helper)

Correct, that part is not changed.

@erozenfeld
Copy link
Member Author

We gain two things from tailcallstress:

  1. Slow implicit tail calls. That's especially important for platforms that don't support fast tail calls: x86 and arm32.
  2. Inlining wins against implicit tail calls but stress tail calls win against inlining.

Copy link
Member

@AndyAyersMS AndyAyersMS left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks again. This is a big improvement in tail call stress reliability.

@erozenfeld
Copy link
Member Author

libraries-jitstress failures are #40607 and #37291.

@erozenfeld
Copy link
Member Author

jitstress failures are #40751.

@erozenfeld erozenfeld merged commit 7742b57 into dotnet:master Aug 15, 2020
@karelz karelz added this to the 5.0.0 milestone Aug 18, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 7, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.