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 |
Free forum by Nabble | Edit this page |