[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: does GNUstep support exception as well as apple implementation?
From: |
David Chisnall |
Subject: |
Re: does GNUstep support exception as well as apple implementation? |
Date: |
Fri, 4 Jun 2010 16:24:12 +0100 |
Hi Nikolaus,
On 4 Jun 2010, at 16:04, Dr. H. Nikolaus Schaller wrote:
> Hi David,
>
> Am 04.06.2010 um 15:30 schrieb David Chisnall:
>
>> On 4 Jun 2010, at 12:18, Shuduo Sang wrote:
>>
>>> Does it mean the exception implementation of GNUstep is not complete as
>>> well as Apple runtime?
>>
>>
>> There are two implementations of exception handling for use with GNUstep.
>> One is the old NeXT-style implementation, using setjmp()/longjmp(), which is
>> slow, unsafe, and needs to die a quick and peaceful death. You may only use
>> this with the NS_DURING family of macros.
>
> Can you explain that a little?
>
> My view is:
>
> Exceptions are exceptions and should never occur in normal operation. So it
> does not matter that they are slow when they got rised (is this currect
> English?). Or you have a fundamental design problem.
Absolutely - they're called exceptions because they should happen in
exceptional circumstances.
> So, IMHO the only "cost" is the setjmp() hidden by the NS_DURING macro which
> AFAIK fills an array with some pointers and values.
setjmp() is required to dump all of the registers in the CPU into a buffer.
This is not hugely expensive, but is a significantly greater cost than nothing.
It's typically at least 16 or so instructions (including stores from FPU
registers - more if you have a vector unit) every time that you go over an
NS_DURING macro, even when no exception is thrown. This costs memory
bandwidth, d-cache usage to store the buffer, and i-cache usage to store the
string of instructions required for saving the CPU state.
In contrast, the zero-cost exceptions cost nothing unless they are actually
used. Entering an @try block does not involve executing any instructions. The
only cost is a slight increase in the size of the binary, but because the
unwinding tables are only used during unwinding they do not need to be loaded
into memory unless an exception is thrown.
When an exception is thrown with the zero-cost mechanism, the unwind library
parses these tables and calls the correct personality function for every frame
on the stack, asking it if it has cleanup code or if it has a handler. If a
handler is not found, the unwind library just aborts. If there is a handler,
then the intervening unwind code is called and then the handler.
> And what is specifically unsafe with using them? They have been in use for 20
> years now.
They are unsafe because they do not do anything like graceful unwinding of the
stack. They just load a set of CPU registers from a buffer. This gives none
of the intervening stack frames a chance to call cleanup code. For example,
you can't release a lock or deallocate on-heap temporaries if an exception is
thrown over your stack frame.
If you mix Objective-C and C++ this is especially bad. If you have C++ stack
frames, they will typically involve things like destructor calls that happen
automatically when C++ on-stack variables go out of scope. This also happens
with C code if you use __attribute__((cleanup)).
There is a reason why the NeXT documentation recommends against using
exceptions for anything other than printing a message and aborting - they leave
your program in an undefined state. Using setjmp()/longjmp() instructions is
an absolutely terrible idea and should not be done unless there are absolutely
no other options.
Note: Windows' SEH also involves a cost for entering and leaving exception
blocks, but does not have the other problems of setjmp() exceptions.
David
Re: does GNUstep support exception as well as apple implementation?, Lars Sonchocky-Helldorf, 2010/06/04
RE: does GNUstep support exception as well as apple implementation?, Nicola Pero, 2010/06/04