For one thing, they’re expensive and viral. “Zero overhead” implementations don’t take into account the need for unwind tables. For every function/method that might be thrown across. They’re disabled in a lot of production environments for this reason.
The CPU can not remember an infinite number of branches. Also, many branches will increase code size. With exceptions the unwind tables and unwind code can be placed elsewhere and not take up valuable L1 cache.
> The CPU can not remember an infinite number of branches.
I suspect a modern CPU has a branch instruction saying "This branch will never be taken except in exceptions, so assume this branch is not taken". But I must admit I haven't seriously looked at assembly language for some time.
(EDIT: yes, modern CPUs including x86 and ARM allow the programmer/compiler to hint if a branch is expected to be taken).
> Also, many branches will increase code size.
I'd like to see some data on that. Of course branches take code size, but how much is that percentage-wise? I suspect not much.
You should take a look at the presentation I mentioned elsewhere in this thread. You also have to keep in mind that it's not only the branches that use space, but also the error handling code. Code which must be duplicated for every single call to a particular function.
Ok, thanks. But that code needs to be loaded into memory only if the branch takes place. Which, for exceptions, will be not often. The main assumption is: optimize for the common case, where exceptions are not the common case.