On 12/11/2012 9:51 PM, David Piepgrass wrote:
The problem, as I see it, is nobody actually cares about this. Why would I say
something so provocative? Because I've seen D programmers go to herculean
lengths to get around problems they are having in the language. These efforts
make a strong case that they need better language support (UDAs are a primo
example of this). I see nobody bothering to write a CheckedInt type and seeing
how far they can push it, even though writing such a type is not a significant
challenge; it's a bread-and-butter job.
I disagree with the analysis. I do want overflow detection, yet I would not use
a CheckedInt in D for the same reason I do not usually use one in C++: without
compiler support, it is too expensive to detect overflow. In my C++ I have a lot
of math to do, and I'm using C++ because it's faster than C# which I would
otherwise prefer. Constantly checking for overflow without hardware support
would kill most of the performance advantage, so I don't do it.
You're not going to get performance with overflow checking even with the best
compiler support. For example, much arithmetic code is generated for the x86
using addressing mode instructions, like:
LEA EAX,16[8*EBX][ECX] for 16+8*b+c
The LEA instruction does no overflow checking. If you wanted it, the best code
would be:
MOV EAX,16
IMUL EBX,8
JO overflow
ADD EAX,EBX
JO overflow
ADD EAX,ECX
JO overflow
Which is considerably less efficient. (The LEA is designed to run in one cycle).
Plus, often more registers are modified which impedes good register allocation.
This is why performance languages do not do overflow checking, and why C# only
does it under duress. It is not a conspiracy of pig-headed language developers :-)
I do use "clipped conversion" though: e.g. ClippedConvert<short>(40000)==32767.
I can afford the overhead in this case because I don't do type conversions as
often as addition, bit shifts, etc.
You can't have both performant code and overflow detection.
The C# solution is not good enough either. C# throws exceptions on overflow,
which is convenient but is bad for performance if it happens regularly; it can
also make a debugger almost unusable. Some sort of mechanism that works like an
exception, but faster, would probably be better. Consider:
result = a * b + c * d;
If a * b overflows, there is probably no point to executing c * d so it may as
well jump straight to a handler; on the other hand, the exception mechanism is
costly, especially if the debugger is hooked in and causes a context switch
every single time it happens. So... I dunno. What's the best semantic for an
overflow detector?
If you desire overflows to be programming errors, then you want an abort, not a
thrown exception. I am perplexed by your desire to continue execution when
overflows happen regularly.