[Vm-dev] Fix for broken integer arithmetic on 64 bit image/32 bit host

David T. Lewis lewis at mail.msen.com
Sun Nov 12 23:26:07 UTC 2006


Unfortunately, I made an error in testing this on 64 bit image/64 bit hosts,
for which this patch did *not* work.

A corrected patch is on Mantis, which now uses this Smalltalk:

isIntegerValue: intValue
    ^ self isDefined: 'SQ_HOST32'
        inSmalltalk: [true]
        comment: 'cast to int for 64 bit image on 32 bit host'
        ifTrue: ((self cCoerce: intValue to: 'int')
                    bitXor: ((self cCoerce: intValue to: 'int') << 1)) >= 0
        ifFalse: (self explicitCheckIsIntegerValue: intValue)

explicitCheckIsIntegerValue: valueWord
    ^ valueWord >= 16r-40000000 and: [valueWord <= 16r3FFFFFFF]

which generates the C function:

sqInt isIntegerValue(sqInt intValue) {
    return
# ifdef SQ_HOST32  // cast to int for 64 bit image on 32 bit host
        (((((int) intValue)) ^ ((((int) intValue)) << 1)) >= 0)
# else
        (((intValue >= -1073741824) && (intValue <= 1073741823)) >= 0)
# endif  // SQ_HOST32
    ;
}

and inlined C code such as this:

    if (
# ifdef SQ_HOST32  // cast to int for 64 bit image on 32 bit host
        (((((int) integerResult)) ^ ((((int) integerResult)) << 1)) >= 0)
# else
        (((integerResult >= -1073741824) && (integerResult <= 1073741823)) >= 0)
# endif  // SQ_HOST32
    ) {

Dave

On Sat, Nov 11, 2006 at 03:07:58PM -0500, David T. Lewis wrote:
>  
> There is a bug (Mantis 5238) with integer arithmetic on 64 bit images running
> on 32 bit hosts.
> 
> I have been pecking away at this bug for a while now, and I have come up with
> a solution. In a nutshell, the solution I'm proposing is to add C preprocessor
> capability to Slang, then change ObjectMemory>>isIntegerValue: to this:
> 
> 	^ self isDefined: 'SQ_HOST32'
> 		inSmalltalk: [true]
> 		comment: 'cast to int for 64 bit image on 32 bit host'
> 		ifTrue: ((self cCoerce: intValue to: 'int')
> 					bitXor: ((self cCoerce: intValue to: 'int') << 1)) >= 0
> 		ifFalse: (intValue bitXor: (intValue << 1)) >= 0
> 
> Which generates the following C code:
> 
> sqInt isIntegerValue(sqInt intValue) {
> 	return
> # ifdef SQ_HOST32  // cast to int for 64 bit image on 32 bit host
> 		((((int) intValue)) ^ ((((int) intValue)) << 1)) >= 0
> # else
> 		(intValue ^ (intValue << 1)) >= 0
> # endif  // SQ_HOST32
> 	;
> }
> 
> The method is still inlined throughout the interpreter, with generated code
> such as this:
> 
> 	/* begin storeInteger:ofObject:withValue: */
> 	if (
> # ifdef SQ_HOST32  // cast to int for 64 bit image on 32 bit host
> 		((((int) (evtBuf[0]))) ^ ((((int) (evtBuf[0]))) << 1)) >= 0
> # else
> 		((evtBuf[0]) ^ ((evtBuf[0]) << 1)) >= 0
> # endif  // SQ_HOST32
> 	) {
> 		longAtput((arg + BaseHeaderSize) + (0 << ShiftForWord), (((evtBuf[0]) << 1) | 1));
> 	} else {
> 		/* begin primitiveFail */
> 		foo->successFlag = 0;
> 	}
> 
> 
> While this adds some complexity to the C code generator, it produces correct
> results on all combinations of 32/64 bit image and host, and requires no
> additional platform support files. It also preserves the speed advantage of
> Tim's current #isIntegerValue: (which unfortunately did not work for 64 bit
> images on 32 bit hosts).
> 
> Comments?
> 
> Dave


More information about the Vm-dev mailing list