27 ms·
> Case 2: (b == 0) || ((a == INT32_MIN) && (b == -1)) > A Java compiler, in contrast, has obligations in Case 2 and must deal with it (though in this particula
by Joker_vD 3y ago
> Case 2: (b == 0) || ((a == INT32_MIN) && (b == -1))
> A Java compiler, in contrast, has obligations in Case 2 and must deal with it (though in this particular case, it is likely that there won’t be runtime overhead since processors can usually provide trapping behavior for integer divide by zero).
Actually, there will be runtime overhead on x86/x64: Java mandates that Integer.MinValue / (-1) evaluates to Integer.MinValue (see 15.17.2. "Division Operator /" of the Java Language Specification) but IDIV instruction raises #DE in such circumstance. So the JITter actually emits
cmp eax, 0x80000000
jne .normalCase
xor edx, edx
cmp $reg, -1
je .specialCase
.normalCase:
cdq
idiv $reg
.specialCase:
code sequence as you can see in its source ([0][1]) instead of simplistic "cdq; idiv $reg": because it does not want trapping behaviour in this particular case; but e.g. AArch64 doesn't trap neither division by zero nor INT_MIN / -1. That's why accurately implementing your language's semantics on different platforms is so annoying and why C standard left itself a nice shortcut.
[0] https://github.com/openjdk/jdk/blob/d27daf01d6361513a815e78327961f9367887163/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp#L2632 https://github.com/openjdk/jdk/blob/d27daf01d6361513a815e783...
[1] https://github.com/openjdk/jdk/blob/d27daf01d6361513a815e78327961f9367887163/src/hotspot/cpu/x86/macroAssembler_x86.cpp#L1938 https://github.com/openjdk/jdk/blob/d27daf01d6361513a815e783...
- fluoridation 3y agoOn the other hand, C left the burden of implementing portable semantics to its users.
- Joker_vD 3y agoYes, but when C was being made, the application-level programmers knew the quirks of the platforms they used just as well as the compiler writers because they were almost precisely the same people.