[Vm-dev] [commit] r2463 - CogVM source as per VMMaker.oscog-eem.105. Fix signed32BitValueOf for most neg-

stephane ducasse stephane.ducasse at gmail.com
Thu Jul 21 19:08:55 UTC 2011


> 
> 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.... ;)

indeed!


More information about the Vm-dev mailing list