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
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
vm-dev@lists.squeakfoundation.org