You look at the implementation details: they, as a rule, do not meet each other's ECMA specifications for many possible reasons (for example, ease of implementation, code sharing, providing additional semantics, future protection, optimization, etc.).
In this particular case, there are several considerations.
Mono handles exceptions based on a view of the state of the MonoContext processor: since this structure is used elsewhere, it contains all the appropriate registers, even if some of them may not be needed in some specific cases. In particular, exception handling can also be triggered from a processor exception, where all registers must be restored, so they are all collected.
Someone already noticed that context is also used for the debugger.
Consider also the case of a try / catch method with a catch being a simple local var setting. Now the extended register allocator can put a local var, which is used as before the throw (note that the throw can be implicit, like a null reference, this is handled by cpu exception) and after catch in the register, for example edx. If you do not save all the registers at the throw / exception point, you have corrupted the program state, since edx will be overwritten during exception handling.
As a final comment: are you worried that storing a few extra registers is a waste of processor cycles? If you actually count the cycles spent, they completely in noise accept everything that should happen during exception handling.
source share