"Those who do not understand the hardware are doomed to blog about it, poorly.
Intel chips already detect overflow, that is what the OF (bit 11) flag in the flags/eflags register indicates. That the most recent operation overflowed.
Testing, and generating a trap, for an overflow is a single instruction (JO – jump if overflow and JNO – jump if no overflow).
This is true of almost all CPU’s. At the hardware/assembly programming level, overflow detection is handled by hardware, and detected by a single instruction.
The reason all of your languages listed don’t have any sort of trap/etc. is simple. The language designers did not bother to check the result of their operations. Why, most likely because almost all of them are ultimately implemented in C, and C does not reflect the overflow status back into the C language level.
So the problem isn’t the hardware. It is the software architectural design(s) implemented above the hardware. They are not bothering to communicate to you the results of what the hardware already has available and tells them about."
> Why, most likely because almost all of them are ultimately implemented in C
That isn't right: languages created before and after C exhibit the same behaviour. Some languages do explicitly check the overflow flag every time.
The reason for not always checking (or never checking) is that in a tight loop the extra instruction can significantly affect performance especially back when CPUs had a fraction of their current speediness capability. The reason for not exposing the value to the higher level constructs is similar: you have to check it every time it might change and update an appropriate structure, which is expensive given an overflow should be a rare occurrence so checking every time and saving the result is wasteful.
The linked article specifically mentions the performance effect of checking overflow flags in software. I believe what it is calling for is some form of interrupt that fires when the flag is switched on in a context where a handler for it is enabled - a fairly expensive event happens upon overflow but when all is well there is no difference in performance (no extra instructions run). Of course there would be complications here: how does the CPU keep track of what to call (if anything) in the current situation? Task/thread handling code in the OS would presumably need to be involved in helping maintain this information during context switches.
The performance penalty you mention ("in a tight loop the extra instruction can significantly affect performance") doesn't happen if you add the new type in the language (that is, what in VC++ is a "SafeInt"). In the really tight loop you wouldn't use that type. That type is important exactly for the things I've given a MSFT's example (calculating how much to allocate -- overflow means you allocated much less and you don't catch that!) So no, you don't have to "check every time."
The reason it's not in standard C is to be portable with some odd old architecture which doesn't have the overflow flag at all. Some modern language can be clearly designed to depend on the overflow flag. The cost would happen only when the programmer really does access it (in a modern language: by using such a type) and the cost would be minimal, as there is a direct hardware support.
> I believe what it is calling for is some form of interrupt that fires when the flag is switched on in a context where a handler for it is enabled
And that is misguided, as it doesn't allow for fine grained control -- it's all or nothing, either all instructions generate "an interrupt" or none. If you want to change the behavior from the variable to variable, changing processor mode would cost. If you add a new instructions for all things that can overflow and trap, you'd add a lot of new instructions. So it's also bad. The simplest approach is: use what's already there. The flag is there in the CPU, it's not used by the languages OP mentions, but once the language supports it for the "safe" integer type, it will be checked only when it's really needed: for that type and nowhere else.
Finally, the maintenance of the exception handling code (what you name under "how does the CPU keep track of what to call") is something that modern compilers and even assembly writers must take care of and is very good understood among them: for example, Winx64 ABI expects every non-leaf function to maintain the stack unwinding information properly and even if I write assembly code I effectively have to support exceptions outside of my code for every non-trivial function I write. So this part is very good known, and the most is taken care of outside of the OS. The OS merely has some expectations, the compiler (in broader sense, that is, including native code generator and linker) writers must fulfill them.
Setting a flag is not the same as raising an exception. When you get a segfault that's not because a flag was checked, that's because a chunk of hardware interrupted the next operation.
So yes, you can check for overflow by inspecting a flag, but that's not all that much better from coding around the potential overflow to see if your operands + operation combo will cause an overflow.
Imagine setting a flag on a divide by 0 instead of raising an exception.
So the author is most likely aware of the overflow flag (just like any other old timer that has programmed in assembly and that had a cursory look at the flags register, or in some cases more than a cursory look :) ), he's writing about hardware exceptions, not about how to write in javascript.
But inspecting a flag simply isn't on the same level as raising a hardware exception, right along with segfault, division by 0, FPEs and so on.
That instantly propagates through to any programming language executed on the machine. Checking a flag in a register is a decision by a compiler writer and many compiler writers (consciously!) ignore that (usually because the language specs are vague enough that wrapping is considered acceptable when it is in fact almost always simply wrong).
No, I don't agree that "the author is most likely aware of the overflow flag" since the author says:
"Processors should support integer math instructions that optionally trap on overflow. Because popular architectures lack this feature, otherwise excellent modern systems programming languages, such as Rust, Go, and D, have default integer types that wrap."
In short, he believes there's no hardware support and therefore Rust, GO and D don't have it.
There is however hardware support in every imaginable CPU -- overflow is important to be able to synthesize adds bigger than the native size (e.g. 128 bit add if your regs are 64-bits) . Except for the implementor of the HLL compiler you as the user wouldn't be able to see how it's implemented in the hardware unless you look at the resulting generated code (you'd see an "exception" triggered no matter how it's implemented).
I know: I had the opportunity to implement the language which has special behavior when the floating point compare involves NaN. Luckily, there is a flag in the Intel CPU for that too and as far as I know you can't access it from any popular high level language, but my code generator injects additional flag check in every FP compare and in the production code I haven't seen any negative performance impacts compared to the case where I don't do the stated injection. That's how good the current branch prediction in CPUs can be.
So no, you don't need "hardware traps" you need somebody to first try to implement the given behavior in any HLL language before before we argue further. As soon as you have "wrappable" and "unwrappable" types in the language, you can have all the crypto primitives that need wrapping use the "wrappables" without any performance impact.
In fact "unwrappables" were interesting mostly for the calculations of the limits, practically wherever you'd use, for example, Microsoft's SafeInt classes.
The example from their header:
void* AllocateMemForStructs(int StructSize, int HowMany) {
SafeInt<unsigned long> s(StructSize);
s *= HowMany;
return malloc(s);
}
At least using MSFT's Visual C++ you can already have exceptions on integer overflows.
> "Processors should support integer math instructions that optionally trap on overflow. Because popular architectures lack this feature, otherwise excellent modern systems programming languages, such as Rust, Go, and D, have default integer types that wrap."
The operative word there is trap.
There is no hardware support for traps on overflow, period.
You can detect overflow in software and then you can generate an exception (or deal with it in some other fashion) like you describe, this is not the same as a trap.
Feel free to stick to your definition if you want to but the accepted one is that a trap operates much like an interrupt would.
Of course I know the semantics of the "trap," the topic here is that the very "trap" is not necessary to have a reasonable high level language support for overflow checking, as there is the hardware flag already present and simply not used (according to the OP, in the sense of "not having the types that can produce an exception on overflow") in the languages mentioned by OP ("Rust, Go, and D").
I also gave an example of the language (Visual C++) which already implements exceptions (the application programmers sees only exceptions, not traps) on integer overflows, provided the programmer specifies that he wants such a type (declares them as SafeInt).
I think you're missing the point entirely, which is that if we had such a trap then integer overflow situations would be dealt with automatically rather than that they would rely on support by the individual languages.
Now whether or not the balance of burden (hardware/software) would favour a hardware solution or not is a different matter entirely. But I completely get what the author is trying to achieve and I'm well aware of the various bits in the flag registers of a whole pile of processors. I see having such a trap as a distinct advantage, just like I see division by 0 and floating point exceptions as advantageous.
The fact that you could do this in software right now has no bearing on his argument, that's a choice by the implementors of the various languages, which are usually built for speed rather than safety and where unchecked integer overlows are the norm. Retro-fitting a trap mechanism in hardware would likely turn up a whole pile of bugs in systems that we currently consider to be solid.
Well I have the news for you (re "I see division by 0 and floating point exceptions as advantageous"): when you use floating point in any current language now the division with 0 would not trigger any "exception" and it's certainly not supported by any language directly. CPU traps for the FPU are disabled by default by the language std libs.
Even worse, Java's model doesn't allow anybody to reach to the hardware.
The author of IEEE 754, prof. Kahan lamented exactly that: that the languages of today effectively can't use a lot of the features he designed (in 2004, http://www.cs.berkeley.edu/~wkahan/JAVAhurt.pdf Page 20: "Java lacks these flags and cannot conform to IEEE 754 without them.").
That was the FP domain, but is instructive. The traps are relatively "all or nothing" thing. To have a language where some integer variables behave one way and some another way (you know, the types are important now), you already have the hardware flags and they simply aren't used in the languages OP mentions.
Just changing the compiler behavior would be absolutely enough to "turn up a whole pile of bugs in systems that we currently consider to be solid" that you suggest. You certainly don't need to wait for some new CPUs.
So we return to what Anon said: "Those who do not understand the hardware are doomed to blog about it, poorly." If somebody wants to have the language types that trigger exceptions on overflows, he doesn't have to wait for the new processors. It's possible now, if there's interest in it. And even as the real "traps" as the very specific CPU feature for FP already exist, no language I know of uses them for types.
Intel chips already detect overflow, that is what the OF (bit 11) flag in the flags/eflags register indicates. That the most recent operation overflowed.
Testing, and generating a trap, for an overflow is a single instruction (JO – jump if overflow and JNO – jump if no overflow).
This is true of almost all CPU’s. At the hardware/assembly programming level, overflow detection is handled by hardware, and detected by a single instruction. The reason all of your languages listed don’t have any sort of trap/etc. is simple. The language designers did not bother to check the result of their operations. Why, most likely because almost all of them are ultimately implemented in C, and C does not reflect the overflow status back into the C language level.
So the problem isn’t the hardware. It is the software architectural design(s) implemented above the hardware. They are not bothering to communicate to you the results of what the hardware already has available and tells them about."
(Qouting comment from Anon)