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
}