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




--
best,
Eliot