4

12322: Fix deep recursive expression processing by dsyme · Pull Request #12420 ·...

 2 years ago
source link: https://github.com/dotnet/fsharp/pull/12420
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Copy link

Contributor

dsyme commented on Nov 18

edited

#12322 is a related to processing very large expressions recursively, where these expressions are not already recognised as "linear".

Normally when processing F# expressions the depth is small, e.g. 10, though for some known "linear" sequences such as long lists of let bindings, the depth may be arbitrarily large. We already code the compiler to handle these.

However some potentially-linearizable expressions are not detected and it's really hard to detect and handle them properly systematically. Some examples include

  • Very long pipelines A |> A |> A ...
  • Very long computation expressions thing { 1;2;3;4;.. .}
  • Very deep hand-written expressions M(M(M(M(M....)

We can at least guard against this kind of problem by jumping to a new thread stack when non-linear processing of deeply recursive is detected. This isn't ideal but it works.

Overall this protects us against the real problem of #12322 which is that stack depth varies on the six configurations of running our compiler

  • 32-bit .NET Framework fsc.exe
  • 64-bit .NET Framework fscAnyCpu.exe/devenv.exe
  • 64-bit .NET 6 fsc.dll

It does this by making much more of our deep-stack processing independent of actual available stack size.

Testing:

  • I've done manual testing to uncover the problematic recursive processing for the case of long computation expressions from #12322
  • Add stress tests for each of the three cases above
  • Run them in both debug and release mode
  • Run them when generating both optimized and debug code
  • Run them in all three of net472 fsc.exe, net472 fscAnyCpu.exe and .NET 6 fsc.dll
  • Run them in all three of net472 fsi.exe, net472 fsiAnyCpu.exe and .NET 6 fsi.dll
  • Test with "full" and "portable" PDB generation

Manual testing notes for the whole matrix (except Windows v. Linux v. macOS)

# Debug compiler, release codegen, no debug 
del test.exe && artifacts\bin\fscAnyCpu\Debug\net472\fscAnyCpu.exe tests/fsharp/regression/12322/test.fsx  && dir test.exe
del test.exe && artifacts\bin\fsc\Debug\net472\fsc.exe tests/fsharp/regression/12322/test.fsx  && dir test.exe
del test.exe && dotnet artifacts\bin\fsc\Debug\net5.0\fsc.dll tests/fsharp/regression/12322/test.fsx  && dir test.exe

# Debug compiler, debug codegen, debug full
del test.exe && artifacts\bin\fscAnyCpu\Debug\net472\fscAnyCpu.exe --optimize- --debug:full --tailcalls- tests/fsharp/regression/12322/test.fsx  && dir test.exe
del test.exe && artifacts\bin\fsc\Debug\net472\fsc.exe --optimize- --debug:full --tailcalls- tests/fsharp/regression/12322/test.fsx  && dir test.exe
del test.exe && dotnet artifacts\bin\fsc\Debug\net5.0\fsc.dll --optimize- --debug:full --tailcalls- tests/fsharp/regression/12322/test.fsx  && dir test.exe

# Debug compiler, debug codegen, debug portable
del test.exe && artifacts\bin\fscAnyCpu\Debug\net472\fscAnyCpu.exe --optimize- --debug:portable --tailcalls- --define:PORTABLE_PDB tests/fsharp/regression/12322/test.fsx  && dir test.exe
del test.exe && artifacts\bin\fsc\Debug\net472\fsc.exe --optimize- --debug:portable --tailcalls- --define:PORTABLE_PDB tests/fsharp/regression/12322/test.fsx  && dir test.exe
del test.exe && dotnet artifacts\bin\fsc\Debug\net5.0\fsc.dll --optimize- --debug:portable --tailcalls- --define:PORTABLE_PDB tests/fsharp/regression/12322/test.fsx  && dir test.exe

# Debug fsi, normal codegen
artifacts\bin\fsi\Debug\net472\fsi.exe tests/fsharp/regression/12322/test.fsx  
artifacts\bin\fsiAnyCpu\Debug\net472\fsiAnyCpu.exe tests/fsharp/regression/12322/test.fsx  
dotnet artifacts\bin\fsi\Debug\net5.0\fsi.dll tests/fsharp/regression/12322/test.fsx  

# Release compiler, release codegen, no debug 
del test.exe && artifacts\bin\fscAnyCpu\Release\net472\fscAnyCpu.exe tests/fsharp/regression/12322/test.fsx  && dir test.exe
del test.exe && artifacts\bin\fsc\Release\net472\fsc.exe tests/fsharp/regression/12322/test.fsx  && dir test.exe
del test.exe && dotnet artifacts\bin\fsc\Release\net5.0\fsc.dll tests/fsharp/regression/12322/test.fsx  && dir test.exe

# Release compiler, debug codegen, debug full
del test.exe && artifacts\bin\fscAnyCpu\Release\net472\fscAnyCpu.exe --optimize- --debug:full --tailcalls- tests/fsharp/regression/12322/test.fsx  && dir test.exe
del test.exe && artifacts\bin\fsc\Release\net472\fsc.exe --optimize- --debug:full --tailcalls- tests/fsharp/regression/12322/test.fsx  && dir test.exe
del test.exe && dotnet artifacts\bin\fsc\Release\net5.0\fsc.dll --optimize- --debug:full --tailcalls- tests/fsharp/regression/12322/test.fsx  && dir test.exe

# Release compiler, debug codegen, debug portable
del test.exe && artifacts\bin\fscAnyCpu\Release\net472\fscAnyCpu.exe --optimize- --debug:portable --tailcalls- --define:PORTABLE_PDB tests/fsharp/regression/12322/test.fsx  && dir test.exe
del test.exe && artifacts\bin\fsc\Release\net472\fsc.exe --optimize- --debug:portable --tailcalls- --define:PORTABLE_PDB tests/fsharp/regression/12322/test.fsx  && dir test.exe
del test.exe && dotnet artifacts\bin\fsc\Release\net5.0\fsc.dll --optimize- --debug:portable --tailcalls- --define:PORTABLE_PDB tests/fsharp/regression/12322/test.fsx  && dir test.exe

# Release fsi, normal codegen
artifacts\bin\fsi\Release\net472\fsi.exe tests/fsharp/regression/12322/test.fsx
artifacts\bin\fsiAnyCpu\Release\net472\fsiAnyCpu.exe tests/fsharp/regression/12322/test.fsx
dotnet artifacts\bin\fsi\Release\net5.0\fsi.dll tests/fsharp/regression/12322/test.fsx

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK