void GCSafePointsInfo::updatePairsOnInst()

in vm/jitrino/src/codegenerator/ia32/Ia32GCSafePoints.cpp [435:576]


void GCSafePointsInfo::updatePairsOnInst(Inst* inst, GCSafePointPairs& res) {
    runLivenessFilter(inst, res);//filter pairs with dead mptrs from list

    Inst::Opnds opnds(inst, Inst::OpndRole_Explicit | Inst::OpndRole_Auxilary |Inst::OpndRole_UseDef);
    U_32 defIndex = opnds.begin();
    U_32 useIndex1 = opnds.next(defIndex);

    if (defIndex >= opnds.end() || useIndex1 >= opnds.end() 
        || (inst->getOpndRoles(defIndex) & Inst::OpndRole_Def) == 0 
        || (inst->getOpndRoles(useIndex1) & Inst::OpndRole_Use) == 0 )
    {
        return;
    }
    Opnd* opnd = inst->getOpnd(defIndex);
    Type* opndType = opnd->getType();
    if (!opndType->isObject() && !opndType->isManagedPtr()) {
        return;
    }
   filterStaticMptrs(inst);
   if (isStaticFieldMptr(opnd)) {
        removePairByMPtrOpnd(res, opnd);
       return; // no more analysis required
   }
   if (mode == MODE_1_FIX_BASES) { //3 addr form
        if (opndType->isObject()) { // MODE_1_FIX_BASES -> obj & mptr types are not coalesced
            StlMap<Inst*, Opnd*>::const_iterator ait;
            if (!ambiguityFilters.empty() && ((ait = ambiguityFilters.find(inst))!=ambiguityFilters.end())) {
                //mptr ambiguity filter -> replace old base with new(opnd) in pairs
                const Opnd* mptr = ait->second;
                MPtrPair* pair =  findPairByMPtrOpnd(res, mptr);
#ifdef _DEBUG
                Opnd* oldBase = inst->getOpnd(useIndex1); //inst is: newBase = oldBase
                assert(pair!=NULL);
                assert(pair->getBase() == oldBase || pair->getBase() == opnd); // ==opnd-> already resolved in dominant block
#endif

                pair->base = opnd;
            }
        } else { //def of mptr
            // detect which operand is base
            Opnd* fromOpnd = inst->getOpnd(useIndex1);
            U_32 useIndex2 = opnds.next(useIndex1);
            Opnd* fromOpnd2 = useIndex2!=opnds.end() ? inst->getOpnd(useIndex2) : NULL;
            if (!(fromOpnd->getType()->isObject() || fromOpnd->getType()->isManagedPtr())) {
                assert(fromOpnd2!=NULL);
                Opnd* tmp = fromOpnd; fromOpnd = fromOpnd2; fromOpnd2 = tmp;
            }
            assert(fromOpnd->getType()->isObject() || fromOpnd->getType()->isManagedPtr());
            I_32 offset = MPTR_OFFSET_UNKNOWN;
            if (inst->getMnemonic() == Mnemonic_LEA) {
                assert(fromOpnd->isPlacedIn(OpndKind_Memory));
                Opnd* scaleOpnd = fromOpnd->getMemOpndSubOpnd(MemOpndSubOpndKind_Scale);
                if (scaleOpnd == NULL) {
                    Opnd* displOpnd = fromOpnd->getMemOpndSubOpnd(MemOpndSubOpndKind_Displacement);
                    assert(displOpnd!=NULL);
                    offset = (I_32)displOpnd->getImmValue();
                }
                fromOpnd = fromOpnd->getMemOpndSubOpnd(MemOpndSubOpndKind_Base);
            } else if (fromOpnd2!=NULL) {
                Opnd* offsetOpnd = fromOpnd2; 
                offset = getOffsetFromImmediate(offsetOpnd);
            }
            updateMptrInfoInPairs(res, opnd, fromOpnd, offset, fromOpnd->getType()->isObject());
            dbg_point();
        }
    } else { // mode == MODE_2_CALC_OFFSETS   - 2 addr form
        //we can't rely on base/mptr type info here.
        //algorithm:
        if (inst->hasKind(Inst::Kind_ControlTransferInst) ||
            inst->getMnemonic() == Mnemonic_MOVS8         ||
            inst->getMnemonic() == Mnemonic_MOVS16        ||
            inst->getMnemonic() == Mnemonic_MOVS32        ||
            inst->getMnemonic() == Mnemonic_MOVS64        ||
            inst->getMnemonic() == Mnemonic_CMPSB         ||
            inst->getMnemonic() == Mnemonic_CMPSW         ||
            inst->getMnemonic() == Mnemonic_CMPSD         ) {
            //Do nothing, calls return only bases
        } else {
            Opnd* fromOpnd = NULL;
            I_32 offset = 0;
            Mnemonic mn = inst->getMnemonic();

            Mnemonic conditionalMnem = getBaseConditionMnemonic(mn);
            if (conditionalMnem != Mnemonic_NULL)
                mn = conditionalMnem;

            switch (mn) {
                case Mnemonic_XOR:
                case Mnemonic_MOV: 
                case Mnemonic_CMOVcc:
                    assert(mn != Mnemonic_XOR || inst->getOpnd(useIndex1)==opnd);
                    fromOpnd = inst->getOpnd(useIndex1);
                    break;                
                case Mnemonic_ADD: { 
                case Mnemonic_SUB:
                        fromOpnd = opnd;
                        Opnd* offsetOpnd = inst->getOpnd(useIndex1);
                        Opnd* immOffset = OpndUtils::findImmediateSource(offsetOpnd);
                        if (immOffset) {
                           if (isHeapBase(immOffset)) {
                               offset = 0;
                           } else {
                               offset = getOffsetFromImmediate(immOffset);
                           }
                        } else {
                           offset = MPTR_OFFSET_UNKNOWN;
                        }
                    }
                    break;
                case Mnemonic_LEA: {
                        fromOpnd = inst->getOpnd(useIndex1);
                        assert(fromOpnd->isPlacedIn(OpndKind_Memory));
                        Opnd* scaleOpnd = fromOpnd->getMemOpndSubOpnd(MemOpndSubOpndKind_Scale);
                        if (scaleOpnd == NULL) {
                            Opnd* displOpnd = fromOpnd->getMemOpndSubOpnd(MemOpndSubOpndKind_Displacement);
                            assert(displOpnd!=NULL);
                            offset = (I_32)displOpnd->getImmValue();
                        } else {
                            offset = MPTR_OFFSET_UNKNOWN;
                        }
                        fromOpnd = fromOpnd->getMemOpndSubOpnd(MemOpndSubOpndKind_Base);
                    }
                    break;
                default: assert(0);
            }
            bool fromIsMptrOrObj = fromOpnd->getType()->isObject() || fromOpnd->getType()->isManagedPtr();
            MPtrPair* fromPair = fromIsMptrOrObj ? findPairByMPtrOpnd(res, fromOpnd) : NULL;

            if (fromPair != NULL || offset!=0)  {//opnd is mptr -> update pairs
                updateMptrInfoInPairs(res, opnd, fromOpnd, offset,  fromPair == NULL);
            } else {
                //new def of base -> we must remove all pairs where opnd acts as base or mptr 
                //the problem is that in MODE2 we do not save info about bases (no ambiguity resolution is done) 
                //so we can't match pairs where opnd is a base. 
                //Solution: let pairs derived from this base to live, due to the fact that 
                //such pairs must have static offset and base redefinition will not corrupt info. 
                //For pairs with unknown offset there is a live base -> MODE1 cares about it
                removePairByMPtrOpnd(res, opnd);
            }
        }
    } // else mode2
}