On Thu, Jul 21, 2011 at 4:30 AM, David T. Lewis lewis@mail.msen.com wrote:
On Thu, Jul 21, 2011 at 07:08:18AM -0400, David T. Lewis wrote:
Commit message blocked due to size, forwarding trimmed version:
Author: eliot Date: 2011-07-18 17:35:51 -0700 (Mon, 18 Jul 2011) New Revision: 2463
<snip>
Log: CogVM source as per VMMaker.oscog-eem.105. Fix signed32BitValueOf for
most neg-
ative value C compiler mis-optimization. Speed up primitiveFail using !
trick.
Add multi-threaded sources to tree (won't build yet due to issue in
ia32abicc.c)
Upgrade nscogsrc/plugins to official versions.
Hi Eliot,
Can you say what the issue was with signed32BitValueOf? I can see the changes in InterpreterPrimitives>>signed32BitValueOf: but I'm not clear on whether this is something that affects Alien, or if it is something that has been causing problems more generally but went unnoticed. Also, I'd like to document this with a unit test, so if you can suggest a code snippet that would be great.
The unit test is in the lien tests and is the attempt to assign max neg int (-2^31) through signedLongAt:put:. The problem is due to a pervasive C compiler bug with optimization. Recall that max neg int is exceptional in that it is the only value in a 2's complement representation that can't be negated since max neg int = -max pos int - 1. Here's the bug, and it occurred in signed64BitValueOf: and signedMachineIntegerValueOf: as well; I slipped in not fixing signed32BitValueOf:
<var: #value type: #int> ... (negative and: [self cCode: [value - 1 > 0] inSmalltalk: [value = -16r80000000]]) ifTrue: "Don't fail for -2147483648 /-16r80000000"
Since value is int (32 bits on relevant systems) then if value = 16r80000000, value - 1 will wrap around to 16r7fffffff, bit all other negative values will remain negative. Hence value - 1 > 0 /should/ cheaply identify max neg int. But both gcc in many versions, and icc, the intel compiler, under optimization assume that value - 1 > 0 is always false, and hence cause the primitive to fail for max neg int.
Instead, the solution I've adopted is to use a different sequence using shifts that is not mis-optimized, at least by gcc and icc:
(negative and: [0 = (self cCode: [value << 1] inSmalltalk: [value << 1 bitAnd: (1 << 32) - 1])]) ifTrue:
i.e. 16r8000000 is the only negative value (0 is positive) that when shifted left within a 32-bit type equals zero since the sign bit is shifted out.
And to those C compilers, grrr.... ;)
TIA, Dave