Why slowed down? The cost of simple comparison on data already in L1 is effectively zero. The cost of manual checking in safemath should be more expensive by orders of magnitude. Go’s compiler optimization would have to be horrible for a comparison to be noticeable in any way.
Go implements big math in assembly.
I don’t know Go much, but according to this calling arbitrary native code in Go is easy and can offer big performance improvements:
name time/op
GetBucket-8 17.4ns ± 2%
GetBucketNoInline-8 17.4ns ± 2%
GetBucketASM-8 12.8ns ± 1%
in any case, I don’t think it would be possible to observe the difference between a comparison in go (assuming reasonable optimizing compiler) vs checking carry/overflow in assembly/C/C++, but in the case that it is, external code in C/C++, optionally with intrinsics or inline asm could be used.
Ah, I wasn’t clear enough - I meant a flag AND an option to trap on it. For example, for a FLAGS register defined in the following way:
struct FLAGS {
unsigned short int flags;
unsigned short int trapMask;
unsigned int trapHandler; //defaults to revert?
}
with flags’ bits defined as:
carryFlag | overFlowFlag | signFlag | zeroFlag | reserved | …
trapMask as a bitmask for traps:
carryFlagTrap | overflowFlagTrap | signFlag | zeroFlag | reserved | …
ie. when carryFlagTrap bit is set trap on setting carryFlag.
After flags are set in EVM it’s enough to:
if(FLAGS.flags&FLAGS.trapMask) {
pushOnEvmStack(evmEip);
evmEip = FLAGS.trapHandler;
}
//end current instruction
So this way, there are both flags, optional traps and everything is easily extensible.
I guess in this construction arguments 0-31 for pushf/popf could refer to flags’ and mask’s bits, 255 for the whole register, 254 for flags, 253 for trapMask and 252 for trapHandler. Perhaps 251 for trapMask with trapHandler at once, as these two fields are likely to be set together.
To be clear, either approach would require compiler changes. Solidity would have to allow you to specify when overflow is and isn’t wanted, and either check the flag or set and clear the trap handler.
Well yes, but enabling trapping on overflow could be implemented as a one dumb pushf added at the beginning, pure flags require changes in code generation for arithmetic expressions. A simple pushf could in principle be added manually after compiling, or as inline asm, with a compiler that doesn’t know traps exist.