[Python-Dev] Memory size overflows

Gerald S. Williams gsw@agere.com
Thu, 17 Oct 2002 18:03:39 -0400


I wrote:
> But I said I was done tweaking for now. :-)

Well, I was done tweaking, but then I decided to try out one more
performance tweak. This is in desperate need of commenting, but
it's finally faster than checking via division on my machine:

#define FULL_BITS (sizeof(size_t) * 8U)
#define TOP_BIT (((size_t)1) << ((FULL_BITS)-1))
#define HALF_BITS (sizeof(size_t) * 4U)
#define MID_BIT (((size_t)1) << ((HALF_BITS)-1))
#define LO_MASK ((((size_t)1) << (HALF_BITS))-1)
#define HI_MASK (~(LO_MASK))

#define Q_BITS (sizeof(size_t) * 2U)
#define TQ_BITS (sizeof(size_t) * 6U)
#define TQ_BIT (((size_t)1) << ((TQ_BITS)-1))
#define LTQ_MASK ((((size_t)1) << (TQ_BITS))-1)
#define TQ_MASK (~(LTQ_MASK))

#define SAFE_MULTIPLY(dest,src1,src2,on_overflow)\
    {\
        size_t _x = src1;\
        size_t _y = src2;\
        size_t _dest = _x * _y;\
        \
        dest = _dest;\
        \
        if ((_x | _y) & HI_MASK)\
        {\
            if (_safe_multiply_check_for_overflow(_x,_y,_dest))\
            {\
                on_overflow;\
            }\
        }\
    }

int
_safe_multiply_check_for_overflow(
    size_t h,
    size_t l,
    size_t dest)
{
    if (l > h)
    {
        size_t temp = l;
        l = h;
        h = temp;
    }

    if ((h & HI_MASK) && (l))
    {
        size_t lgt;
        size_t leq;

        if (l & HI_MASK)
        {
            lgt = (size_t)(-1);
            leq = 0;
        }
        else
        {
            size_t hbit;
            size_t mask;

            if (h & TQ_MASK)
            {
                for ((mask=TOP_BIT),(hbit=0);!(mask&h);mask>>=1)
                {
                    ++hbit;
                }
            }
            else
            {
                for ((mask=TQ_BIT),(hbit=Q_BITS);!(mask&h);mask>>=1)
                {
                    ++hbit;
                }
            }
            leq = 1 << hbit;
            mask = leq - 1;
            lgt = ~mask ^ leq;
        }
        if ((l & lgt) || ((l & leq) && !(dest & TOP_BIT)))
        {
            return 1;
        }
    }

    return 0;
}

-Jerry