-
Notifications
You must be signed in to change notification settings - Fork 3
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
Simple Exception Support #424
Comments
Will need to store EH clauses for methods with try/catch/finally blocks. IP Start Is it worth extending above so that arbitrary info can be stored per method. In effect we have a map from instruction pointer address via IP range to a MethodTable data structure that can hold the EH Clauses and other info in the future too? |
Currently not all methods include normal stack frame setup transferring the original SP into IX:
However, doesn't look like this happens on many methods e.g. for Snake there are only 2 methods without stack frame setup. Also these methods look like they'd be good candidates for inlining - so perhaps that is the long term solution. For Exception handling - will need to add new config option and will use this to ensure that stack frame setup is always emitted for all methods. |
Real dotnet runtime maps instruction pointer to method info via the EEJitManager::FindMethodCode(..) method. This makes use of interesting data structure, the nibble map. |
Instead of throw opcode codegen call to ExceptionHandling.ThrowException(..) it needs to call an assembly code routine to capture the true exceptions IP address and framepointer. These need to be packaged into a struct and then passed on to ExceptionHandling.ThrowException. The assembly code routine e.g. ThrowEx, will be something like this:
Note there is no need to call ThrowException as we don't expect it to ever return directly - it's going to call handlers/unwind the stack or ultimately call the unhandled exception handler. |
There is a problem with unwinding as we can determine SP at point call was made to current frame but we don't know the number of parameters on the stack. This is only an issue due to the stack under/overflow validation logic emitted in the Ret code generator - having the unwound SP effectively such that the calling parameters are left on the stack is probably okay as none of the codegen for subsequent basic blocks will be making any assumptions about what is on the actual stack. Alternatively need a way to determine the number of parameters on the stack to virtually remove. Could use a loop table for the method call we are unwinding but this would require at least 3 bytes per method e.g. address of method being called, and number of parameters (could just be a single byte). Stack frame iterator would need to lookup in the table and use entry to work out exact SP prior to method call. |
Sample code that illustrates problem with incorrect unwinding due to not removing parameters from calls. This code will eventually overflow the stack as each call to N will push 4 bytes on the stack for the int, but this is not unwound.
Option for solving this is to generate unwind table used during the unwind process to apply appropriate delta to SP to remove the method parameters from the stack. Note that we don't need to include entries in this table for every method in the program - only those that are called within try blocks. The unwind table could be represented as a range of PC addresses and the delta SP. However, it might be possible to just use the address of the start of the method - as when unwinding we will have the return address, which is directly after the CALL instruction to the method, so can extract from the CALL instruction the address of the start of the method. |
SSA may need revisiting as some test programs have been resulting in errors in the SSA analysis. |
Current overhead for exception handling is roughly 2k - so definitely large enough to keep exceptions behind feature flag for now. |
Look at exception handling in nativeaot - most of logic is in System.Runtime.ExceptionHandling.cs
https://github.com/dotnet/runtime/blob/acc3f0cea4057f8bde7ffebdabd1dc62c4ebef0b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ExceptionHandling.cs#L4
Still uses native code for actual stack unwinding though.
rethrow
The text was updated successfully, but these errors were encountered: