On 08/04/14 14:03, David Nadlinger wrote:
On Tuesday, 8 April 2014 at 10:08:24 UTC, Jacob Carlborg wrote:
Is there a reason to not use the same model, or what's required to be
compatible?
In short, the reason not to use the same "model" (you could argue that
the model is the same, as only the personality functions differ) is that
the exception unwinder is intimately tied to both the target language
ABI and semantics.
For example, all unwinders need to handle the run-time type information
for the exception object to correctly dispatch it. And while e.g. the
GNU C++ unwinding implementation needs to pull shenanigans to implement
the crazy C++ exception lifetime model (cf. catching by reference vs. by
value) and enforce throws(...) specifications, the D unwinder needs to
understand the difference between Exception and Error and correctly
implement exception chaining.
Now, of course, it is possible to find a middle ground that works as a
basis for virtually all languages. In fact, I'd argue that SEH for
Windows actually provides such a layer, and libunwind does too. For
example, a proper implementation of a libunwind personality function
allows you to check whether a given exception originated in your own
language, and just pass it on otherwise (such that e.g. C++ exception
just bubble through a layer of D code). In theory, it would e.g. also be
possible to wrap foreign exceptions in e.g. D Throwable objects to make
them catchable in D code. But the lifetime of the foreign object is
virtually impossible to get right in the general case, and the benefits
of wrapping exceptions like this have turned out not to be worth it,
because it is hard to handle them in a sensible way in the receiving
language (DMD actually does – did? – something like this on Win32).
A middle ground would help. In the D/Objective-C implementation there is
already an exception bridge for 32bit. The 32bit implementation uses
setjmp and longjmp.
For transferring D exceptions to Objective-C the compiler sets up a
try-catch. Then there's a subclass of NSException (the root exception
class in Objective-C) which wraps a D Throwable. This NSException is
then thrown using the Objective-C runtime function for throwing exceptions.
For transferring exceptions in the other direction bascilly the same
thing happens. The compiler uses setjmp and longjmp to catch the
Objective-C exception. This is then wrapped as a D exception, a subclass
of Throwable, and thrown using the D runtime function for throwing
exceptions.
For 64bit, Objective-C uses the same exception handling as C++. So I
need to somehow be able to catch Objective-C exceptions and Objective-C
need to be able to catch D exceptions. Although I still expect to need
to wrap the exceptions, since D code won't be expecting to catch
instances of NSException, which doesn't inherit from Throwable. Same on
the Objective-C side.
If D would use the C++ exception handling model I hope that the
implementation would be a lot simpler.
--
/Jacob Carlborg