예제 #1
0
void PrintDotFile::printDotHeader(MethodDesc& mh) {
    *os << "digraph dotgraph {" << ::std::endl
        << "node [shape=record,fontname=\"Courier\",fontsize=9];" << ::std::endl
        << "label=\""
        << mh.getParentType()->getName()
        << "::"
        << mh.getName()
        << "\";" << ::std::endl;
}
/**
 * Checks a callee method side effect.
 * @param inst - method call instruction
 * @return <code>true</code> if method has side effect;
 *         <code>false<code> if method has no side effect.
 */
bool
LazyExceptionOpt::methodCallHasSideEffect(Inst* inst) {
    U_32 opcode = inst->getOpcode();
    MethodDesc* cmd = NULL;
    Method_Side_Effects mse = MSE_Unknown;

    if (opcode==Op_DirectCall || opcode==Op_TauVirtualCall) {
        cmd = inst->asMethodCallInst()->getMethodDesc();
    } else {
        if (opcode==Op_IndirectCall || opcode==Op_IndirectMemoryCall) {
            Type* type = inst->asCallInst()->getFunPtr()->getType();
            if (type->isUnresolvedType()) {
                return true;
            }
            cmd = type->asMethodPtrType()->getMethodDesc();
        } else {
#ifdef _DEBUG
            if (Log::isEnabled()) {
                Log::out() << "    checkMC: no check ";
                inst->print(Log::out());
                Log::out()  << std::endl;
            }
#endif
            return true;
        }
    }
#ifdef _DEBUG
    if (Log::isEnabled()) {
        Log::out() << "    checkMC: ";
        cmd->printFullName(Log::out());
        Log::out() << std::endl;
    }
#endif

    mse = cmd->getSideEffect();
#ifdef _DEBUG
    if (mse != MSE_Unknown) {
        if (Log::isEnabled()) {
            Log::out() << "    checkMC: prev.set sideEff " << mse << "  ";
            inst->print(Log::out());
            Log::out() << std::endl;
        }
    }
#endif
    if (mse == MSE_True) {
        return true;
    }
    if (mse == MSE_False) {
        return false;
    }
//  core api exception init
    if (cmd->isInstanceInitializer() && cmd->getParentType()->isLikelyExceptionType()
            && strncmp(cmd->getParentType()->getName(),"java/lang/",10) == 0) {
        cmd->setSideEffect(MSE_False);
#ifdef _DEBUG
        if (Log::isEnabled()) {
            Log::out() << "    checkMC: core api exc ";
            inst->print(Log::out());
            Log::out() << std::endl;
        }
#endif
        return false;
    }

    if ( opcode!=Op_DirectCall && !cmd->isFinal() ) {
#ifdef _DEBUG
        if (Log::isEnabled()) {
            Log::out() << "    checkMC: not DirCall not final ";
            inst->print(Log::out());
            Log::out() << std::endl;
        }
#endif
        return true;
    }

    if (!isExceptionInit &&
            !(cmd->isInstanceInitializer()&&cmd->getParentType()->isLikelyExceptionType())) {
#ifdef _DEBUG
        if (Log::isEnabled()) {
            Log::out() << "    checkMC: no init ";
            Log::out() << isExceptionInit << " ";
            Log::out() << cmd->isInstanceInitializer() << " ";
            Log::out() << cmd->getParentType()->isLikelyExceptionType() << " ";
            inst->print(Log::out());
            Log::out() << std::endl;
        }
#endif
        return true;
    }

    /*
        if (cmd->getParentType()->needsInitialization()) {
    #ifdef _DEBUG
            if (Log::isEnabled()) {
                Log::out() << "    checkMC: need cinit ";
                inst->print(Log::out()); Log::out() << std::endl;
            }
    #endif
            return true;  // cannot compile <init> before <clinit> (to fix vm)
        }
    */

    if (mse == MSE_Unknown) {  // try to compile method
        //TODO: avoid compilation here. Use translator to perform analysis needed
        bool allowRecursion = !compInterface.getTypeManager().isLazyResolutionMode();
        if (!allowRecursion) {
            return MSE_True;
        }
        if (!compInterface.compileMethod(cmd)) {
#ifdef _DEBUG
            if (Log::isEnabled()) {
                Log::out() << "    checkMC: method was not compiled " << std::endl;
            }
#endif
            return true;
        } else {
            mse = cmd->getSideEffect();
#ifdef _DEBUG
            if (Log::isEnabled()) {
                Log::out() << "    checkMC: method was compiled, sideEff "
                           << mse << std::endl;
            }
#endif
            if (mse == MSE_True)
                return true;
            if (mse == MSE_False) {
                return false;
            }
        }
    }

    if (mse == MSE_True_Null_Param) {
        U_32 nsrc=inst->getNumSrcOperands();
        bool mayBeNull;
        if (nsrc>3) {
#ifdef _DEBUG
            if (Log::isEnabled()) {
                Log::out() << "    checkMC: exc.init ";
                inst->print(Log::out());
                Log::out() << std::endl;
            }
#endif
            mayBeNull=false;
            for (U_32 i=3; i<nsrc; i++) {
                if (inst->getSrc(i)->getType()->isReference()) {
                    if (mayBeNullArg(inst,i))
                        mayBeNull=true;
                }
            }
            if (!mayBeNull)
                return false;
#ifdef _DEBUG
            for (U_32 i=0; i<nsrc; i++) {
                if (Log::isEnabled()) {
                    Log::out() << "        "<<i<<" isRef: "<<
                               inst->getSrc(i)->getType()->isReference()<<" ";
                    inst->getSrc(i)->getInst()->print(Log::out());
                    Log::out() << std::endl;
                }
            }
#endif
            return true;
        }
#ifdef _DEBUG
        else {
            if (Log::isEnabled()) {
                Log::out() << " ?????? MSE_NULL_PARAM & nsrc "<<
                           nsrc << std::endl;
            }
        }
#endif
    }
    return true;
}
/**
 * Executes lazy exception optimization pass.
 */
void
LazyExceptionOpt::doLazyExceptionOpt() {
    MethodDesc &md = irManager.getMethodDesc();
    BitSet excOpnds(leMemManager,irManager.getOpndManager().getNumSsaOpnds());
    StlDeque<Inst*> candidateSet(leMemManager);
    optCandidates = new (leMemManager) OptCandidates(leMemManager);
    Method_Side_Effects m_sideEff = md.getSideEffect();

    const Nodes& nodes = irManager.getFlowGraph().getNodes();
    Nodes::const_iterator niter;

#ifdef _DEBUG
    mtdDesc=&md;
#endif

#ifdef _DEBUG
    if (Log::isEnabled()) {
        Log::out() << std::endl;
        for (int i=0; i<level; i++) Log::out() << " ";
        Log::out() << "doLE ";
        md.printFullName(Log::out());
        Log::out() << " SideEff " << (int)m_sideEff << std::endl;
    }
#endif

    level++;
    U_32 opndId = 0;
    isArgCheckNull = false;
    isExceptionInit = md.isInstanceInitializer() &&
                      md.getParentType()->isLikelyExceptionType();
//  core api exception init
    if (m_sideEff == MSE_Unknown && isExceptionInit
            && strncmp(md.getParentType()->getName(),"java/lang/",10) == 0) {
        m_sideEff = MSE_False;
        md.setSideEffect(m_sideEff);
#ifdef _DEBUG
        if (Log::isEnabled()) {
            Log::out() << "      core api exc ";
            md.printFullName(Log::out());
            Log::out() << " SideEff " << (int)m_sideEff << std::endl;
        }
#endif
    }

    for(niter = nodes.begin(); niter != nodes.end(); ++niter) {
        Node* node = *niter;
        Inst *headInst = (Inst*)node->getFirstInst();
        for (Inst* inst=headInst->getNextInst(); inst!=NULL; inst=inst->getNextInst()) {
#ifdef _DEBUG
            if (inst->getOpcode()==Op_DefArg && isExceptionInit) {
                if (Log::isEnabled()) {
                    Log::out() << "    defarg: ";
                    inst->print(Log::out());
                    Log::out()  << std::endl;
                    Log::out() << "            ";
                    Log::out() << (int)(inst->getDefArgModifier()) << " " <<
                               (inst->getDefArgModifier()==DefArgNoModifier) << " " <<
                               (inst->getDefArgModifier()==NonNullThisArg) << " " <<
                               (inst->getDefArgModifier()==SpecializedToExactType) << " " <<
                               (inst->getDefArgModifier()==DefArgBothModifiers) << std::endl;
                }
            }
#endif
            if (inst->getOpcode()==Op_Throw) {
                if (inst->getSrc(0)->getInst()->getOpcode()==Op_NewObj) {
                    excOpnds.setBit(opndId=inst->getSrc(0)->getId(),true);
                    if (!addOptCandidates(opndId,inst))
                        excOpnds.setBit(opndId,false); // different exc. edges
#ifdef _DEBUG
                    if (excOpnds.getBit(opndId)==1) {
                        if (Log::isEnabled()) {
                            Log::out() << "      add opnd: ";
                            inst->print(Log::out());
                            Log::out() << std::endl;
                            Log::out() << "      add  obj: ";
                            inst->getSrc(0)->getInst()->print(Log::out());
                            Log::out() << std::endl;
                        }
                    }
#endif
                }
            }
            if (m_sideEff == MSE_Unknown)
                if (instHasSideEffect(inst)) {
                    m_sideEff = MSE_True;
#ifdef _DEBUG
                    if (Log::isEnabled()) {
                        Log::out() << "~~~~~~inst sideEff ";
                        inst->print(Log::out());
                        Log::out() << std::endl;
                    }
#endif
                }
        }
    }
    if (md.getSideEffect() == MSE_Unknown) {
        if (m_sideEff == MSE_Unknown) {
            if (isExceptionInit && isArgCheckNull) {
#ifdef _DEBUG
                if (Log::isEnabled()) {
                    Log::out() << "~~~~~~init sideEff reset: " << m_sideEff << " 3 ";
                    md.printFullName(Log::out());
                    Log::out() << std::endl;
                }
#endif
                m_sideEff = MSE_True_Null_Param;
            } else
                m_sideEff = MSE_False;
        }
        md.setSideEffect(m_sideEff);
    }

    for(niter = nodes.begin(); niter != nodes.end(); ++niter) {
        Node* node = *niter;
        Inst *headInst = (Inst*)node->getFirstInst();
        Opnd* opnd;
        for (Inst* inst=headInst->getNextInst(); inst!=NULL; inst=inst->getNextInst()) {
            U_32 nsrc = inst->getNumSrcOperands();
            for (U_32 i=0; i<nsrc; i++) {
                if (!(opnd=inst->getSrc(i))->isSsaOpnd())  // check ssa operands
                    continue;
                if (excOpnds.getBit(opndId=opnd->getId())==0)
                    continue;
                if (inst->getOpcode()==Op_DirectCall) {
                    MethodDesc* md = inst->asMethodInst()->getMethodDesc();
                    if (md->isInstanceInitializer() &&
                            md->getParentType()->isLikelyExceptionType()) {
                        if (!addOptCandidates(opndId,inst)) {
                            excOpnds.setBit(opndId,false);
#ifdef _DEBUG
                            if (Log::isEnabled()) {
                                Log::out() << "    - rem opnd " << opnd->getId() << " ";
                                inst->print(Log::out());
                                Log::out() << std::endl;
                            }
#endif
                        }
                    } else {
                        excOpnds.setBit(opndId,false);
#ifdef _DEBUG
                        if (Log::isEnabled()) {
                            Log::out() << "   -- rem opnd " << opnd->getId() << " ";
                            inst->print(Log::out());
                            Log::out() << std::endl;
                        }
#endif
                    }
                } else {
                    if (inst->getOpcode()!=Op_Throw) {
                        excOpnds.setBit(opndId,false);
#ifdef _DEBUG
                        if (Log::isEnabled()) {
                            Log::out() << "      rem opnd " << opnd->getId() << " ";
                            inst->print(Log::out());
                            Log::out() << std::endl;
                        }
#endif
                    }
                }
            }
        }
    }
    if (!excOpnds.isEmpty()) {
#ifdef _DEBUG
        if (Log::isEnabled()) {
            Log::out() << "------LE: ";
            md.printFullName(Log::out());
            Log::out() << std::endl;
        }
#endif
        fixOptCandidates(&excOpnds);
    }

    level--;
#ifdef _DEBUG
    if (Log::isEnabled()) {
        for (int i=0; i<level; i++) Log::out() << " ";
        Log::out() << "done ";
        md.printFullName(Log::out());
        Log::out() << " SideEff " << (int)m_sideEff << std::endl;
    }
#endif
};