MethodTable內(nèi)存空間分配中加法運算算法

字號:

在分析MethodTable具體分配內(nèi)存實現(xiàn)的時候,看到了計算MethodTable的大小,然后分配空間的算法。其中有個加法運算實現(xiàn)的非常贊,特地截取出來。
    所有的MethodTable的分配,都是通過methodtable中的一個static方法AllocagteNewMT來實現(xiàn)的,該方法定義如下:
    MethodTable * MethodTable::AllocagteNewMT(EEClass *pClass,
    DWORD dwVtableSlots,
    DWORD dwGCSize,
    DWORD dwNumInterfaces,
    DWORD numGenericArgs,
    DWORD dwNumDicts,
    DWORD cbDict,
    ClassLoader *pClassLoader,
    BaseDomain *pDomain,
    BOOL isInterface,
    BOOL fHasGenericsStaticsInfo,
    BOOL fNeedsRemotableMethodInfo,
    BOOL fNeedsRemotingVtsInfo,
    BOOL fHasThreadOrContextStatics
    , AllocMemTracker *pamTracker
    )
    下面是該方法中計算大小的一段,采用模板來忽略類型帶來的影響:
    DWORD cbTotalSize = 0;
    DWORD cbDicts = 0;
    if (!ClrSafeInt::multiply(dwNumDicts, sizeof(TypeHandle*), cbDicts) ||
    !ClrSafeInt::addition((DWORD)size, cbDicts, cbTotalSize) ||
    !ClrSafeInt::addition(cbTotalSize, dwGCSize, cbTotalSize))
    ThrowHR(COR_E_OVERFLOW);
    然后轉(zhuǎn)到addition((DWORD)size, cbDicts, cbTotalSize)的實現(xiàn),加法的實現(xiàn)如下,加入了對各種情況的嚴格考慮:
    // Returns true if safe, false on overflow
    static inline bool addition(T lhs, T rhs, T &result)
    {
    //check for T first.
    if(IsSigned())
    {
    //test for +/- combo
    if(!IsMixedSign(lhs, rhs))
    {
    //either two negatives, or 2 positives, not mixed symbols
    if(rhs < 0)
    {
    //two negatives
    if(lhs < (T)(MinInt() - rhs)) //remember rhs < 0
    {
    return false;
    }
    //ok
    }
    else
    {
    //two positives
    if((T)(MaxInt() - lhs) < rhs)
    {
    return false;
    }
    //OK
    }
    }
    //else overflow not possible
    result = lhs + rhs;
    return true;
    }
    else //unsigned, and two symbols is mixed
    {
    if((T)(MaxInt() - lhs) < rhs)
    {
    return false;
    }
    result = lhs + rhs;
    return true;
    }
    }
    其中,涉及到中間調(diào)用的幾個方法如下:
    static bool IsSigned()
    {
    return( (T)-1 < 0 );
    }
    //Check if lhs and rhs is mixed Sign symbols
    static bool IsMixedSign(T lhs, T rhs)
    {
    return ((lhs ^ rhs) < 0);
    }
    //both of the following should optimize away
    static T MinInt()
    {
    if(IsSigned())
    {
    return (T)((T)1 << (BitCount()-1));
    }
    else
    {
    return ((T)0);
    }
    }
    static T MaxInt()
    {
    if(IsSigned())
    {
    return (T)~((T)1 << (BitCount()-1));
    }
    //else
    return (T)(~(T)0);
    }