Fix for broken integer arithmetic on 64 bit image/32 bit host

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Fix for broken integer arithmetic on 64 bit image/32 bit host

David T. Lewis
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


Reply | Threaded
Open this post in threaded view
|

Re: Fix for broken integer arithmetic on 64 bit image/32 bit host

David T. Lewis
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