Index: vm/jitrino/config/em64t/opt.emconf =================================================================== --- vm/jitrino/config/em64t/opt.emconf (revision 532241) +++ vm/jitrino/config/em64t/opt.emconf (working copy) @@ -24,7 +24,7 @@ -XX:jit.CS_OPT.path=opt_init,translator,optimizer,hir2lir,codegen --XX:jit.CS_OPT.path.optimizer=ssa,devirt,inline,uce,purge,simplify,dce,uce,memopt,simplify,dce,uce,lower,dessa,statprof,markglobals +-XX:jit.CS_OPT.path.optimizer=ssa,devirt,inline,uce,purge,simplify,dce,uce,escape,dce,uce,memopt,simplify,dce,uce,lower,dessa,statprof,markglobals -XX:jit.CS_OPT.path.codegen=lock_method,bbp,gcpoints,cafl,dce1,i8l-,early_prop-,itrace-,native,constraints,dce2,regalloc,spillgen,layout,copy,rce-,stack,break-,iprof-,emitter!,si_insts,gcmap,info,unlock_method -XX:jit.CS_OPT.path.dce1=cg_dce -XX:jit.CS_OPT.path.dce2=cg_dce Index: vm/jitrino/config/ia32/opt.emconf =================================================================== --- vm/jitrino/config/ia32/opt.emconf (revision 532241) +++ vm/jitrino/config/ia32/opt.emconf (working copy) @@ -24,7 +24,7 @@ -XX:jit.CS_OPT.path=opt_init,translator,optimizer,hir2lir,codegen --XX:jit.CS_OPT.path.optimizer=ssa,devirt,inline,uce,purge,simplify,dce,uce,lazyexc,memopt,simplify,dce,uce,lower,dessa,statprof,markglobals +-XX:jit.CS_OPT.path.optimizer=ssa,devirt,inline,uce,purge,simplify,dce,uce,lazyexc,escape,dce,uce,memopt,simplify,dce,uce,lower,dessa,statprof,markglobals -XX:jit.CS_OPT.path.codegen=lock_method,bbp,btr,gcpoints,cafl,dce1,i8l,api_magic,early_prop,peephole,itrace-,native,constraints,dce2,regalloc,spillgen,copy,i586,layout,rce+,stack,break-,iprof-,peephole,emitter!,si_insts,gcmap,info,unlock_method -XX:jit.CS_OPT.path.dce1=cg_dce -XX:jit.CS_OPT.path.dce2=cg_dce Index: vm/jitrino/src/optimizer/escanalyzer.cpp =================================================================== --- vm/jitrino/src/optimizer/escanalyzer.cpp (revision 532241) +++ vm/jitrino/src/optimizer/escanalyzer.cpp (working copy) @@ -40,7 +40,11 @@ const char* help = " escape flags:\n" " escape.max_level[=0] - max level callee method analysis\n" - " escape.do_sync_removal[={on,OFF}] - do synchonization removal optimization\n" + " escape.do_sync_removal[={on,OFF}] - do synchronization removal optimization\n" + " escape.do_sync_removal_vc[={ON,off}] - do synchronization removal optimization\n" + " for virtual call escaped operands\n" + " escape.do_sync_removal_sm[={ON,off}] - do synchronization removal optimization\n" + " for synchronized methods\n" " escape.do_scalar_repl[={ON,off}] - do scalar replacement optimization for\n" " local and escaped objects\n" " escape.do_esc_scalar_repl[={ON,off}] - scalar replacement for escaped objects\n" @@ -62,8 +66,8 @@ uint32 _n_lo; }; static ComObjStat comObjStat; -EscAnalyzer::CalledMethodInfos* EscAnalyzer::calledMethodInfos=NULL; -Mutex EscAnalyzer::calledMethodInfosLock; +EscAnalyzer::CalleeMethodInfos* EscAnalyzer::calleeMethodInfos=NULL; +Mutex EscAnalyzer::calleeMethodInfosLock; void @@ -76,33 +80,22 @@ Log::out() << "E s c a p e A n a l y s i s " << std::endl; } - //if (Log::isEnabled()) { - // const char* i1=Log::getDotFileDirName(); - // if (strlen(i1)!=0) { - // ControlFlowGraph& flowGraph = irm.getFlowGraph(); - // FlowGraph::printDotFile(flowGraph, irm.getMethodDesc(), "ea1"); - // } - //} ea.doAnalysis(); - //if (Log::isEnabled()) { - // const char* i1=Log::getDotFileDirName(); - // if (strlen(i1)!=0) { - // ControlFlowGraph& flowGraph = irm.getFlowGraph(); - // FlowGraph::printDotFile(flowGraph, irm.getMethodDesc(), "ea2"); - // } - //} + } // run(IRManager& irm) EscAnalyzer::EscAnalyzer(MemoryManager& mm, SessionAction* argSource, IRManager& irm) -: eaMemManager(mm), irManager(irm), mh(irm.getMethodDesc()),os_sc(Log::out()), - compInterface(irm.getCompilationInterface()) +: eaMemManager(mm), irManager(irm), mh(irm.getMethodDesc()), + compInterface(irm.getCompilationInterface()),os_sc(Log::out()) { maxMethodExamLevel = (uint32)argSource->getIntArg("max_level",maxMethodExamLevel_default); allProps = (uint32)argSource->getIntArg("d_prop",0); debug_method = argSource->getStringArg("d_method", NULL); method_ea_level = 0; // determines level of method scan - do_sync_removal = argSource->getBoolArg("do_sync_removal",false); + do_sync_removal = argSource->getBoolArg("do_sync_removal",true); + do_sync_removal_vc = argSource->getBoolArg("do_sync_removal_vc",true); + do_sync_removal_sm = argSource->getBoolArg("do_sync_removal_sm",true); do_scalar_repl = argSource->getBoolArg("do_scalar_repl",true); do_esc_scalar_repl = argSource->getBoolArg("do_esc_scalar_repl",true); print_scinfo = argSource->getBoolArg("sc_info",false); @@ -129,8 +122,8 @@ } EscAnalyzer::EscAnalyzer(EscAnalyzer* parent, IRManager& irm) -: eaMemManager(parent->eaMemManager), irManager(irm), mh(irm.getMethodDesc()), os_sc(Log::out()), - compInterface(irm.getCompilationInterface()) +: eaMemManager(parent->eaMemManager), irManager(irm), mh(irm.getMethodDesc()), + compInterface(irm.getCompilationInterface()), os_sc(Log::out()) { maxMethodExamLevel = parent->maxMethodExamLevel; allProps = parent->allProps; @@ -151,7 +144,8 @@ scannedObjsRev = new (eaMemManager) ObjIds(eaMemManager); scannedInsts = new (eaMemManager) ObjIds(eaMemManager); scannedSucNodes = new (eaMemManager) ObjIds(eaMemManager); - monitorInstUnits = new (eaMemManager) MonInstUnits(eaMemManager); + monitorInstUnits = new (eaMemManager) MonInstUnits(eaMemManager); + exam2Insts = new (eaMemManager) Insts(eaMemManager); methodEndInsts = new (eaMemManager) Insts(eaMemManager); checkInsts = new (eaMemManager) Insts(eaMemManager); @@ -204,7 +198,11 @@ EscAnalyzer::showFlags(std::ostream& os) { os << " escape flags:"<getId(); - (pr_n[cur]).fgNode = node; - (pr_n[cur]).instructions = NULL; // exam instructions #ifdef _DEBUG if (_cfgirun) { Log::out() <getId(); - Log::out() <getId() <begin( ); it != cngNodes->end( ); it++ ) { - CnGNode* n = (*it); - if (n->nodeType==NT_ACTARG && n->argNumber==0 && - ((MethodDesc*)(n->refObj))->isSynchronized()) { - ((MethodDesc*)(n->refObj))->printFullName(Log::out()); - Log::out()<clear(); - Log::out() << "================ Return Values 2" << std::endl; - for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { - if ((*it)->nodeType==NT_EXITVAL) { - printCnGNodeRefs(*it, "", Log::out()); - } - } - scannedObjs->clear(); - } #endif } @@ -416,8 +373,7 @@ Log::out()<<"sync "; if (mh.isStatic()) Log::out()<<"stat "; - if (Log::isEnabled()) - mh.printFullName(Log::out()); + mh.printFullName(Log::out()); Log::out()<< std::endl; } @@ -438,1603 +394,1112 @@ } // doAnalysis() -void -EscAnalyzer::eaFixupVars(IRManager& irm) { - OptPass::computeDominators(irm); - DominatorTree* dominatorTree = irm.getDominatorTree(); - ControlFlowGraph& flowGraph = irm.getFlowGraph(); - - DomFrontier frontier(irm.getNestedMemoryManager(),*dominatorTree,&flowGraph); - SSABuilder ssaBuilder(irm.getOpndManager(),irm.getInstFactory(),frontier,&flowGraph, irm.getOptimizerFlags()); - bool phiInserted = ssaBuilder.fixupVars(&irm.getFlowGraph(), irm.getMethodDesc()); - irm.setInSsa(true); - if (phiInserted) - irm.setSsaUpdated(); -} +void +EscAnalyzer::instrExam(Node* node) { + Inst *headInst = (Inst*)node->getFirstInst(); + int insnum=0; + Type* type; + CnGNode* cgnode; + uint32 ntype=0; + MethodDesc* md; + uint32 n; + bool addinst; + Inst* method_inst; + for (Inst* inst=headInst->getNextInst();inst!=NULL;inst=inst->getNextInst()) { + insnum++; + ntype=0; + if (_instrInfo) { + Log::out() <<"instrExam:" << std::endl; + Log::out() <<"++Node Id."<getId()<<" "<getDfNum()<getId()<<" "<getDfNum()<print(Log::out()); + Log::out() << std::endl; + } -void -EscAnalyzer::scanSyncInsts() { - MonInstUnits::iterator it; - Insts::iterator it1; - Insts* syncInsts; - CnGNode* node; - uint32 checkedState = 0; - uint32 nState = 0; - bool to_fix_ssa = false; - - if (monitorInstUnits == NULL) - return; - -#ifdef _DEBUG - if (_seinfo) { - Log::out() << "Synchronized units: " << std::endl; - } -#endif - for (it = monitorInstUnits->begin( ); it != monitorInstUnits->end( ); it++ ) { - node = findCnGNode_op((*it)->opndId); - checkedState = 0; - nState = getEscState(node); - if (node->nodeType == NT_OBJECT || nState == GLOBAL_ESCAPE) - checkedState = nState; - if (nState != GLOBAL_ESCAPE && (node->nodeType != NT_OBJECT)) { - checkedState = checkState(node->nInst,nState); - scannedObjs->clear(); - if (checkedState != nState && checkedState != 0) { -#ifdef _DEBUG - if (_setState) { - Log::out() <<"--scanSyncInsts 1: node " - <cngNodeId<<" opndId "<opndId - <<" state "; - if (Log::isEnabled()) - printState(node); - Log::out()<<" to esc.state "<< checkedState << std::endl; + switch (inst->getOpcode()) { + case Op_NewObj: // newobj + case Op_NewArray: // newarray + case Op_NewMultiArray: // newmultiarray + ntype=NT_OBJECT; // for 3 cases above + case Op_LdRef: // ldref + case Op_LdConstant: // ldc + if (ntype==0) + ntype=NT_LDOBJ; // loads refs + case Op_DefArg: // defarg + if (ntype==0) { + ntype=NT_DEFARG; // for Op_DefArg + defArgNumber++; } -#endif - setEscState(node,checkedState); - } - } #ifdef _DEBUG - if (_seinfo) { - Log::out() <<"--sync: state "; - Log::out() << checkedState << " "; - if (checkedState != nState) - Log::out() << "initState " << nState << " "; - Log::out() << node->cngNodeId << " - " << node->opndId << " "; - if (Log::isEnabled()) - printCnGNode(node,Log::out()); - Log::out() << std::endl; - } -#endif - if ((node->nodeType&NT_OBJECT)==0 && (getEscState(node) != GLOBAL_ESCAPE)) { - findObject(node->nInst); - scannedObjs->clear(); - } - syncInsts = (*it)->monInsts; -#ifdef _DEBUG - if (_seinfo) { - for (it1 = syncInsts->begin( ); it1 != syncInsts->end( ); it1++ ) { - Log::out() << " -"; - if (Log::isEnabled()) - (*it1)->print(Log::out()); - Log::out() << " // node " - << (*it1)->getNode()->getId() << std::endl; - } - } -#endif - if (getEscState(node) == GLOBAL_ESCAPE) - setSencEscState(node,syncInsts); - if (getVirtualCall(node)!=0) { - if (checkedState > GLOBAL_ESCAPE) { -#ifdef _DEBUG - if (_seinfo) { - Log::out() << "=-=- vc loc.esc." << std::endl; - findObject(node->nInst); - scannedObjs->clear(); + if (_instrInfo) { + Log::out() <<"Node Id."<getId()<nodeType==NT_OBJECT) { -#ifdef _DEBUG - if (_seinfo) { - Log::out() << "=-=- vc to optimize object" << std::endl; - } -#endif - fixMonitorInstsVCalls(*it); + if (inst->getDst()->getType()->isObject()) { + type=inst->getDst()->getType(); + assert(findCnGNode_op(inst->getDst()->getId())==NULL); + cgnode = addCnGNode_op(inst,type,ntype); } - if (node->nodeType==NT_RETVAL) { + break; + + case Op_Conv: // conv #ifdef _DEBUG - if (_seinfo) { - Log::out() << "=-=- vc to optimize retval" << std::endl; - } -#endif - fixMonitorInstsVCalls(*it); + if (_instrInfo) { + Log::out() <<"Node Id."<getId()<getDst()->getType()->isObject()) { + type=inst->getDst()->getType(); + assert(findCnGNode_op(inst->getDst()->getId())==NULL); + cgnode = addCnGNode_op(inst,type,NT_OBJECT); + } + break; + + case Op_LdFieldAddr: // ldflda + ntype=NT_INSTFLD; + case Op_LdStaticAddr: // ldsflda + if (ntype==0) + ntype=NT_STFLD; // for LdStaticAddr #ifdef _DEBUG - if (_seinfo) { - Log::out() << "=-=- vc gl.esc." << std::endl; - findObject(node->nInst); - scannedObjs->clear(); + if (_instrInfo) { + Log::out() <<"Node Id."<getId()<nodeType==NT_OBJECT && getEscState(node) != GLOBAL_ESCAPE) { -#ifdef _DEBUG - if (_seinfo) { - Log::out() << "++++ to optimize (remove) object" << std::endl; + FieldAccessInst* fainst; + if ((fainst=inst->asFieldAccessInst())!=NULL) { + type=fainst->getFieldDesc()->getFieldType(); //field type + if (type->isReference()) { + assert(findCnGNode_op(inst->getDst()->getId())==NULL); + cgnode = addCnGNode_op(inst,type,NT_REF); + CnGNode* n = findCnGNode_fl(inst,ntype); + if (n==NULL) { + n = addCnGNode_fl(inst,ntype); + } + cgnode->lNode=n; // stick nodes + exam2Insts->push_back(inst); + } else { + if (ntype==NT_INSTFLD) { + assert(findCnGNode_op(inst->getDst()->getId())==NULL); + cgnode = addCnGNode_op(inst,type,NT_REF); + CnGNode* n = findCnGNode_fl(inst,ntype); + if (n==NULL) { + n = addCnGNode_fl(inst,ntype); + } + exam2Insts->push_back(inst); + cgnode->lNode=n; // stick nodes + } + } } -#endif - removeMonitorInsts(syncInsts); - } + break; - if (node->nodeType==NT_DEFARG && getEscState(node) != GLOBAL_ESCAPE - && node->nInst->getDefArgModifier()==NonNullThisArg && mh.isSynchronized()) { + case Op_TauLdInd: // ldind #ifdef _DEBUG - if (_seinfo) { - Log::out() << "++++ to optimize (fix) defarg.ths" << std::endl; + if (_instrInfo) { + Log::out() <<"Node Id."<getId()<getOpcode()==Op_DefArg && opndInst->getDefArgModifier()==NonNullThisArg) { + type = inst->getDst()->getType(); + if (type->isReference()) { //isObject()) { + assert(findCnGNode_op(inst->getDst()->getId())==NULL); + cgnode = addCnGNode_op(inst,type,NT_LDOBJ); + exam2Insts->push_back(inst); + } + if (inst->getSrc(0)->getInst()->getOpcode()==Op_LdStaticAddr) + break; + if (type->isValue()) { + assert(findCnGNode_op(inst->getDst()->getId())==NULL); + cgnode = addCnGNode_op(inst,type,NT_LDVAL); + exam2Insts->push_back(inst); + } + break; - } - } -#ifndef PLATFORM_POSIX - checkCallSyncMethod(); -#endif - // to fix var operand inserted by fixMonitorInstsVCalls method - if (to_fix_ssa) { - OptPass::fixupSsa(irManager); - } - return; -} // scanSyncInsts() - - -void -EscAnalyzer::fixSyncMethodMonitorInsts(Insts* syncInsts) { - SsaTmpOpnd* stThis = (SsaTmpOpnd*)insertReadJitHelperCall(); - insertFlagCheck(syncInsts,stThis); -} // fixSyncMethodMonitorInsts(Insts* syncInsts) - - -void -EscAnalyzer::checkCallSyncMethod() { - CnGNodes::iterator it; - CnGRefs::iterator it2; - CnGNode* node; - CnGNode* aanode; - MethodDesc* md; - CalledMethodInfo* mtdInfo; - uint32 callee_state; - - for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { - node = (*it); - if (node->nodeType == NT_ACTARG && node->argNumber == 0) { - md = (MethodDesc*)(node->refObj); - if (md->isSynchronized() && node->nInst->getOpcode()==Op_DirectCall) { - const char* ch1 = md->getParentType()->getName(); - const char* ch2 = md->getName(); - const char* ch3 = md->getSignatureString(); - mtdInfo = getMethodInfo(ch1,ch2,ch3); - if (mtdInfo==NULL) { - callee_state = 0; + case Op_LdArrayBaseAddr: // ldbase + case Op_AddScaledIndex: // addindex #ifdef _DEBUG - if (_seinfo) { - Log::out() << "=- Methodinfo is NULL"; - Log::out() << std::endl; - } + if (_instrInfo) { + Log::out() <<"Node Id."<getId()<getDst()->getType()->isReference()) { + type=inst->getDst()->getType(); + assert(findCnGNode_op(inst->getDst()->getId())==NULL); + cgnode = addCnGNode_op(inst,type,NT_ARRELEM); + exam2Insts->push_back(inst); } + break; + + case Op_VMHelperCall: // callvmhelper #ifdef _DEBUG - if (_seinfo) { - Log::out() << "---- checkCallSyncMethod:" << std::endl; - if (Log::isEnabled()) - node->nInst->print(Log::out()); - Log::out() << std::endl; - if (Log::isEnabled()) - printCnGNode(node,Log::out()); - Log::out() << std::endl; - if (node->outEdges != NULL) { - for (it2 = node->outEdges->begin(); it2 != node->outEdges->end(); it2++ ) { - Log::out() << " ccsm: "; - if (Log::isEnabled()) - printState(callee_state); - Log::out() << " "; - if (Log::isEnabled()) - printCnGNode((*it2)->cngNodeTo,Log::out()); - Log::out() << std::endl; - } - } - Log::out() << "++++ checkCallSyncMethod: "; - Log::out() << " instance: " << md->isInstance() << - " initializer: " << md->isInstanceInitializer() << " end" << std::endl; + if (_instrInfo) { + Log::out() <<"Node Id."<getId()<outEdges != NULL) { - for (it2 = node->outEdges->begin(); it2 != node->outEdges->end(); it2++ ) { - aanode = (*it2)->cngNodeTo; - if (!isGlobalState(aanode->state)&& - (aanode->nodeType==NT_OBJECT||aanode->nodeType==NT_RETVAL)) { -#ifdef _DEBUG - if (_seinfo) { - Log::out() - << "=-=- sm this.agr.saving" << std::endl; - } -#endif - insertSaveJitHelperCall(node); -#ifdef _DEBUG - if (_seinfo) { - Log::out() - << " checkCSM: this was saved" - << std::endl; - } - } else { - if (_seinfo) { - Log::out() - << " checkCSM: this wasn't saved" - << std::endl; - } -#endif - } + if (!inst->getDst()->isNull()) { + if (inst->getDst()->getType()->isObject()) { + CompilationInterface::RuntimeHelperId callId = + inst->asVMHelperCallInst()->getVMHelperId(); + switch(callId) { + case CompilationInterface::Helper_GetTLSBase: + ntype = NT_ARRELEM; + break; + case CompilationInterface::Helper_NewObj_UsingVtable: + case CompilationInterface::Helper_NewVector_UsingVtable: + ntype = NT_OBJECT; + break; + default: + ntype = 0; + assert(0); } + type=inst->getDst()->getType(); + assert(findCnGNode_op(inst->getDst()->getId())==NULL); + cgnode = addCnGNode_op(inst,type,ntype); } } - } - } - } -} // checkCallSyncMethod() +#ifdef _DEBUG + if (_seinfo) { + CompilationInterface::RuntimeHelperId callId = + inst->asVMHelperCallInst()->getVMHelperId(); + if (method_ea_level == 0 && callId != CompilationInterface::Helper_Throw_Lazy) { - -/** - * Inserts ldc0, if it was not inserted previously, - * jit helper call to save this arg of direct call method. - * Parameter: - * CnGNode corresponding to this arg of direct call sync method. - */ -void -EscAnalyzer::insertSaveJitHelperCall(CnGNode* node) { - SsaTmpOpnd* stVal; - Inst* inst_before = node->nInst; - Node* oldBlock = inst_before->getNode(); - ControlFlowGraph& fg = irManager.getFlowGraph(); - -#ifdef _DEBUG - if (_seinfo) { - Log::out() << "++++ insertSJHC: before" << std::endl; - if (Log::isEnabled()) { - printNode(fg.getEntryNode(),Log::out()); - printNode(oldBlock,Log::out()); - } - Log::out() << "++++ insertSJHC: before end" << std::endl; - } + Log::out() <<"iE: callvmhelper "; + inst->print(Log::out()); + Log::out()<insertBefore(inst_before); - Node* newBlock = fg.splitNodeAtInstruction(jhcinst, true, false, instfactory.makeLabel()); - // add dispatch edge to oldBlock - fg.addEdge(oldBlock,newBlock->getExceptionEdgeTarget()); -#ifdef _DEBUG - if (_seinfo) { - Log::out() << "++++ insertSJHC: after" << std::endl; - if (Log::isEnabled()) { - printNode(fg.getEntryNode(),Log::out()); - printNode(oldBlock,Log::out()); - printNode(newBlock,Log::out()); - } - Log::out() << "++++ insertSJHC: after end" << std::endl; - } -#endif -} // insertSaveJitHelperCall(CnGNode* node) + break; + case Op_JitHelperCall: // calljithelper + if (method_ea_level == 0) { + Log::out() <<"iE: calljithelper "; + inst->print(Log::out()); + Log::out()<asJitHelperCallInst()->getJitHelperId()) { + case InitializeArray: + case FillArrayWithConst: + case SaveThisState: + case ReadThisState: + case LockedCompareAndExchange: + case AddValueProfileValue: + break; + default: + assert(0); + } + } + break; -/** - * Inserts ldc0, if it was not inserted previously, - * jit helper call to read this arg of the method. - * Parameter: - * CnGNode corresponding to this arg of direct call sync method. - * Returns: - * Opnd* stored_value - * 0 - this argument is thread local, 1 - this argument is thread global - */ -Opnd* -EscAnalyzer::insertReadJitHelperCall() { - ControlFlowGraph& fg = irManager.getFlowGraph(); - Node* oldBlock = fg.getEntryNode(); - Inst* inst_after = (Inst*)oldBlock->getFirstInst(); - TypeManager& _typeManager = irManager.getTypeManager(); - Type* typeInt32 = _typeManager.getInt32Type(); - OpndManager& _opndManager = irManager.getOpndManager(); - SsaTmpOpnd* stThis = _opndManager.createSsaTmpOpnd(typeInt32); - + case Op_TauStInd: // stind #ifdef _DEBUG - if (_seinfo) { - Log::out() << "++++ insertRJHC: before" << std::endl; - if (Log::isEnabled()) - printNode(oldBlock,Log::out()); - Log::out() << "++++ insertRJHC: before end" << std::endl; - } + if (_instrInfo) { + Log::out() <<"Node Id."<getId()<insertAfter(inst_after); - fg.splitNodeAtInstruction(jhcinst,true, false,instfactory.makeLabel()); - fg.addEdge(oldBlock,fg.getUnwindNode()); -#ifdef _DEBUG - if (_seinfo) { - Log::out() << "++++ insertRJHC: after" << std::endl; - if (Log::isEnabled()) { - printNode(oldBlock,Log::out()); - } - Log::out() << "++++ insertRJHC: after end" << std::endl; - } -#endif - return stThis; -} // insertReadJitHelperCall() + if ((type=inst->getSrc(0)->getType())->isObject() || type->isValue()) { + exam2Insts->push_back(inst); + } + break; - -/** - * Checks, that method contains monitor instructions with parameter - * which is this or subobject of this. - * Returns: true, if such monitors exist, false overwise. - */ -bool -EscAnalyzer::checkMonitorsOnThis() { - MonInstUnits::iterator it; - Insts::iterator it1; - CnGNode* node; - - if (monitorInstUnits==NULL) - return false; - for (it = monitorInstUnits->begin( ); it != monitorInstUnits->end( ); it++ ) { //540 - node = findCnGNode_op((*it)->opndId); - - Inst* opndInst = node->nInst; + case Op_DirectCall: // call #ifdef _DEBUG - if (_seinfo) { - Log::out() << " checkMOT: "; - if (Log::isEnabled()) - opndInst->print(Log::out()); - Log::out() << std::endl; - } + if (_instrInfo) { + Log::out() <<"Node Id."<getId()<getOpcode()==Op_DefArg && opndInst->getDefArgModifier()==NonNullThisArg) { -#ifdef _DEBUG - if (_seinfo) { - Log::out() << " checkMOT: "; - Log::out() << (int)(opndInst->getDefArgModifier()) << " " << - (opndInst->getDefArgModifier()==DefArgNoModifier) << " " << - (opndInst->getDefArgModifier()==NonNullThisArg) << " " << - (opndInst->getDefArgModifier()==DefArgBothModifiers) << " state: "; - if (Log::isEnabled()) - printState(node,Log::out()); - Log::out() << std::endl; - if (getEscState(node) != GLOBAL_ESCAPE) { - Log::out() << " defarg.ths isn't global "<< std::endl; + if (!inst->getDst()->isNull()) { + if (inst->getDst()->getType()->isObject()) { + type=inst->getDst()->getType(); + assert(findCnGNode_op(inst->getDst()->getId())==NULL); + cgnode = addCnGNode_op(inst,type,NT_RETVAL); + } } - } + md=inst->asMethodInst()->getMethodDesc(); + n=md->getNumParams(); + addinst=false; + for (uint32 i = 0; i < n; i++) { + Type* tt = md->getParamType(i); + if (!tt->isReference()) { + continue; + } + addinst=true; + assert(findCnGNode_mp(inst->getId(),i)==NULL); + cgnode = addCnGNode_mp(inst,md,NT_ACTARG, i); + } + if (addinst) { + exam2Insts->push_back(inst); + } +#ifdef _DEBUG + if (_seinfo) { + if (method_ea_level == 0) { + Log::out() <<"iE: call "; + if (md->isSynchronized()) + Log::out() << "sync "; + if (md->isStatic()) + Log::out() << "stat "; + if (md->isNative()) + Log::out() << "native "; + inst->print(Log::out()); + Log::out()<printFullName(Log::out()); + Log::out() << std::endl; + } + } #endif - return true; - } - } - return false; -} // checkMonitorsOnThis() + break; - -void -EscAnalyzer::setSencEscState(CnGNode* node,Insts* syncInsts) { - CnGEdges::iterator it; - Insts::iterator it1; - CnGRefs::iterator it2; - Inst* einst; - bool pLocalObj = true; - bool pLocalCurObj = false; + case Op_IndirectMemoryCall: //callimem #ifdef _DEBUG - if (_seinfo) { - Log::out() << "=- to node " << node->cngNodeId - << std::endl; - } + if (_instrInfo) { + Log::out() <<"Node Id."<getId()<clear(); // prepared for successor collection - for (it = cngEdges->begin( ); it != cngEdges->end( ); it++ ) { - for (it2 = (*it)->refList->begin( ); it2 != (*it)->refList->end( ); it2++ ) { - if ((*it2)->cngNodeTo == node) { - pLocalCurObj = false; - einst = (*it2)->edgeInst; -#ifdef _DEBUG + if (!inst->getDst()->isNull()) { + if (inst->getDst()->getType()->isObject()) { + type=inst->getDst()->getType(); + assert(findCnGNode_op(inst->getDst()->getId())==NULL); + cgnode = addCnGNode_op(inst,type,NT_RETVAL); + } + } + method_inst=inst->getSrc(0)->getInst(); + if (method_inst->getOpcode() == Op_LdVar) { + Opnd* funptr = inst->getSrc(0); + Type* optype = funptr->getType(); + MethodPtrType* opmtype = optype->asMethodPtrType(); + md = opmtype->getMethodDesc(); + } else { + md=method_inst->asMethodInst()->getMethodDesc(); + } + n=md->getNumParams(); + addinst=false; + for (uint32 i = 0; i < n; i++) { + Type* tt = md->getParamType(i); + if (!tt->isReference()) { + continue; + } + addinst=true; + assert(findCnGNode_mp(inst->getId(),i)==NULL); + cgnode = addCnGNode_mp(inst,md,NT_ACTARG,i); + } + if (addinst) { + exam2Insts->push_back(inst); + } +#ifdef _DEBUG if (_seinfo) { - Log::out() << "=- "; - Log::out() << einst->getNode()->getId() - << " "; - if (Log::isEnabled()) - einst->print(Log::out()); - Log::out() << std::endl; + if (method_ea_level == 0) { + Log::out() <<"iE: callimem "; + if (md->isSynchronized()) + Log::out() << "sync "; + if (md->isStatic()) + Log::out() << "stat "; + if (md->isNative()) + Log::out() << "native "; + inst->print(Log::out()); + Log::out()<printFullName(Log::out()); + Log::out() << std::endl; + } } #endif - if (einst->getOpcode() == Op_DirectCall) { - MethodDesc* md=einst->asMethodInst()->getMethodDesc(); - const char* ch1 = md->getParentType()->getName(); - const char* ch2 = md->getName(); - const char* ch3 = md->getSignatureString(); - CalledMethodInfo* mtdInfo = getMethodInfo(ch1,ch2,ch3); - if (mtdInfo==NULL) { + break; + + case Op_IntrinsicCall: // callintr #ifdef _DEBUG - if (_seinfo) { - Log::out() << "=- Methodinfo is NULL"; - Log::out() << std::endl; - } + if (_instrInfo) { + Log::out() <<"Node Id."<getId()<cngNodeFrom->argNumber); -#ifdef _DEBUG - if (_seinfo) { - Log::out() << "=-=- Method param " - << (*it)->cngNodeFrom->argNumber << " state is "; - if (Log::isEnabled()) - printState(st); - Log::out() << std::endl; - } -#endif - if ((st&ESC_MASK)>GLOBAL_ESCAPE) { - pLocalCurObj = true; -#ifdef _DEBUG - if (_seinfo) { - Log::out() << "=- Method param " - << (*it)->cngNodeFrom->argNumber << " state is "; - if (Log::isEnabled()) - printState(st); - Log::out() << std::endl; - } -#endif - } else { -#ifdef _DEBUG - if (_seinfo) { - if (Log::isEnabled()) - printMethodInfo(mtdInfo); - } -#endif - } + + if (!inst->getDst()->isNull()) { + assert(0); + } + n=inst->getNumSrcOperands(); + addinst=false; + for (uint32 i = 0; i < n; i++) { + Type* tt = inst->getSrc(i)->getType(); + if (!tt->isReference()) { + continue; } + addinst=true; + break; } - findObject1(einst); - collectSuccessors(einst->getNode()); - } - } - for (it1 = syncInsts->begin(); it1 != syncInsts->end( ); it1++ ) { - if (scannedSucNodes->size()!=0) { - if (checkScannedSucNodes((*it1)->getNode()->getId())!=0) { -#ifdef _DEBUG - if (_seinfo) { - if (pLocalCurObj) - Log::out() << " "; - Log::out() << "=- contains " - << (*it1)->getNode()->getId() - << std::endl; + if (addinst) { + exam2Insts->push_back(inst); + } + +#ifdef _DEBUG + if (_seinfo) { + if (method_ea_level == 0) { + Log::out() <<"iE: callintr "; + inst->print(Log::out()); + Log::out()<clear(); - } - if (pLocalObj) { -#ifdef _DEBUG - if (_seinfo) { - Log::out() << "=- may be optimized" - << std::endl; - } #endif - } -} // setSencEscState(CnGNode* node,Insts* syncInsts) + break; - -/** - * Collect all reachable from specified node nodes in FlowGraph. - * scannedSucNodes - result of collection. - */ -void -EscAnalyzer::collectSuccessors(Node* node) { - Node* n; - Edges::const_iterator eit; - const Edges& out_edges = node->getOutEdges(); - if (scannedSucNodes->size()!=0) { - if (checkScannedSucNodes(node->getId())!=0) { - return; - } - } - scannedSucNodes->push_back(node->getId()); - for (eit = out_edges.begin(); eit != out_edges.end(); ++eit) { - n = (*eit)->getTargetNode(); - collectSuccessors(n); - } -} // collectSuccessors(Node* node) - - -void -EscAnalyzer::collectGlobalNodeSuccessors(CnGNode* node) { - CnGEdges::iterator it; - CnGRefs::iterator it2; - Inst* einst; - bool pGlobalObj = false; + case Op_Catch: // catch #ifdef _DEBUG - if (_seinfo) { - Log::out() << "=- to node " << node->cngNodeId - << std::endl; - } + if (_instrInfo) { + Log::out() <<"Node Id."<getId()<clear(); // prepared for successor collection - for (it = cngEdges->begin( ); it != cngEdges->end( ); it++ ) { - for (it2 = (*it)->refList->begin( ); it2 != (*it)->refList->end( ); it2++ ) { - if ((*it2)->cngNodeTo == node) { - pGlobalObj = false; - einst = (*it2)->edgeInst; + if (inst->getDst()->getType()->isObject()) { + type=inst->getDst()->getType(); + assert(findCnGNode_op(inst->getDst()->getId())==NULL); + cgnode = addCnGNode_op(inst,type,NT_CATCHVAL); + } + break; + + case Op_StVar: // stvar #ifdef _DEBUG - if (_seinfo) { - Log::out() << "=-ggns "; - Log::out() << einst->getNode()->getId() - << " "; - if (Log::isEnabled()) - einst->print(Log::out()); - Log::out() << std::endl; + if (_instrInfo) { + Log::out() <<"Node Id."<getId()<getOpcode() == Op_DirectCall) { - MethodDesc* md=einst->asMethodInst()->getMethodDesc(); - const char* ch1 = md->getParentType()->getName(); - const char* ch2 = md->getName(); - const char* ch3 = md->getSignatureString(); - CalledMethodInfo* mtdInfo = getMethodInfo(ch1,ch2,ch3); - if (mtdInfo==NULL) { - pGlobalObj = true; + type = inst->getDst()->getType(); + if (type->isObject()) { + assert(findCnGNode_op(inst->getDst()->getId())==NULL); + cgnode = addCnGNode_op(inst,type,NT_VARVAL); + exam2Insts->push_back(inst); + } + break; + + case Op_Phi: // phi #ifdef _DEBUG - if (_seinfo) { - Log::out() << "ggns=- Methodinfo is NULL"; - Log::out() << std::endl; - } + if (_instrInfo) { + Log::out() <<"Node Id."<getId()<cngNodeFrom->argNumber); + type = inst->getDst()->getType(); + if (type->isReference()) { + assert(findCnGNode_op(inst->getDst()->getId())==NULL); + cgnode = addCnGNode_op(inst,type,NT_VARVAL); + exam2Insts->push_back(inst); + } + break; + + case Op_LdVar: // ldvar #ifdef _DEBUG - if (_seinfo) { - Log::out() << "ggns=-=- Method param " - << (*it)->cngNodeFrom->argNumber << " state is "; - if (Log::isEnabled()) - printState(st); - Log::out() << std::endl; - } + if (_instrInfo) { + Log::out() <<"Node Id."<getId()<getDst()->getType(); + if (type->isReference()) { + assert(findCnGNode_op(inst->getDst()->getId())==NULL); + cgnode = addCnGNode_op(inst,type,NT_LDOBJ); + exam2Insts->push_back(inst); + } + break; + + case Op_Return: // return + ntype=NT_EXITVAL; + case Op_Throw: // throw + if (ntype==0) + ntype=NT_THRVAL; #ifdef _DEBUG - if (_seinfo) { - Log::out() << "ggns=- Method param " - << (*it)->cngNodeFrom->argNumber << " state is "; - if (Log::isEnabled()) - printState(st); - Log::out() << std::endl; - } + if (_instrInfo) { + Log::out() <<"Node Id."<getId()<getNumSrcOperands()>0) { + if (inst->getSrc(0)->getType()->isObject()) { + assert(findCnGNode_in(inst->getId())==NULL); + cgnode = addCnGNode_ex(inst,ntype); + exam2Insts->push_back(inst); } } - if (einst->getOpcode() == Op_IndirectMemoryCall) - pGlobalObj = true; - if (einst->getOpcode() == Op_TauStInd) { - Inst* i1 = einst->getSrc(0)->getInst(); - if (i1->getOpcode()==Op_LdStaticAddr) - pGlobalObj = true; - uint32 st = getContainingObjState(i1); - if ((st&ESC_MASK)<=GLOBAL_ESCAPE) { - pGlobalObj = true; - } - } - findObject1(einst); - if (pGlobalObj) - collectSuccessors(einst->getNode()); - } - } - } -} // collectGlobalNodeSuccessors(CnGNode* node) + break; - -uint32 -EscAnalyzer::getContainingObjState(Inst* linst) { - Opnd* cop = NULL; - if (linst->getOpcode()==Op_LdStaticAddr) - return GLOBAL_ESCAPE; - if (linst->getOpcode()==Op_LdFieldAddr || linst->getOpcode()==Op_LdArrayBaseAddr) - cop = linst->getSrc(0); - if (linst->getOpcode()==Op_AddScaledIndex) - cop = linst->getSrc(0)->getInst()->getSrc(0); - else - return GLOBAL_ESCAPE; - CnGNode* n = findCnGNode_op(cop->getId()); - return n->state; -} // getContainingObjState(Inst* linst) - - -void -EscAnalyzer::removeMonitorInsts(Insts* syncInsts) { - ControlFlowGraph& fg = irManager.getFlowGraph(); - Insts::iterator it1; - Edge* excedge = NULL; - Node* targetnode = NULL; - Inst* reminst; + case Op_TauStaticCast: // staticcast + case Op_TauCast: // cast #ifdef _DEBUG - bool canthrow = false; + if (_instrInfo) { + Log::out() <<"Node Id."<getId()<getDst()->getType(); + if (type->isObject()) { + assert(findCnGNode_op(inst->getDst()->getId())==NULL); + cgnode = addCnGNode_op(inst,type,NT_REF); + exam2Insts->push_back(inst); + } + break; - for (it1 = syncInsts->begin( ); it1 != syncInsts->end( ); it1++ ) { - reminst = *it1; - if (reminst->getOperation().canThrow()==true) { - excedge = (Edge*)reminst->getNode()->getExceptionEdge(); - if (excedge != NULL) - targetnode = excedge->getTargetNode(); - else - targetnode = NULL; - } else { - excedge = NULL; - targetnode = NULL; - } + case Op_SaveRet: // saveret #ifdef _DEBUG - if (_seinfo) { - canthrow = reminst->getOperation().canThrow(); - Log::out() << " "; - if (Log::isEnabled()) - reminst->print(Log::out()); - Log::out() << std::endl; - Log::out() << " canThrow "<< canthrow; - Log::out() << std::endl; - if (excedge==NULL) { - Log::out() << " exception edge is NULL " << std::endl; - } else { - Log::out() << " target node is " - << targetnode->getId() << std::endl; - } - if (canthrow && (excedge==NULL)) { - const Edges& out_edges = reminst->getNode()->getOutEdges(); - Edges::const_iterator eit; - Node* n; - for (eit = out_edges.begin(); eit != out_edges.end(); ++eit) { - n = (*eit)->getTargetNode(); - Log::out() << " edge to node " - << n->getId() << " kind " << (*eit)->getKind() << std::endl; + if (_instrInfo) { + Log::out() <<"Node Id."<getId()<getDst()->getType(); + if (type->isIntPtr()) { + cgnode = findCnGNode_op(inst->getDst()->getId()); + if (cgnode == NULL) + cgnode = addCnGNode_op(inst,type,NT_INTPTR); + } + break; - reminst->unlink(); + case Op_TauMonitorEnter: // monenter + case Op_TauMonitorExit: // monexit + if (do_sync_removal && method_ea_level == 0) { + addMonInst(inst); #ifdef _DEBUG - if (_seinfo) { - Log::out() << " unlinked: "; - if (Log::isEnabled()) - reminst->print(Log::out()); - Log::out() << std::endl; - } + if (_seinfo) { + Log::out() << "iE: monX Node Id." + << node->getId() << " "; + inst->print(Log::out()); + Log::out()<getInEdges().size() > 1) { - fg.removeEdge(excedge); -#ifdef _DEBUG - if (_seinfo) { - Log::out() << " removed edge: " - << excedge->getSourceNode()->getId() << " -> " - << excedge->getTargetNode()->getId() << " kind " << excedge->getKind(); - Log::out() << std::endl; } -#endif - } else { - scannedObjs->clear(); - removeNode(targetnode); - scannedObjs->clear(); - } - } - } + break; -} // removeMonitorInsts(Insts* syncInsts) + case Op_TypeMonitorEnter:// tmonenter + case Op_TypeMonitorExit: // tmonexit + break; + case Op_TauVirtualCall: // callvirt + case Op_IndirectCall: // calli -void -EscAnalyzer::removeNode(Node* node) { - const Edges& out_edges = node->getOutEdges(); - Edges::const_iterator eit; - Node* n; + case Op_TauStRef: + case Op_TauStField: + case Op_TauStElem: + case Op_TauStStatic: + case Op_Copy: -#ifdef _DEBUG - if (_seinfo) { - Log::out() << " to remove node " - << node->getId() << std::endl; - } -#endif - if (scannedObjs->size()!=0) { - if (checkScannedObjs(node->getId())) { - return; - } - } - scannedObjs->push_back(node->getId()); - Nodes nodes2delete(irManager.getMemoryManager()); - for (eit = out_edges.begin(); eit != out_edges.end(); ++eit) { - n = (*eit)->getTargetNode(); - if (n->getInEdges().size() == 1) { - nodes2delete.push_back(n); - } - } - Nodes::iterator iter = nodes2delete.begin(), end = nodes2delete.end(); - for (; iter != end; ++iter) { - n = (*iter); - removeNode(n); - } - irManager.getFlowGraph().removeNode(node); - scannedObjs->pop_back(); -#ifdef _DEBUG - if (_seinfo) { - Log::out() << " removed node " - << node->getId() << std::endl; - } -#endif -} // removeNode(Node* node) + case Op_Box: + if (_instrInfo) { + Log::out() <<"--Node Id."<getId()<print(Log::out()); + Log::out() << std::endl; + } + break; -/** - * Creates i32_0 or i32_1 SsaTmpOpnd (in accordance with value: 0 or 1) - * if it was'n created before. - * Inserts ldc0 or ldc1 instruction after first instruction in entry Node, - * if SsaTmpOpnd was created. - * Returns: - * i32_0, if value = 0 - * i32_1, if value = 1 - */ -SsaTmpOpnd* -EscAnalyzer::insertLdConst(uint32 value) { - TypeManager& _typeManager = irManager.getTypeManager(); - Type* typeInt32 = _typeManager.getInt32Type(); - OpndManager& _opndManager = irManager.getOpndManager(); - InstFactory& _instFactory = irManager.getInstFactory(); - Inst* ildc = NULL; - if (value == 0) - if (i32_0 == NULL) { - i32_0 = _opndManager.createSsaTmpOpnd(typeInt32); - ildc = _instFactory.makeLdConst(i32_0, 0); + default: + + if (_instrInfo) { + Log::out() <<"~~Node Id."<getId()<print(Log::out()); + Log::out() << std::endl; + } } - if (value == 1) - if (i32_1 == NULL) { - i32_1 = _opndManager.createSsaTmpOpnd(typeInt32); - ildc = _instFactory.makeLdConst(i32_1, 1); - } - if (ildc != NULL) { - ildc->insertAfter(irManager.getFlowGraph().getEntryNode()->getFirstInst()); } - if (value == 0) - return i32_0; - return i32_1; -} // insertLdConst(uint32 value) + return; +} // instrExam(Node* node) void -EscAnalyzer::fixMonitorInstsVCalls(MonUnit* mu) { - Inst* opi = findCnGNode_op(mu->opndId)->nInst; - OpndManager& _opndManager = irManager.getOpndManager(); - InstFactory& _instFactory = irManager.getInstFactory(); - TypeManager& _typeManager = irManager.getTypeManager(); - Type* typeInt32 = _typeManager.getInt32Type(); - VarOpnd* muflag = _opndManager.createVarOpnd(typeInt32, false); - Inst* stvar0; // = _instFactory.makeStVar(muflag, i32_0); - Inst* stvar1; - Insts::iterator inst_it; - Insts* vcInsts = mu->icallInsts;; - Insts* syncInsts = mu->monInsts; -#ifdef _DEBUG - ControlFlowGraph& fg = irManager.getFlowGraph(); - Node* entry_node = fg.getEntryNode(); - Node* muo_node = opi->getNode(); - Node* node; -#endif +EscAnalyzer::instrExam2() { + Insts *instrs = exam2Insts; + int insnum=0; + Insts::iterator it; + Inst* inst; + Type* type; + CnGNode* cgnode; + CnGNode* cgn_src; + uint32 ntype=0; + MethodDesc* md; + uint32 n; + Inst* method_inst; + bool not_exam = false; - // values 0 and 1 to set flag variable -#ifdef _DEBUG - if (_seinfo) { - Log::out() << "=-=- w0 Before " << std::endl; - if (Log::isEnabled()) - printNode(entry_node,Log::out()); - } -#endif - insertLdConst(1); - insertLdConst(0); -#ifdef _DEBUG - if (_seinfo) { - Log::out() << "=-=- w0 After " << std::endl; - if (Log::isEnabled()) - printNode(entry_node,Log::out()); - } -#endif + for (it = instrs->begin( ); it != instrs->end( ); it++ ) { + inst=*it; + insnum++; + ntype=0; - // insert flag=0 after monitor instruction opnd creation instruction #ifdef _DEBUG - if (_seinfo) { - Log::out() << "=-=- w1 Before " << std::endl; - if (Log::isEnabled()) - printNode(muo_node,Log::out()); - } -#endif - stvar0 = _instFactory.makeStVar(muflag, i32_0); - stvar0->insertAfter(opi); -#ifdef _DEBUG - if (_seinfo) { - Log::out() << "=-=- w1 After " << std::endl; - if (Log::isEnabled()) - printNode(muo_node,Log::out()); - } -#endif - - // insert flag=1 before virtual call instructions -#ifdef _DEBUG - if (_seinfo) { - Log::out() << "=-=-=-=- Start w2" << std::endl; - } -#endif - for (inst_it = vcInsts->begin( ); inst_it != vcInsts->end( ); inst_it++ ) { -#ifdef _DEBUG - node = (*inst_it)->getNode(); - if (_seinfo) { - Log::out() << "=-=- w2 Before " << std::endl; - if (Log::isEnabled()) - printNode(node,Log::out()); + if (_instrInfo2) { + Log::out() <<"instrExam2: Node Id."<getNode()->getId()<< " "; + FlowGraph::printLabel(Log::out(),inst->getNode()); Log::out() << std::endl; + inst->print(Log::out()); Log::out() << std::endl; } #endif - stvar1 = _instFactory.makeStVar(muflag, i32_1); - stvar1->insertBefore(*inst_it); -#ifdef _DEBUG - if (_seinfo) { - Log::out() << "=-=- w2 After " << std::endl; - if (Log::isEnabled()) - printNode(node,Log::out()); - } -#endif - } -#ifdef _DEBUG - if (_seinfo) { - Log::out() << "=-=-=-=- Finish w2" << std::endl; - } -#endif - insertFlagCheck(syncInsts,muflag); + switch (inst->getOpcode()) { + case Op_LdFieldAddr: // ldflda + ntype=NT_INSTFLD; + case Op_LdStaticAddr: // ldsflda + if (ntype==0) + ntype=NT_STFLD; // for LdStaticAddr + FieldAccessInst* fainst; + if ((fainst=inst->asFieldAccessInst())!=NULL) { + bool isref = fainst->getFieldDesc()->getFieldType()->isReference(); + if (isref || ntype==NT_INSTFLD) { + cgn_src=findCnGNode_op(inst->getDst()->getId()); // field address node + if (isref) + assert(cgn_src!=NULL); + cgnode=findCnGNode_fl(inst,ntype); // field node + assert(cgnode!=NULL); + if (ntype == NT_INSTFLD) { + cgn_src=findCnGNode_op(inst->getSrc(0)->getId()); // instance node + // adding fld edge for ldflda + addEdge(cgn_src,cgnode,ET_FIELD,inst); + // special for java/lang/String::value + FieldDesc* fd=inst->asFieldAccessInst()->getFieldDesc(); + if (fd->getParentType()->isSystemString()&&strcmp(fd->getName(),"value")==0) { + addEdge(cgnode,cgn_src,ET_DEFER,inst); + } + } + } + } + break; -} // fixMonitorInstsVCalls(MonUnit* mu) + case Op_TauLdInd: // ldind + type=inst->getDst()->getType(); + if (type->isObject()) { + cgnode=findCnGNode_op(inst->getDst()->getId()); + assert(cgnode!=NULL); + // ref to loaded object + cgn_src=findCnGNode_op(inst->getSrc(0)->getId()); + assert(cgn_src!=NULL); + addEdge(cgn_src,cgnode,ET_POINT,inst); + } + if (type->isValue()) { + cgnode=findCnGNode_op(inst->getDst()->getId()); + assert(cgnode!=NULL); + // ref to loaded object + cgn_src=findCnGNode_op(inst->getSrc(0)->getId()); + assert(cgn_src!=NULL); + addEdge(cgn_src,cgnode,ET_POINT,inst); + } + break; + case Op_LdArrayBaseAddr: // ldbase + case Op_AddScaledIndex: // addindex + if (inst->getDst()->getType()->isReference()) { + cgnode=findCnGNode_op(inst->getDst()->getId()); + assert(cgnode!=NULL); + // ref to loaded address + if (inst->getOpcode()==Op_LdArrayBaseAddr) { + cgn_src=findCnGNode_op(inst->getSrc(0)->getId()); + assert(cgn_src!=NULL); + addEdge(cgn_src,cgnode,ET_FIELD,inst); // ref to base element + } + if (inst->getOpcode()==Op_AddScaledIndex) { + if (inst->getSrc(0)->getInst()->getOpcode()==Op_LdArrayBaseAddr) { + cgn_src=findCnGNode_op( + inst->getSrc(0)->getInst()->getSrc(0)->getId()); + assert(cgn_src!=NULL); + addEdge(cgn_src,cgnode,ET_FIELD,inst); // ref from array object to inner objects + } + } + } + break; -/** - * Inserts flag check before monitor instruction. - * If flag = 0 monitor instruction isn't executed. - * Operand flag may be VarOpnd* or SsaTmpOpnd* type. - */ -void -EscAnalyzer::insertFlagCheck(Insts* syncInsts, Opnd* muflag) { - Insts::iterator inst_it; - OpndManager& _opndManager = irManager.getOpndManager(); - InstFactory& _instFactory = irManager.getInstFactory(); - ControlFlowGraph& fg = irManager.getFlowGraph(); - TypeManager& _typeManager = irManager.getTypeManager(); - Type* typeInt32 = _typeManager.getInt32Type(); + case Op_TauStInd: // stind + if (inst->getSrc(0)->getType()->isObject()) { + // ref to loaded address + cgn_src=findCnGNode_op(inst->getSrc(0)->getId()); + assert(cgn_src!=NULL); + cgnode=findCnGNode_op(inst->getSrc(1)->getId()); + assert(cgnode!=NULL); + addEdge(cgnode,cgn_src,ET_DEFER,inst); + break; + } + if ((type=inst->getSrc(0)->getType())->isValue()) { + uint32 src_opcode = inst->getSrc(1)->getInst()->getOpcode(); + if (src_opcode==Op_LdStaticAddr) + break; + cgn_src=findCnGNode_op(inst->getSrc(0)->getId()); + if (cgn_src==NULL) { + cgn_src = addCnGNode_op(inst->getSrc(0)->getInst(),type,NT_LDVAL); + } + cgnode=findCnGNode_op(inst->getSrc(1)->getId()); + assert(cgnode!=NULL); + addEdge(cgnode,cgn_src,ET_DEFER,inst); + } + break; - // check flag before monitor instructions - assert(muflag->isVarOpnd()||muflag->isSsaTmpOpnd()); -#ifdef _DEBUG - if (_seinfo) { - Log::out() << "=-=-=-=- Start w3" << std::endl; - } -#endif - for (inst_it = syncInsts->begin( ); inst_it != syncInsts->end( ); inst_it++ ) { - Inst* curMonInst = (*inst_it); - Node* oldnode = curMonInst->getNode(); -#ifdef _DEBUG - if (_seinfo) { - Log::out() << "=-=- w3 Before " << std::endl; - if (Log::isEnabled()) - printNode(oldnode,Log::out()); - } -#endif - Node* afterMonInstBlock = NULL; - Node* tiInstBlock = NULL; - if ((*inst_it)->getNextInst()!=NULL) { - // monitor inst isn'n last - tiInstBlock = fg.splitNodeAtInstruction(curMonInst, true, false, _instFactory.makeLabel()); - afterMonInstBlock = tiInstBlock; - } else { - // monitor inst is last - afterMonInstBlock = (Node*)(oldnode->getUnconditionalEdge()->getTargetNode()); - } - SsaTmpOpnd* i32_flag; - if (muflag->isVarOpnd()) { - i32_flag = _opndManager.createSsaTmpOpnd(typeInt32); - _instFactory.makeLdVar(i32_flag,(VarOpnd*)muflag)->insertBefore(curMonInst); - } else - i32_flag = (SsaTmpOpnd*)muflag; - Inst* branch_inst = _instFactory.makeBranch(Cmp_EQ, Type::Int32, - i32_flag, i32_0, (LabelInst*)(afterMonInstBlock->getFirstInst())); - // insert flag check - branch_inst->insertBefore(curMonInst); -#ifdef _DEBUG - Node* monInstBlock = -#endif - fg.splitNodeAtInstruction(branch_inst,true, false, _instFactory.makeLabel()); - fg.addEdge(oldnode,afterMonInstBlock); -#ifdef _DEBUG - if (_seinfo) { - Log::out() << "=-=- w3 After " << std::endl; - if (Log::isEnabled()) { - printNode(oldnode,Log::out()); - printNode(monInstBlock,Log::out()); - if (tiInstBlock != NULL) { - printNode(tiInstBlock,Log::out()); + case Op_DirectCall: // call + md=inst->asMethodInst()->getMethodDesc(); + n=md->getNumParams(); + for (uint32 i = 0; i < n; i++) { + Type* tt = md->getParamType(i); + if (!tt->isReference()) + continue; + cgnode=findCnGNode_mp(inst->getId(),i); + assert(cgnode!=NULL); + cgn_src=findCnGNode_op(inst->getSrc(2+i)->getId()); + assert(cgn_src!=NULL); + addEdge(cgnode,cgn_src,ET_DEFER,inst); } - } - } -#endif - } -#ifdef _DEBUG - if (_seinfo) { - Log::out() << "=-=-=-=- Finish w3" << std::endl; - } -#endif -} // insertFlagCheck(Insts* syncInsts, VarOpnd* muflag) + break; + case Op_IndirectMemoryCall: //callimem + method_inst=inst->getSrc(0)->getInst(); + if (method_inst->getOpcode() == Op_LdVar) { + MethodPtrType* mpt = inst->getSrc(0)->getType()->asMethodPtrType(); + md = mpt->getMethodDesc(); + } else { + md=method_inst->asMethodInst()->getMethodDesc(); + } + n=md->getNumParams(); + for (uint32 i = 0; i < n; i++) { + Type* tt = md->getParamType(i); + if (!tt->isReference()) + continue; + cgnode = findCnGNode_mp(inst->getId(),i); + assert(cgnode!=NULL); + cgn_src=findCnGNode_op(inst->getSrc(3+i)->getId()); + assert(cgn_src!=NULL); + addEdge(cgnode,cgn_src,ET_DEFER,inst); + } + break; -void -EscAnalyzer::printNode(Node* n,::std::ostream& os) { - const Edges& ie = n->getInEdges(); - const Edges& oe = n->getOutEdges(); - Edges::const_iterator i; - os << "=- Node Id." << n->getId() << std::endl; - FlowGraph::printInsts(os,n,2); - os << "=- pred: "; - for(i = ie.begin(); i != ie.end(); ++i) { - os << (*i)->getSourceNode()->getId() << " "; - } - os << std::endl; - os << "=- succ: "; - for(i = oe.begin(); i != oe.end(); ++i) { - os << (*i)->getTargetNode()->getId() << " "; - } - os << std::endl; -} // printNode(Node* n,::std::ostream& os) + case Op_IntrinsicCall: // callintr + n=inst->getNumSrcOperands(); + switch(inst->asIntrinsicCallInst()->getIntrinsicId()) { + case ArrayCopyDirect: + case ArrayCopyReverse: + cgnode = findCnGNode_op(inst->getSrc(4)->getId()); + assert(cgnode!=NULL); + cgn_src = findCnGNode_op(inst->getSrc(2)->getId()); + assert(cgn_src!=NULL); + addEdge(cgnode,cgn_src,ET_DEFER,inst); + Log::out() << "need to add edge from "<< cgnode->cngNodeId << " - " << cgnode->opndId << " to " + << cgn_src->cngNodeId << " - " << cgn_src->opndId << std::endl; + break; + default: + assert(0); + } + break; + case Op_StVar: // stvar + if (inst->getDst()->getType()->isObject()) { + cgnode = findCnGNode_op(inst->getDst()->getId()); + assert(cgnode!=NULL); + cgn_src=findCnGNode_op(inst->getSrc(0)->getId()); + assert(cgn_src!=NULL); + addEdge(cgn_src,cgnode,ET_DEFER,inst); + } + break; -/** - * Checks state for NT_LDOBJ nodes. - * Returns - * GLOBAL_ESCAPE - for global escaped NT_OBJECT, NT_RETVAL, NT_DEFARG - * node state - for not global escaped NT_OBJECT - * 0 - for not global escaped ?NT_RETVAL, NT_DEFARG - */ -uint32 -EscAnalyzer::checkState(Inst* inst,uint32 st) { - uint32 st1; - Inst* inst1; - Opnd* opnd1; - uint32 nsrc=inst->getNumSrcOperands(); + case Op_Phi: // phi + if (inst->getDst()->getType()->isObject()) { + uint32 nsrc=inst->getNumSrcOperands(); + cgnode = findCnGNode_op(inst->getDst()->getId()); + assert(cgnode!=NULL); + for (uint32 i=0; igetSrc(i)->getId()); + assert(cgn_src!=NULL); + addEdge(cgn_src,cgnode,ET_DEFER,inst); + } + } + break; - if (st <= GLOBAL_ESCAPE) - return st; - if (scannedObjs->size()!=0) { - if (checkScannedObjs(inst->getId())) { - return st; + case Op_LdVar: // ldvar + type = inst->getDst()->getType(); + if (type->isReference()) { + cgnode = findCnGNode_op(inst->getDst()->getId()); + assert(cgnode!=NULL); + cgn_src=findCnGNode_op(inst->getSrc(0)->getId()); + assert(cgn_src!=NULL); + addEdge(cgn_src,cgnode,ET_DEFER,inst); // load ldobj + } + break; + + case Op_Return: // return + ntype=NT_EXITVAL; + case Op_Throw: // throw + if (ntype==0) + ntype=NT_THRVAL; + if (inst->getNumSrcOperands()>0) { + cgnode = findCnGNode_in(inst->getId()); + assert(cgnode!=NULL); + cgn_src=findCnGNode_op(inst->getSrc(0)->getId()); + assert(cgn_src!=NULL); + addEdge(cgnode,cgn_src,ET_DEFER,inst); + } + break; + + case Op_TauStaticCast: // staticcast + case Op_TauCast: // cast + type = inst->getDst()->getType(); + cgnode = findCnGNode_op(inst->getDst()->getId()); + assert(cgnode!=NULL); + if (cgnode->lNode == NULL) { + cgn_src=findCnGNode_op(inst->getSrc(0)->getId()); + assert(cgn_src!=NULL); + cgnode->lNode = cgn_src; + } + break; + + case Op_TauMonitorEnter: // monenter + case Op_TauMonitorExit: // monexit + case Op_TypeMonitorEnter:// tmonenter + case Op_TypeMonitorExit: // tmonexit + break; + + default: + if (_instrInfo2) { + not_exam = true; + } } - } - if (inst->getOpcode()==Op_DirectCall || inst->getOpcode()==Op_IndirectMemoryCall) { - Opnd *returnOpnd = inst->getDst(); - if (returnOpnd != NULL) { - CnGNode* n = findCnGNode_op(returnOpnd->getId()); - if (n != NULL) { - st1 = getEscState(n); - if (st > st1) - st=st1; + if (_instrInfo2) { + if (not_exam) { + Log::out() <<"!!! Not examined. "; + inst->print(Log::out()); Log::out() << std::endl; + not_exam = false; } } - return st; } - if (st <= GLOBAL_ESCAPE) - return st; - if (inst->getOpcode()==Op_TauLdInd || inst->getOpcode()==Op_LdVar) { // ldind, ldvar - Opnd *dst = inst->getDst(); - CnGNode* n = findCnGNode_op(dst->getId()); - if (n != NULL) { - st1 = getEscState(n); - if (st > st1) - st=st1; - } + return; +} // instrExam2() + + +EscAnalyzer::CnGNode* +EscAnalyzer::addCnGNode(Inst* inst, Type* type, uint32 ntype) { + CnGNode* cgnode = new (eaMemManager) CnGNode; // new CG node + + cgnode->cngNodeId = ++lastCnGNodeId; + cgnode->instrId = inst->getId(); + cgnode->nodeType = ntype; + cgnode->lNode = NULL; + cgnode->nInst = inst; + cgnode->outEdges = NULL; + if (cgnode->nodeType==NT_DEFARG) + cgnode->argNumber = defArgNumber; // number of formal parameter + else + cgnode->argNumber = 0; + if ((ntype==NT_STFLD)||ntype==NT_THRVAL) + setFullState(cgnode,GLOBAL_ESCAPE); + else { + if (ntype==NT_ACTARG) { + setFullState(cgnode,ARG_ESCAPE); + if (inst->getOpcode()==Op_IndirectMemoryCall) + setVirtualCall(cgnode); + } else + setFullState(cgnode,NO_ESCAPE); } - if (st <= GLOBAL_ESCAPE) - return st; - switch (inst->getOpcode()) { - case Op_LdRef: // ldref - case Op_NewObj: // newobj - case Op_NewArray: // newarray - case Op_NewMultiArray: // newmultiarray - case Op_DefArg: // defarg - { - CnGNode* n = findCnGNode_in(inst->getId()); - if (n != NULL) { - st1 = getEscState(n); - if (st > st1) - st=st1; - } - break; + if (ntype==NT_EXITVAL) + setCalleeEscaped(cgnode); + cgnode->nodeMDs = NULL; + if (type->isReference()) { + if (type->isArray()) { + if (type->asArrayType()->getElementType()->isReference()) { + cgnode->nodeRefType = NR_REFARR; + } else + cgnode->nodeRefType = NR_ARR; + } else + cgnode->nodeRefType = NR_REF; + if (ntype&(NT_OBJECT|NT_RETVAL)||ntype==NT_LDOBJ) { + cgnode->nodeMDs = new (eaMemManager) NodeMDs(eaMemManager); // to collect methods receiving object } - default: - break; + } else { + cgnode->nodeRefType = NR_PRIM; } - if (st <= GLOBAL_ESCAPE) - return st; - scannedObjs->push_back(inst->getId()); - for (uint32 i=0; igetSrc(i); - if (opnd1->isVarOpnd()) { - inst1 = opnd1->asVarOpnd()->getVarAccessInsts(); - } else { - inst1 = opnd1->getInst(); - } - st1 = checkState(inst1,st); - if (st > st1) - st=st1; - if (st<=GLOBAL_ESCAPE) - break; - } - scannedObjs->pop_back(); - return st; -} // checkState(Inst* inst,uint32 st) + cngNodes->push_back(cgnode); + return cgnode; +} // addCnGNode(Inst* inst, Type* type, uint32 ntype) -void -EscAnalyzer::findObject(Inst* inst,std::string text) { - Inst* inst1 = NULL; - uint32 nsrc=inst->getNumSrcOperands(); +EscAnalyzer::CnGNode* +EscAnalyzer::addCnGNode_op(Inst* inst, Type* type, uint32 ntype) { + CnGNode* cgnode = addCnGNode(inst, type, ntype); // new CG node + Opnd* opnd = inst->getDst(); - if (scannedObjs->size()!=0) { - if (checkScannedObjs(inst->getId())) { + cgnode->opndId = opnd->getId(); + cgnode->refObj = opnd; #ifdef _DEBUG - if (_seinfo || _scinfo) { - Log::out() << "instId " << inst->getId() - << " . . . " << std::endl; - } + if (_cngnodes) { + Log::out() <<"++++ addNode "; printCnGNode(cgnode,Log::out()); + Log::out() << std::endl; + } #endif - return; - } - } + return cgnode; +} // addCnGNode_op(Inst* inst, Type* type, uint32 ntype) + + +EscAnalyzer::CnGNode* +EscAnalyzer::addCnGNode_mp(Inst* inst, MethodDesc* md, uint32 ntype, uint32 narg) { + Type* type = md->getParamType(narg); + CnGNode* cgnode = addCnGNode(inst, type, ntype); // new CG node + + cgnode->opndId = 0; + cgnode->argNumber = narg; + cgnode->refObj = md; #ifdef _DEBUG - if (_seinfo || _scinfo) { - Log::out() << text; - if (Log::isEnabled()) - inst->print(Log::out()); + if (_cngnodes) { + Log::out() <<"++++ addNode "; printCnGNode(cgnode,Log::out()); Log::out() << std::endl; } #endif - if (inst->getOpcode()==Op_DirectCall || inst->getOpcode()==Op_IndirectMemoryCall) { - Opnd *returnOpnd = inst->getDst(); - if (returnOpnd != NULL) { - CnGNode* n = findCnGNode_op(returnOpnd->getId()); - if (n != NULL) { + return cgnode; +} // addCnGNode_mp(Inst* inst, MethodDesc* md, uint32 ntype, uint32 narg) + + +EscAnalyzer::CnGNode* +EscAnalyzer::addCnGNode_ex(Inst* inst, uint32 ntype) { + Type* type = inst->getSrc(0)->getType(); + CnGNode* cgnode = addCnGNode(inst, type, ntype); // new CG node + + cgnode->opndId = 0; + cgnode->refObj = inst->getSrc(0); // returned or thrown operand #ifdef _DEBUG - if (_seinfo || _scinfo) { - Log::out()<< text << " "; - if (Log::isEnabled()) - printCnGNode(n,Log::out()); - Log::out()<< std::endl; - } -#endif - } - } - if (inst->getOpcode()==Op_IndirectMemoryCall) { -#ifdef _DEBUG - MethodDesc* md; - if (inst->getSrc(0)->getInst()->getOpcode()== Op_LdVar) { - md = inst->getSrc(0)->getType()->asMethodPtrType()->getMethodDesc(); - } else { - md = inst->getSrc(0)->getInst()->asMethodInst()->getMethodDesc(); - } - if (_seinfo || _scinfo) { - Log::out() << text << " "; - if (Log::isEnabled()) - md->printFullName(Log::out() ); - Log::out() << std::endl; - } -#endif - } - return; + if (_cngnodes) { + Log::out() <<"++++ addNode "; printCnGNode(cgnode,Log::out()); + Log::out() << std::endl; } - if (inst->getOpcode()==Op_TauLdInd || inst->getOpcode()==Op_LdVar) { // ldind,ldvar - Opnd *dst = inst->getDst(); - CnGNode* n = findCnGNode_op(dst->getId()); - if (n != NULL) { -#ifdef _DEBUG - if (_seinfo || _scinfo) { - Log::out()<< text << " "; - if (Log::isEnabled()) - printCnGNode(n,Log::out()); - Log::out()<< std::endl; - } #endif - } - } - switch (inst->getOpcode()) { - case Op_LdRef: // ldref - case Op_NewObj: // newobj - case Op_NewArray: // newarray - case Op_NewMultiArray: // newmultiarray - case Op_DefArg: // defarg - { - CnGNode* n = findCnGNode_in(inst->getId()); - if (n != NULL) { -#ifdef _DEBUG - if (_seinfo || _scinfo) { - Log::out() << text << " "; - if (Log::isEnabled()) - printCnGNode(n,Log::out() ); - Log::out() << std::endl; - // if (getEscState(n) == GLOBAL_ESCAPE) - // return; - } -#endif - } - break; - } - default: - break; - } - scannedObjs->push_back(inst->getId()); - for (uint32 i=0; igetSrc(i)->getInst(); - findObject(inst1,text+" "); - } - scannedObjs->pop_back(); -} // findObject(Inst* inst,std::string text) + return cgnode; +} // addCnGNode_ex(Inst* inst, uint32 ntype) -/** - * Finds (prints) origin objects of monitor instruction operand. - */ -void -EscAnalyzer::findObject1(Inst* inst,std::string text) { - Inst* inst1; - uint32 nsrc=inst->getNumSrcOperands(); +EscAnalyzer::CnGNode* +EscAnalyzer::addCnGNode_fl(Inst* inst, uint32 ntype) { + Type* type = inst->getDst()->getType(); + CnGNode* cgnode = addCnGNode(inst, type, ntype); // new CG node - if (scannedObjs->size()!=0) { - if (checkScannedObjs(inst->getId())) { - if (_seinfo || _scinfo) { - Log::out() << "instId " << inst->getId() - << " . . . " << std::endl; - } - return; - } - } - if (_seinfo || _scinfo) { - Log::out() << text; - if (Log::isEnabled()) - inst->print(Log::out()); + cgnode->opndId = 0; + cgnode->refObj = inst; // returned or thrown operand +#ifdef _DEBUG + if (_cngnodes) { + Log::out() <<"++++ addNode "; printCnGNode(cgnode,Log::out()); Log::out() << std::endl; } - if (inst->getOpcode()==Op_DirectCall || inst->getOpcode()==Op_IndirectMemoryCall) { - Opnd *returnOpnd = inst->getDst(); - if (returnOpnd != NULL) { - CnGNode* n = findCnGNode_op(returnOpnd->getId()); - if (n != NULL) { - if (_seinfo || _scinfo) { - Log::out()<< text << " "; - if (Log::isEnabled()) - printCnGNode(n,Log::out()); - Log::out()<< std::endl; - } - } - } - if (inst->getOpcode()==Op_IndirectMemoryCall) { - MethodDesc* md; - if (inst->getSrc(0)->getInst()->getOpcode()== Op_LdVar) { - md = inst->getSrc(0)->getType()->asMethodPtrType()->getMethodDesc(); - } else { - md = inst->getSrc(0)->getInst()->asMethodInst()->getMethodDesc(); - } - if (_seinfo || _scinfo) { - Log::out() << text << " "; - if (Log::isEnabled()) - md->printFullName(Log::out() ); - Log::out() << std::endl; - } - } - return; - } - if (inst->getOpcode()==Op_TauLdInd || inst->getOpcode()==Op_LdVar) { // ldind,ldvar - Opnd *dst = inst->getDst(); - CnGNode* n = findCnGNode_op(dst->getId()); - if (n != NULL) { - if (_seinfo || _scinfo) { - Log::out()<< text << " "; - if (Log::isEnabled()) - printCnGNode(n,Log::out()); - Log::out()<< std::endl; - } - } - } - switch (inst->getOpcode()) { - case Op_LdRef: // ldref - case Op_NewObj: // newobj - case Op_NewArray: // newarray - case Op_NewMultiArray: // newmultiarray - case Op_DefArg: // defarg - { - CnGNode* n = findCnGNode_in(inst->getId()); - if (n != NULL) { - if (_seinfo || _scinfo) { - Log::out() << text << " "; - if (Log::isEnabled()) - printCnGNode(n,Log::out() ); - Log::out() << std::endl; - } - } - break; - } - default: - break; - } - scannedObjs->push_back(inst->getId()); - switch (inst->getOpcode()) { - case Op_TauLdInd: // ldind - case Op_AddScaledIndex: // addindex - inst1 = inst->getSrc(0)->getInst(); - findObject1(inst1,text+" "); - break; - case Op_TauStInd: // stind - for (uint32 i=0; i<2; i++) { - inst1 = inst->getSrc(i)->getInst(); - findObject1(inst1,text+" "); - } - break; - default: - for (uint32 i=0; igetSrc(i)->getInst(); - findObject1(inst1,text+" "); - } - } - scannedObjs->pop_back(); -} // findObject1(Inst* inst,std::string text) +#endif + return cgnode; +} // addCnGNode_fl(Inst* inst, uint32 ntype) -void -EscAnalyzer::markNotEscInsts() { +EscAnalyzer::CnGNode* +EscAnalyzer::findCnGNode_op(uint32 nId) { CnGNodes::iterator it; - bool p2 = false; - StlMap nonEscInsts(eaMemManager); - typedef ::std::pair intPair; - for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { - if ((*it)->nodeType == NT_OBJECT && getEscState(*it) > GLOBAL_ESCAPE) { - nonEscInsts.insert(intPair((*it)->instrId,getFullState(*it))); - } + if ((*it)->opndId==nId && ((*it)->nodeType & (NT_OBJS|NT_LDVAL))) + return (*it); } - if (p2 && Log::isEnabled()) { - Log::out() << "================ > "; - irManager.getMethodDesc().printFullName(Log::out()); - Log::out() << std::endl; - } -} // markNotEscInsts() + return(NULL); +} // findCnGNode_op(uint32 nId) -/** - * Summarizes common number of objects with the same state. - * Prints statictics if required. - */ -void -EscAnalyzer::createdObjectInfo() { +EscAnalyzer::CnGNode* +EscAnalyzer::findCnGNode_id(uint32 nId) { CnGNodes::iterator it; - int n0 = 0; - int n_ge = 0; - int n_ae = 0; - int n_ne = 0; - uint32 state = 0; - for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { - if ((*it)->nodeType == NT_OBJECT) { - n0++; - state = getEscState(*it); - if (state == GLOBAL_ESCAPE) - n_ge++; - if (state == ARG_ESCAPE) - n_ae++; - if (state == NO_ESCAPE) - n_ne++; - } + if ((*it)->cngNodeId==nId) + return (*it); } - if (_printstat==1) { - Log::out() << "************** Created object info: "; - if (Log::isEnabled()) - mh.printFullName(Log::out()); - Log::out() << std::endl; - Log::out() << " Number of created objects: " << n0 << std::endl; - if (n0>0) { - Log::out() << " Global escaped objects: " << n_ge << std::endl; - Log::out() << " Arg. escaped objects: " << n_ae << std::endl; - Log::out() << " Non escaped objects: " << n_ne << std::endl; - } - Log::out() << "************** " << std::endl; - } + return(NULL); +} // findCnGNode_id(uint32 nId) - comObjStat._n0+=n0; - comObjStat._n_ge+=n_ge; - comObjStat._n_ae+=n_ae; - comObjStat._n_ne+=n_ne; - if (_printstat==1) { - Log::out() << "************** Common created object info " << std::endl; - Log::out() << " Number of created objects: " << comObjStat._n0 << std::endl; - Log::out() << " Global escaped objects: " << comObjStat._n_ge << std::endl; - Log::out() << " Arg. escaped objects: " << comObjStat._n_ae << std::endl; - Log::out() << " Non escaped objects: " << comObjStat._n_ne << std::endl; - Log::out() << " Objects in loop: " << comObjStat._n_lo << std::endl; - Log::out() << "************** " << std::endl; +EscAnalyzer::CnGNode* +EscAnalyzer::findCnGNode_in(uint32 nId) { + CnGNodes::iterator it; + for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { + if ((*it)->instrId==nId) + return (*it); } -} // createdObjectInfo() + return(NULL); +} // findCnGNode_in(uint32 nId) -void -EscAnalyzer::saveScannedMethodInfo() { +EscAnalyzer::CnGNode* +EscAnalyzer::findCnGNode_mp(uint32 iId, uint32 aId) { CnGNodes::iterator it; - MethodDesc* mdesc = &irManager.getMethodDesc(); - MemoryManager& globalMM = irManager.getCurrentJITContext()->getGlobalMemoryManager(); -// MemoryManager& globalMM = eaMemManager; - const char* ch1 = mdesc->getParentType()->getName(); - const char* ch2 = mdesc->getName(); - const char* ch3 = mdesc->getSignatureString(); - if (calledMethodInfos==NULL) { -//std::cout<< "*1****** lock "<begin( ); it != cngNodes->end( ); it++ ) { + if ((*it)->instrId==iId && (*it)->argNumber==aId && + (*it)->nodeType == NT_ACTARG) + return (*it); } - if (getMethodInfo(ch1,ch2,ch3)!=NULL) // info was saved by another jit - return; -//std::cout<< "*2****** lock "<parentName=mpname; - mident->name=mname; - mident->signature=msig; - minfo->methodIdent=mident; - uint32 numpar = mdesc->getNumParams(); - minfo->numberOfArgs=numpar; - ParamInfos* prminfos = new (globalMM) ParamInfos(globalMM); - minfo->paramInfos=prminfos; - minfo->retValueState=0; - if (mdesc->getReturnType()->isReference()) { - uint32 escstate = 3, bitstate = 0; - for (it = cngNodes->begin( ); it != cngNodes->end( ); it++) { - if ((*it)->nodeType==NT_EXITVAL) { - bitstate = bitstate|getCalleeEscaped(*it); - if (escstate > getEscState(*it)) - escstate=getEscState(*it); +EscAnalyzer::CnGNode* +EscAnalyzer::findCnGNode_fl(Inst* inst, uint32 ntype) { + CnGNodes::iterator it; + FieldDesc* fd1; + FieldDesc* fd2; + uint32 idr = 0; + if (ntype==NT_INSTFLD) + idr=inst->getSrc(0)->getId(); + assert(inst->asFieldAccessInst()!=NULL); + fd1 = inst->asFieldAccessInst()->getFieldDesc(); + for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { + if ((*it)->nodeType==ntype) { + assert(((Inst*)((*it)->refObj))->asFieldAccessInst()!=NULL); + fd2 = ((Inst*)((*it)->refObj))->asFieldAccessInst()->getFieldDesc(); + if ( fd1->getParentType()==fd2->getParentType() && + strcmp(fd1->getName(),fd2->getName())==0) { + if (ntype==NT_INSTFLD) { + uint32 idf=((Inst*)((*it)->refObj))->getSrc(0)->getId(); + if (idr!=idf) { +#ifdef _DEBUG + if (_cngedges) { + Log::out() + << "++++ findCnGNode_fl: required " << idr + << " - found " << idf << " not found" << std::endl; + } +#endif + continue; + } +#ifdef _DEBUG + if (_cngedges) { + Log::out() + << "++++ findCnGNode_fl: required " << idr + << " - found " << idf << std::endl; + } +#endif + } + return (*it); } - } - minfo->retValueState=escstate|bitstate; - } - bool pmt = checkMonitorsOnThis(); - minfo->mon_on_this = pmt; - for (it = cngNodes->begin( ); it != cngNodes->end( ); it++) { - if ((*it)->nodeType==NT_DEFARG) { - ParamInfo* prminfo = new (globalMM) ParamInfo; - prminfo->state=getFullState(*it); - prminfo->paramNumber=(*it)->argNumber; - prminfos->push_back(prminfo); } } - calledMethodInfos->push_back(minfo); -//std::cout<< "*2****** unlock "<methodIdent->parentName << " "; - Log::out() << minfo->methodIdent->name << " "; - Log::out() << minfo->methodIdent->signature << " "; - Log::out() << minfo->numberOfArgs<< " " << std::endl; - for (it2 = minfo->paramInfos->begin( ); it2 != minfo->paramInfos->end( ); it2++) { - Log::out() << (*it2)->paramNumber << " st." - << (*it2)->state << std::endl; - } - Log::out() << "==== end ===== calledMethodInfo " << std::endl; - } -#endif -} // saveScannedMethodInfo(MemoryManager& mm) - +/** + * Creates edge if it doesn't exist yet. + */ void -EscAnalyzer::printMethodInfos() { - CalledMethodInfos::iterator it1; - ParamInfos::iterator it2; - Log::out() << "==== debug ===== calledMethodInfos; " << std::endl; - if (calledMethodInfos==NULL) - Log::out() << " calledMethodInfos is NULL " << std::endl; - if (calledMethodInfos!=NULL) - for (it1 = calledMethodInfos->begin( ); it1 != calledMethodInfos->end( ); it1++) { - Log::out() << (*it1)->methodIdent->parentName << " "; - Log::out() << (*it1)->methodIdent->name << " "; - Log::out() << (*it1)->methodIdent->signature << " "; - Log::out() << (*it1)->numberOfArgs<< " " << std::endl; - for (it2 = (*it1)->paramInfos->begin( ); - it2 != (*it1)->paramInfos->end( ); it2++) { - Log::out() << (*it2)->paramNumber << " st." - << (*it2)->state << std::endl; - } - } - Log::out() << "==== end ===== calledMethodInfos; " << std::endl; -} // printMethodInfos() +EscAnalyzer::addEdge(CnGNode* cgnfrom, CnGNode* cgnto, + uint32 etype, Inst* inst) { + CnGEdges::iterator it; + CnGRefs* el = NULL; + CnGRef* ref; + CnGNode* cgn1=cgnfrom; + CnGNode* cgn2=cgnto; - -void -EscAnalyzer::printMethodInfo(CalledMethodInfo* mi) { - ParamInfos::iterator it2; - Log::out() << "==== debug ===== calledMethodInfo " << std::endl; - if (mi==NULL) - Log::out() << " calledMethodInfo is NULL " << std::endl; - else { - Log::out() << mi->methodIdent->parentName << " "; - Log::out() << mi->methodIdent->name << " "; - Log::out() << mi->methodIdent->signature << " "; - Log::out() << "Number of parameters: " << mi->numberOfArgs<< " " << std::endl; - for (it2 = mi->paramInfos->begin( ); it2 != mi->paramInfos->end( ); it2++) { - Log::out() << (*it2)->paramNumber << " st."; - if (Log::isEnabled()) - printState((*it2)->state); - Log::out() << std::endl; - } - Log::out() << "Return value state: "; - printState(mi->retValueState); - Log::out() << " " << std::endl; + if (cgnfrom->lNode) { + cgn1 = findCnGNode_id(cgnfrom->lNode->cngNodeId); // to find CnG node using CnG node Id + assert(cgn1!=NULL); } - Log::out() << "==== end ===== calledMethodInfo " << std::endl; -} // printMethodInfos(CalledMethodInfo* mi) + if (cgnfrom->nodeType == NT_REF && cgnfrom->lNode == NULL) { + assert(cgnfrom->nInst->getOpcode()==Op_TauCast || cgnfrom->nInst->getOpcode()==Op_TauStaticCast); + cgn1 = findCnGNode_op(cgnfrom->nInst->getSrc(0)->getId()); + assert(cgn1!=NULL); + cgnfrom->lNode = cgn1; + } - -void -EscAnalyzer::scanCalleeMethod(Inst* call) { - MethodDesc* methodDesc = 0; - #ifdef _DEBUG - if (_scanMtds==1) { - Log::out() << "=="; - if (Log::isEnabled()) - call->print(Log::out()); - Log::out() << std::endl; + if (_cngedges) { + Log::out() + << "++++ addEdge: " << cgnfrom->cngNodeId << "-" << cgnfrom->opndId + << " ( "<cngNodeId << "-" << cgn1->opndId << " ) to " + << cgnto->cngNodeId << "-" << cgnto->opndId << " ( " + << cgn2->cngNodeId << "-" << cgn2->opndId << " )" << std::endl; } #endif - if (call == NULL) { // scanned Op_DirectCall, not scanned Op_IndirectMemoryCall - Log::out() << "scanMethod: NULL" << std::endl; + if (cgn1==cgn2) { +#ifdef _DEBUG + if (_cngedges) { + Log::out() << "+++++++ equal " + << cgnfrom->cngNodeId<< "-" << cgnfrom->opndId + << " ( "<cngNodeId << "-" << cgn1->opndId << " ) to " + << cgnto->cngNodeId << "-" << cgnto->opndId << " ( " + << cgn2->cngNodeId << "-" << cgn2->opndId << " )" << std::endl; + } +#endif return; } - methodDesc = call->asMethodCallInst()->getMethodDesc(); - + for ( it = cngEdges->begin( ); it != cngEdges->end( ); it++ ) { + if ((*it)->cngNodeFrom == cgn1) { + CnGRefs::iterator itr; + for ( itr = (*it)->refList->begin( ); itr != (*it)->refList->end( ); itr++ ) { + if ((*itr)->cngNodeTo == cgn2 && (*itr)->edgeType == etype && cgn1->nodeType != NT_INSTFLD) { + if (etype==ET_FIELD || cgn1->nodeType==NT_ACTARG) { #ifdef _DEBUG - if (_scanMtds==1) { - Log::out() << std::endl; - Log::out() << "scanMethod: " << methodDesc->getParentType()->getName() - << "." << methodDesc->getName() << methodDesc->getSignatureString() - << " " << methodDesc << std::endl; - Log::out() << " NumParams: " - << methodDesc->getNumParams()<< std::endl; - Log::out() << " isNative: " << methodDesc->isNative() << std::endl; - Log::out() << " isStatic: " << methodDesc->isStatic() << std::endl; - Log::out() << " isInstance: " << methodDesc->isInstance() << std::endl; - Log::out() << " isFinal: " << methodDesc->isFinal() << std::endl; - Log::out() << " isVirtual: " << methodDesc->isVirtual() << std::endl; - Log::out() << " isAbstract: " << methodDesc->isAbstract() << std::endl; - Log::out() << " isInstanceInitializer: " - << methodDesc->isInstanceInitializer() << std::endl; - Log::out() << " isOverridden: " << methodDesc->isOverridden() << std::endl; - } + if (_cngedges) { + Log::out() << "++++ addEdge: ET_FIELD || cgn1==NT_ACTARG && *->cngNodeTo == cgn2" << std::endl; + } #endif - - OpndManager& _opndManager(irManager.getOpndManager()); - Opnd *returnOpnd = 0; - if(call->getDst()->isNull()) - returnOpnd = _opndManager.getNullOpnd(); - else - returnOpnd = _opndManager.createSsaTmpOpnd(call->getDst()->getType()); - - IRManager* inlinedIRM = new (eaMemManager) IRManager(irManager.getMemoryManager(), irManager, *methodDesc, returnOpnd); - CompilationInterface& ci= inlinedIRM->getCompilationInterface(); - bool cibcmap = ci.isBCMapInfoRequired(); - if (cibcmap) { - ci.setBCMapInfoRequired(false); + return; + } + if (inst->getOpcode() == Op_IntrinsicCall) { //callintr + uint32 iid = inst->asIntrinsicCallInst()->getIntrinsicId(); + switch(iid) { + case ArrayCopyDirect: + case ArrayCopyReverse: +#ifdef _DEBUG + if (_cngedges) { + Log::out() << "++++ addEdge: callintr" << std::endl; + } +#endif + return; + default: + assert(0); + } + } + if (inst->getOpcode() == Op_LdFieldAddr) { + FieldDesc* fd=inst->asFieldAccessInst()->getFieldDesc(); + if (fd->getParentType()->isSystemString()&&strcmp(fd->getName(),"value")==0) { +#ifdef _DEBUG + if (_cngedges) { + Log::out() << "++++ addEdge: ldflda String.value" << std::endl; + } +#endif + return; + } + } +#ifdef _DEBUG + if (_cngedges) { + Log::out() << "++++ addEdge: edge already exists and new is added" << std::endl; + } +#endif + } + } + ref = new (eaMemManager) CnGRef; + ref->cngNodeTo=cgn2; + ref->edgeType=etype; + ref->edgeInst=inst; + (*it)->refList->push_back(ref); +#ifdef _DEBUG + if (_cngedges) { + Log::out() << "++++ addEdge: added CnGRef" << std::endl; + } +#endif + return; + } } - - { - CompilationContext inlineCC(irManager.getMemoryManager(), &ci, ci.getCompilationContext()); - inlineCC.setHIRManager(inlinedIRM); - runTranslatorSession(inlineCC); + ref = new (eaMemManager) CnGRef; + ref->cngNodeTo=cgn2; + ref->edgeType=etype; + ref->edgeInst=inst; + CnGEdge* cgedge=new (eaMemManager) CnGEdge; + el=new CnGRefs(eaMemManager); + cgedge->cngNodeFrom=cgn1; + el->push_back(ref); + cgedge->refList=el; + cngEdges->push_back(cgedge); + cgn1->outEdges=el; +#ifdef _DEBUG + if (_cngedges) { + Log::out() << "++++ addEdge: added edge" << std::endl; } - - optimizeTranslatedCode(*inlinedIRM); - - EscAnalyzer ea1(this, *inlinedIRM); - ea1.doAnalysis(); +#endif - if (cibcmap) { - ci.setBCMapInfoRequired(true); - } -} // scanCalleeMethod(Inst* call, MemoryManager& mm) +} // addEdge(CnGNode* cgnfrom, CnGNode* cgnto, uint32 etype, Inst* inst) -void EscAnalyzer::runTranslatorSession(CompilationContext& inlineCC) { - TranslatorSession* traSession = (TranslatorSession*)translatorAction->createSession(inlineCC.getCompilationLevelMemoryManager()); - traSession->setCompilationContext(&inlineCC); - inlineCC.setCurrentSessionAction(traSession); - traSession->run(); - inlineCC.setCurrentSessionAction(NULL); -} - void -EscAnalyzer::optimizeTranslatedCode(IRManager& irm) { - // run ssa pass - OptPass::computeDominators(irm); - DominatorTree* dominatorTree = irm.getDominatorTree(); - ControlFlowGraph& flowGraph = irm.getFlowGraph(); - - DomFrontier frontier(irm.getNestedMemoryManager(),*dominatorTree,&flowGraph); - SSABuilder ssaBuilder(irm.getOpndManager(),irm.getInstFactory(),frontier,&flowGraph, - irm.getOptimizerFlags()); - ssaBuilder.convertSSA(irm.getMethodDesc()); - irm.setInSsa(true); - irm.setSsaUpdated(); - - // run devirt pass -// Devirtualizer pass(irm); -// pass.guardCallsInRegion(irm, dominatorTree); - -} // optimizeTranslatedCode(IRManager& irManager) - - -void EscAnalyzer::setCreatedObjectStates() { CnGNodes::iterator it; NodeMDs::iterator it1; @@ -2044,10 +1509,9 @@ initNodeType = NT_STFLD; #ifdef _DEBUG if (_setState) { - Log::out() <<"-- before scanGE: node " - <<(*it)->cngNodeId<<" opnd "<<(*it)->opndId<<" state "; - if (Log::isEnabled()) - printState(*it); + Log::out() <<"-- before scanGE: nodeId " + <<(*it)->cngNodeId<<" opId "<<(*it)->opndId<<" state "; + printState(*it); Log::out() << std::endl; } #endif @@ -2057,50 +1521,31 @@ scannedObjs->clear(); scannedObjsRev->clear(); for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { - if ((*it)->nodeType&NT_EXITVAL) { // returned, thrown + if ((*it)->nodeType&NT_EXITVAL || (*it)->nodeType==NT_DEFARG) { // returned, thrown || defarg #ifdef _DEBUG if (_setState) { - Log::out() <<"-- before scanEV: node " - <<(*it)->cngNodeId<<" opnd "<<(*it)->opndId<<" state "; - if (Log::isEnabled()) - printState(*it); + Log::out() <<"-- before scanEVDA: nodeId " + <<(*it)->cngNodeId<<" opId "<<(*it)->opndId<<" state "; + printState(*it); Log::out() << std::endl; } #endif initNodeType = (*it)->nodeType; scanCnGNodeRefsGE(*it,false); + scannedObjs->clear(); // + scannedObjsRev->clear(); // } } scannedObjs->clear(); scannedObjsRev->clear(); for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { - if ((*it)->nodeType==NT_DEFARG) { -#ifdef _DEBUG - if (_setState) { - Log::out() <<"-- before scanDA: node " - <<(*it)->cngNodeId<<" opnd "<<(*it)->opndId<<" state "; - if (Log::isEnabled()) - printState(*it); - Log::out() << std::endl; - } -#endif - initNodeType = NT_DEFARG; - scanCnGNodeRefsGE(*it,false); - scannedObjs->clear(); // temporary - scannedObjsRev->clear(); - } - } - scannedObjs->clear(); - scannedObjsRev->clear(); - for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { if ((*it)->nodeType==NT_ACTARG) { curMDNode=(*it)->cngNodeId; #ifdef _DEBUG if (_setState) { - Log::out() <<"-- before scanAE: node " - <<(*it)->cngNodeId<<" opnd "<<(*it)->opndId<<" state "; - if (Log::isEnabled()) - printState(*it); + Log::out() <<"-- before scanAE: nodeId " + <<(*it)->cngNodeId<<" opId "<<(*it)->opndId<<" state "; + printState(*it); Log::out() << std::endl; } #endif @@ -2124,23 +1569,20 @@ if (ltree->isValid()) for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { if ( (*it)->nodeType==NT_OBJECT) { - if (ltree->getLoopHeader((*it)->fgNode,false)) { - if ((*it)->state > GLOBAL_ESCAPE) { + if (ltree->getLoopHeader((*it)->nInst->getNode(),false)) { #ifdef _DEBUG - if (_setState) { - Log::out() - <<"--setSt loop: node " - <<(*it)->cngNodeId<<" opndId " - <<(*it)->opndId<<" state "; - if (Log::isEnabled()) - printState(*it); - Log::out() - <<" to set loop" << std::endl; - } + if (_setState) { + Log::out() + <<"--setSt loop: nodeId " + <<(*it)->cngNodeId<<" opId " + <<(*it)->opndId<<" state "; + printState(*it); + Log::out() + <<" to set loop" << std::endl; + } #endif - setLoopCreated(*it); - comObjStat._n_lo++; - } + setLoopCreated(*it); + comObjStat._n_lo++; } } } @@ -2153,7 +1595,6 @@ } for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { uint32 nt = (*it)->nodeType; -// if (((nt&(NT_OBJECT|NT_RETVAL) || nt==NT_LDOBJ)&&((*it)->nodeRefType!=NR_PRIM)) && (getEscState(*it)==ARG_ESCAPE)) { if ((nt&(NT_OBJECT|NT_RETVAL) || nt==NT_LDOBJ) && (getEscState(*it)==ARG_ESCAPE)) { for (it1 = (*it)->nodeMDs->begin(); it1 != (*it)->nodeMDs->end(); it1++) { @@ -2163,8 +1604,8 @@ Inst* callInst = n->nInst; #ifdef _DEBUG if (_setState) { - Log::out()<<"--setSt chk arg_esc: node " <<(*it)->cngNodeId - <<" opndId " <<(*it)->opndId<<" state "; + Log::out()<<"--setSt chk arg_esc: nodeId " <<(*it)->cngNodeId + <<" opId " <<(*it)->opndId<<" state "; printState(*it); Log::out() << std::endl; Log::out() << " "; callInst->print(Log::out()); @@ -2172,33 +1613,20 @@ } #endif if (mdesc->isNative()) { // not scanned native methods - if (strcmp(mdesc->getParentType()->getName(),"java/lang/VMMemoryManager")==0 - &&strcmp(mdesc->getName(),"arrayCopy")==0) { - break; // objects don't escape java/lang/VMMemoryManager::arrayCopy - } - if (strcmp(mdesc->getParentType()->getName(),"java/lang/VMClassRegistry")==0 - &&strcmp(mdesc->getName(),"getName")==0) { - break; // objects don't escape java/lang/VMClassRegistry::getName - } - if (strcmp(mdesc->getParentType()->getName(),"java/lang/VMThreadManager")==0 - &&strcmp(mdesc->getName(),"notify")==0) { - break; // objects don't escape java/lang/VMThreadManager::notify - } + setEscState(*it,GLOBAL_ESCAPE); #ifdef _DEBUG if (_scanMtds==1) { - if (Log::isEnabled()) - mdesc->printFullName(Log::out()); + mdesc->printFullName(Log::out()); Log::out() << std::endl; Log::out() << " isNative: " << mdesc->isNative() << std::endl; } if (_setState) { - Log::out() <<"--setSt 1: node " - <<(*it)->cngNodeId<<" opndId "<<(*it)->opndId + Log::out() <<"--setSt 1: nodeId " + <<(*it)->cngNodeId<<" opId "<<(*it)->opndId <<" state "; - if (Log::isEnabled()) - printState(*it); + printState(*it); Log::out()<<" to gl.esc."<< std::endl; } #endif @@ -2211,10 +1639,9 @@ if (monitorInstUnits!=NULL) mu = findMonUnit((*it)->opndId); if (mu != NULL) { -// setVirtualCall(*it); addMonUnitVCall(mu,callInst); #ifdef _DEBUG - if (_seinfo&&Log::isEnabled()) { + if (_seinfo) { Log::out() << "=-=-=-=- callimem for this "; Log::out() << std::endl; Log::out() << "=-=- "; @@ -2232,15 +1659,12 @@ continue; } } - // setEscState(*it,GLOBAL_ESCAPE); #ifdef _DEBUG if (_scanMtds==1) { - if (Log::isEnabled()) { - callInst->print(Log::out()); - Log::out() << std::endl; - mdesc->printFullName(Log::out()); - } + callInst->print(Log::out()); Log::out() << std::endl; + mdesc->printFullName(Log::out()); + Log::out() << std::endl; Log::out() << " isStatic: " << mdesc->isStatic() << std::endl; Log::out() << " isFinal: " @@ -2268,28 +1692,25 @@ } if (_setState) { - Log::out() <<"--setSt 2: node " - <<(*it)->cngNodeId<<" opndId "<<(*it)->opndId + Log::out() <<"--setSt 2: nodeId " + <<(*it)->cngNodeId<<" opId "<<(*it)->opndId <<" state "; - if (Log::isEnabled()) - printState(*it); -// Log::out() <<" to gl.esc." + printState(*it); Log::out() <<" to v.call." << std::endl; } #endif continue; //break; } - CalledMethodInfo* mtdInfo = findMethodInfo(mdesc,callInst); + CalleeMethodInfo* mtdInfo = findMethodInfo(mdesc,callInst); if (mtdInfo == NULL) { // no info about called method setEscState(*it,GLOBAL_ESCAPE); #ifdef _DEBUG if (_setState) { - Log::out() <<"--setSt 3: node " - <<(*it)->cngNodeId<<" opndId "<<(*it)->opndId + Log::out() <<"--setSt 3: nodeId " + <<(*it)->cngNodeId<<" opId "<<(*it)->opndId <<" state "; - if (Log::isEnabled()) - printState(*it); + printState(*it); Log::out() <<" to gl.esc." << std::endl; } @@ -2314,8 +1735,7 @@ Log::out() <<(*it2)->paramNumber<<" == "<state <<" < "<< getEscState(*it)<<" "; - if (Log::isEnabled()) - printState(*it); + printState(*it); Log::out() << std::endl; } #endif @@ -2323,11 +1743,10 @@ if ((state=(*it2)->state&ESC_MASK) < getEscState(*it)) { #ifdef _DEBUG if (_setState) { - Log::out()<<"--setSt cmi1: node " - <<(*it)->cngNodeId<<" opndId "<<(*it)->opndId + Log::out()<<"--setSt cmi1: nodeId " + <<(*it)->cngNodeId<<" opId "<<(*it)->opndId <<" state "; - if (Log::isEnabled()) - printState(*it); + printState(*it); Log::out() <<" to state " <clear(); scannedObjsRev->clear(); } @@ -2351,10 +1770,9 @@ if (nt==NT_CATCHVAL || ((*it)->nInst->getOpcode())==Op_IndirectMemoryCall) { #ifdef _DEBUG if (_setState) { - Log::out() <<"--setCOS 1: node " - <<(*it)->cngNodeId<<" opndId "<<(*it)->opndId <<" state "; - if (Log::isEnabled()) - printState(*it); + Log::out() <<"--setCOS 1: nodeId " + <<(*it)->cngNodeId<<" opId "<<(*it)->opndId <<" state "; + printState(*it); Log::out() <<" to gl.esc."<< std::endl; } #endif @@ -2365,10 +1783,9 @@ if (mdesc->isNative()) { // not scanned native methods #ifdef _DEBUG if (_setState) { - Log::out() <<"--setCOS 2: node " - <<(*it)->cngNodeId<<" opndId "<<(*it)->opndId <<" state "; - if (Log::isEnabled()) - printState(*it); + Log::out() <<"--setCOS 2: nodeId " + <<(*it)->cngNodeId<<" opId "<<(*it)->opndId <<" state "; + printState(*it); Log::out() <<" to gl.esc."<< std::endl; } #endif @@ -2378,24 +1795,22 @@ if (((*it)->nInst->getOpcode())!=Op_DirectCall) { #ifdef _DEBUG if (_setState) { - Log::out() <<"--setCOS 3: node " - <<(*it)->cngNodeId<<" opndId "<<(*it)->opndId <<" state "; - if (Log::isEnabled()) - printState(*it); + Log::out() <<"--setCOS 3: nodeId " + <<(*it)->cngNodeId<<" opId "<<(*it)->opndId <<" state "; + printState(*it); Log::out() <<" to gl.esc."<< std::endl; } #endif setEscState(*it,GLOBAL_ESCAPE); continue; } - CalledMethodInfo* mthInfo = findMethodInfo(mdesc,(*it)->nInst); + CalleeMethodInfo* mthInfo = findMethodInfo(mdesc,(*it)->nInst); if (mthInfo == NULL) { #ifdef _DEBUG if (_setState) { - Log::out() <<"--setCOS 4: node " - <<(*it)->cngNodeId<<" opndId "<<(*it)->opndId <<" state "; - if (Log::isEnabled()) - printState(*it); + Log::out() <<"--setCOS 4: nodeId " + <<(*it)->cngNodeId<<" opId "<<(*it)->opndId <<" state "; + printState(*it); Log::out() <<" to gl.esc."<< std::endl; } #endif @@ -2404,10 +1819,9 @@ if (getEscState(*it)>((mthInfo->retValueState)&ESC_MASK)) { #ifdef _DEBUG if (_setState) { - Log::out() <<"--setCOS 5: node " - <<(*it)->cngNodeId<<" opndId "<<(*it)->opndId <<" state "; - if (Log::isEnabled()) - printState(*it); + Log::out() <<"--setCOS 5: nodeId " + <<(*it)->cngNodeId<<" opId "<<(*it)->opndId <<" state "; + printState(*it); Log::out() <<" to "<< mthInfo->retValueState<< std::endl; } #endif @@ -2416,179 +1830,57 @@ } } } - + scannedObjs->clear(); + scannedObjsRev->clear(); + scannedSucNodes->clear(); + // check states of array elements and fields values + for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { + uint32 nt = (*it)->nodeType; + if ((nt&(NT_OBJECT|NT_RETVAL) || nt==NT_LDOBJ) && (getEscState(*it)!=GLOBAL_ESCAPE)) { + if ((*it)->outEdges == NULL) + continue; +#ifdef _DEBUG + if (_setState) { + Log::out() <<"--setCOS 6: to check subobj nodes "; + printCnGNode(*it,Log::out()); Log::out() << std::endl; + } +#endif + checkSubobjectStates(*it); + } + scannedObjs->clear(); + scannedObjsRev->clear(); + scannedSucNodes->clear(); + } uint32 rs = NO_ESCAPE; CnGRefs::iterator it2; CnGNode* cgn; + // set escape state for NT_EXITVAL nodes for (it = cngNodes->begin( ); it != cngNodes->end( ); it++) { if ((*it)->nodeType==NT_EXITVAL) { if ((*it)->outEdges ==NULL) continue; for (it2 = (*it)->outEdges->begin( ); it2 != (*it)->outEdges->end( ); it2++ ) { cgn = (*it2)->cngNodeTo; - rs = getSubobjectStates(cgn); + // rs = getSubobjectStates(cgn); if (getEscState(cgn)<=(rs&ESC_MASK)) rs = getFullState(cgn); } #ifdef _DEBUG if (_setState) { - Log::out() <<"--setCOS 6: node " - <<(*it)->cngNodeId<<" opndId "<<(*it)->opndId <<" state "; - if (Log::isEnabled()) - printState(*it); + Log::out() <<"--setCOS 7: nodeId " + <<(*it)->cngNodeId<<" opId "<<(*it)->opndId <<" state "; + printState(*it); Log::out() <<" to "<< rs << std::endl; } #endif setFullState(*it,rs); - } - scannedObjs->clear(); - scannedObjsRev->clear(); } +} // setCreatedObjectStates() -} // setCreatedObjectStates(MemoryManager& mm) - - -uint32 -EscAnalyzer::getSubobjectStates(CnGNode* node) { - uint32 st = NO_ESCAPE, rs; - CnGRefs::iterator it; - CnGNode* cgn; - - if (scannedObjs->size()!=0) { - if (checkScannedObjs(node->cngNodeId)) - return st; - } - if (node->outEdges==NULL) - return st; - for (it = node->outEdges->begin( ); it != node->outEdges->end( ); it++ ) { - cgn = (*it)->cngNodeTo; -#ifdef _DEBUG - if (_setState) { - Log::out() <<"--getSOS : node " - <cngNodeId<<" opndId "<opndId <<" state "; - if (Log::isEnabled()) - printState(cgn); - Log::out() << std::endl; - } -#endif - if (st > getEscState(cgn)) - st = getEscState(cgn); - if (st == GLOBAL_ESCAPE) - return st; - scannedObjs->push_back(node->cngNodeId); - rs = getSubobjectStates(cgn); - scannedObjs->pop_back(); - if (st > rs) - st = rs; - if (st == GLOBAL_ESCAPE) - return st; - } - return st; -} - - -EscAnalyzer::CalledMethodInfo* -EscAnalyzer::getMethodInfo(const char* ch1,const char* ch2,const char* ch3) { - CalledMethodInfos::iterator it; - if (calledMethodInfos==NULL) - return NULL; - for (it = calledMethodInfos->begin( ); it != calledMethodInfos->end( ); it++ ) { - const char* c1 = (*it)->methodIdent->parentName; - const char* c2 = (*it)->methodIdent->name; - const char* c3 = (*it)->methodIdent->signature; - if (strcmp(c1,ch1)==0 && strcmp(c2,ch2)==0 && strcmp(c3,ch3)==0) - return (*it); - } - return NULL; -} // getMethodInfo(const char* ch1,const char* ch2,const char* ch3) - - -EscAnalyzer::CalledMethodInfo* -EscAnalyzer::findMethodInfo(MethodDesc* mdesc,Inst* callInst) { - const char* ch1 = mdesc->getParentType()->getName(); - const char* ch2 = mdesc->getName(); - const char* ch3 = mdesc->getSignatureString(); - CalledMethodInfo* mtdInfo = getMethodInfo(ch1,ch2,ch3); - if (mtdInfo == NULL) { -#ifdef _DEBUG - if (_scanMtds==1) { - Log::out() << " = = = = = = = = To scan method " << std::endl; - if (Log::isEnabled()) { - mdesc->printFullName(Log::out()); - Log::out() << std::endl; - callInst->print(Log::out()); - } - Log::out() << std::endl; - } -#endif - if (method_ea_level < maxMethodExamLevel) { - scanCalleeMethod(callInst); - mtdInfo=getMethodInfo(ch1,ch2,ch3); - } - } - return mtdInfo; -} // findMethodInfo(MethodDesc* mdesc) - - -/** - * Finds specified parameter in specified method info. - * Returns: - * state - for existent parameter, - * 0 - for another cases. - */ -uint32 -EscAnalyzer::getMethodParamState(CalledMethodInfo* mi, uint32 np) { - ParamInfos::iterator it; - uint32 st = 0; - if (mi==NULL) - return 0; - for (it = mi->paramInfos->begin( ); it != mi->paramInfos->end( ); it++) { - if ((*it)->paramNumber == np) { - st = (*it)->state; - return st; - } - } - return st; -} // getMethodParamState(CalledMethodInfo* mi, uint32 np) - - void -EscAnalyzer::printCreatedObjectsInfo(::std::ostream& os) { - CnGNodes::iterator it; - NodeMDs::iterator it1; - os << "================ Created Object States < "; - irManager.getMethodDesc().printFullName(os); - os << std::endl; - for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { - uint32 nt = (*it)->nodeType; - if (nt&(NT_OBJECT|NT_RETVAL) || nt==NT_LDOBJ) { - printCnGNode(*it,os); - ((Opnd*)(*it)->refObj)->printWithType(os); - if (getEscState(*it)==ARG_ESCAPE) { - for (it1 = (*it)->nodeMDs->begin(); it1 != (*it)->nodeMDs->end(); it1++) { - CnGNode* n=findCnGNode_id(*it1); - assert(n!=NULL); - os << std::endl; os <<" "; - printCnGNode(n,os); - os << std::endl; os <<" "; - ((MethodDesc*)n->refObj)->printFullName(os); - } - } - os << std::endl; - os << " =="; ((Opnd*)(*it)->refObj)->getInst()->print(os); - os << std::endl; - } - } - os << "================ > " ; - irManager.getMethodDesc().printFullName(os); - os << std::endl; -} // printCreatedObjectsInfo(::std::ostream& os) - - -void -EscAnalyzer::scanCnGNodeRefsGE(CnGNode* cgn, bool check_var_src, bool check_field_elem) { +EscAnalyzer::scanCnGNodeRefsGE(CnGNode* cgn, bool check_var_src) { CnGEdges::iterator it; CnGRefs::iterator it1; CnGNode* next_node; @@ -2598,12 +1890,11 @@ #ifdef _DEBUG if (_setState) { - Log::out() <<"--scanGE 1: node "<cngNodeId - <<" opndId "<opndId<<" state "; + Log::out() <<"--scanGE 1: nodeId "<cngNodeId + <<" opId "<opndId<<" state "; printState(cgn); Log::out() <<" " << nodeTypeToString(cgn) <nodeType - <<" check_var_src " << check_var_src - <<" check_field_elem " << check_field_elem << std::endl; + <<" check_var_src " << check_var_src << std::endl; } #endif if (cgn->nodeType == NT_LDVAL) { @@ -2629,8 +1920,8 @@ if (getEscState(cgn) > GLOBAL_ESCAPE) { #ifdef _DEBUG if (_setState) { - Log::out() <<"--scanGE 2: node " - <cngNodeId<<" opndId "<opndId <<" state "; + Log::out() <<"--scanGE 2: nodeId " + <cngNodeId<<" opId "<opndId <<" state "; printState(cgn); Log::out() <<" to gl.esc."<< std::endl; Log::out() <<"--scanGE 2: "<< nodeTypeToString(cgn) @@ -2644,8 +1935,8 @@ if (getCalleeEscaped(cgn) == 0) { #ifdef _DEBUG if (_setState) { - Log::out() <<"--scanGE 3: node " - <cngNodeId<<" opndId "<opndId <<" state "; + Log::out() <<"--scanGE 3: nodeId " + <cngNodeId<<" opId "<opndId <<" state "; printState(cgn); Log::out() <<" to callee.esc."<< std::endl; Log::out() <<"--scanGE 3: "<< nodeTypeToString(cgn) @@ -2660,8 +1951,8 @@ if (getCalleeEscaped(cgn) == 0) { #ifdef _DEBUG if (_setState) { - Log::out() <<"--scanGE 4: node " - <cngNodeId<<" opndId "<opndId <<" state "; + Log::out() <<"--scanGE 4: nodeId " + <cngNodeId<<" opId "<opndId <<" state "; printState(cgn); Log::out() <<" to callee.esc."<< std::endl; Log::out() <<"--scanGE 4: "<< nodeTypeToString(cgn) @@ -2676,9 +1967,6 @@ scObjs->push_back(cgn->cngNodeId); if (cgn->outEdges != NULL) { bool to_check_var_src = check_var_src; - bool to_check_field_elem = check_field_elem; - if (cgn->nodeType!=NT_INSTFLD && cgn->nodeType!=NT_ARRELEM) - to_check_field_elem = true; for (it1 = cgn->outEdges->begin( ); it1 != cgn->outEdges->end( ); it1++ ) { next_node = (*it1)->cngNodeTo; if (next_node->nodeType == NT_LDOBJ) @@ -2686,16 +1974,16 @@ to_check_var_src = true; #ifdef _DEBUG if (_setState) { - Log::out() <<"--scanGE 5 next: node " - <cngNodeId<<" opndId "<opndId <<" state "; + Log::out() <<"--scanGE 5 next: nodeId " + <cngNodeId<<" opId "<opndId <<" state "; printState(next_node); Log::out() << std::endl; } #endif - scanCnGNodeRefsGE(next_node,to_check_var_src,to_check_field_elem); + scanCnGNodeRefsGE(next_node,to_check_var_src); #ifdef _DEBUG if (_setState) { Log::out() <<"--scanGE ret 1 for node: " << next_node->cngNodeId - <<" opndId " << next_node->opndId << std::endl; + <<" opId " << next_node->opndId << std::endl; } #endif if ((*it1)->edgeType!=ET_POINT) @@ -2709,8 +1997,8 @@ next_node = findCnGNode_op(cgn->nInst->getSrc(i)->getId()); #ifdef _DEBUG if (_setState) { - Log::out() <<"--scanGE 6 next: node " - <cngNodeId<<" opndId "<opndId <<" state "; + Log::out() <<"--scanGE 6 next: nodeId " + <cngNodeId<<" opId "<opndId <<" state "; printState(next_node); Log::out() << std::endl; } #endif @@ -2718,7 +2006,7 @@ #ifdef _DEBUG if (_setState) { Log::out() <<"--scanGE ret 2 for node: " << next_node->cngNodeId - <<" opndId " << next_node->opndId << std::endl; + <<" opId " << next_node->opndId << std::endl; } #endif } @@ -2726,106 +2014,15 @@ } #ifdef _DEBUG if (_setState) { - Log::out()<<"--scanGE: nscan "<opndId<opndId<nodeType==NT_ARRELEM && !check_field_elem) { - Inst* inst_ldbase = cgn->nInst; - if (inst_ldbase->getOpcode()==Op_AddScaledIndex) - inst_ldbase = ((Opnd*)(cgn->refObj))->getInst()->getSrc(0)->getInst(); - CnGNode* cgnode=findCnGNode_op(inst_ldbase->getSrc(0)->getId()); -#ifdef _DEBUG - if (_setState) { - Log::out() <<"--scanGE 7 arrElem: "; - inst_ldbase->print(Log::out()); - Log::out() << std::endl; - Log::out() <<"--scanGE 7 next: " << cgnode->cngNodeId << " - " - << cgnode->opndId << std::endl; - } -#endif - // if some array element is escaped, then all array elements are escaped - if (cgnode->outEdges != NULL) { - for (it1 = cgnode->outEdges->begin( ); it1 != cgnode->outEdges->end( ); it1++ ) { - next_node = (*it1)->cngNodeTo; -#ifdef _DEBUG - if (_setState) { - Log::out() <<"--scanGE 7 next arrElem: node " - <cngNodeId<<" opndId "<opndId <<" state "; - printState(next_node); Log::out() << std::endl; - } -#endif - scanCnGNodeRefsGE(next_node,check_var_src,false); -#ifdef _DEBUG - if (_setState) { - Log::out() <<"--scanGE ret 3 for node: " << next_node->cngNodeId - <<" opndId " << next_node->opndId << std::endl; - } -#endif - } - } - } - if (cgn->nodeType==NT_LDOBJ && check_field_elem) { - Inst* ldinst =((Opnd*)(cgn->refObj))->getInst(); - if (ldinst->getOpcode()==Op_TauLdInd) { //tttt - Inst* inst_fldaddr= ldinst->getSrc(0)->getInst(); - if (inst_fldaddr->getOpcode()==Op_LdFieldAddr) { - CnGNode* cgnode=findCnGNode_fl(inst_fldaddr,NT_INSTFLD); -#ifdef _DEBUG - if (_setState) { - Log::out() << "--scanGE 8 TO FIND 1 for opnd " - << cgn->opndId << std::endl; - ldinst->print(Log::out()); - Log::out() << std::endl; - inst_fldaddr->print(Log::out()); - Log::out() << std::endl; - Log::out() << cgn->cngNodeId << "-" - << cgn->opndId << " -> "; - Log::out() << cgnode->cngNodeId << "-" - << cgnode->opndId << std::endl; - } -#endif - scanCnGNodeRefsGE(cgnode,check_var_src,false); -#ifdef _DEBUG - if (_setState) { - Log::out() <<"--scanGE ret 4 for node: " << cgnode->cngNodeId - <<" opndId " << cgnode->opndId << std::endl; - } -#endif - } else { - uint32 oc = inst_fldaddr->getOpcode(); - if (oc==Op_AddScaledIndex || oc == Op_LdArrayBaseAddr) { - CnGNode* cgnode=findCnGNode_op(ldinst->getSrc(0)->getId()); -#ifdef _DEBUG - if (_setState) { - Log::out() << "--scanGE 8 TO FIND 2 for opnd " - << cgn->opndId << std::endl; - ldinst->print(Log::out()); - Log::out() << std::endl; - inst_fldaddr->print(Log::out()); - Log::out() << std::endl; - Log::out() << cgn->cngNodeId << "-" - << cgn->opndId << " -> "; - Log::out() << cgnode->cngNodeId << "-" - << cgnode->opndId << std::endl; - } -#endif - scanCnGNodeRefsGE(cgnode,check_var_src,false); -#ifdef _DEBUG - if (_setState) { - Log::out() <<"--scanGE ret 5 for node: " << cgnode->cngNodeId - <<" opndId " << cgnode->opndId << std::endl; - } -#endif - } - } - } - } -} // scanCnGNodeRefsGE(CnGNode* cgn, bool check_var_src, bool check_field_elem) +} // scanCnGNodeRefsGE(CnGNode* cgn, bool check_var_src) void -EscAnalyzer::scanCnGNodeRefsAE(CnGNode* cgn, bool check_var_src, bool check_field_elem) { +EscAnalyzer::scanCnGNodeRefsAE(CnGNode* cgn, bool check_var_src) { CnGEdges::iterator it; CnGRefs::iterator it1; CnGNode* next_node; @@ -2835,12 +2032,11 @@ #ifdef _DEBUG if (_setState) { - Log::out() <<"--scanAE < 1: node "<cngNodeId - <<" opndId "<opndId<<" state "; + Log::out() <<"--scanAE < 1: nodeId "<cngNodeId + <<" opId "<opndId<<" state "; printState(cgn); Log::out() <<" " << nodeTypeToString(cgn) <nodeType - <<" check_var_src " << check_var_src - <<" check_field_elem " << check_field_elem << std::endl; + <<" check_var_src " << check_var_src << std::endl; } #endif if (cgn->nodeType == NT_LDVAL) { // primitive type value @@ -2870,21 +2066,20 @@ return; } if (cgn->nodeType&NT_OBJS) { -// if (cgn->nodeMDs!=NULL && check_field_elem) { - if (cgn->nodeMDs!=NULL) { + if (cgn->nodeMDs!=NULL && curMDNode!=0) { cgn->nodeMDs->push_back(curMDNode); #ifdef _DEBUG if (_setState) { - Log::out() <<"--scanAE 1_1: node "<cngNodeId - <<" opndId "<opndId <<" curMDNode "<cngNodeId + <<" opId "<opndId <<" curMDNode "< ARG_ESCAPE) { #ifdef _DEBUG if (_setState) { - Log::out() <<"--scanAE 2: node "<cngNodeId - <<" opndId "<opndId<<" state "; + Log::out() <<"--scanAE 2: nodeId "<cngNodeId + <<" opId "<opndId<<" state "; printState(cgn); Log::out() <<" to arg.esc."<< std::endl; } @@ -2892,19 +2087,15 @@ setEscState(cgn,ARG_ESCAPE); } } -// scannedObjs->push_back(cgn->cngNodeId); scObjs->push_back(cgn->cngNodeId); if (cgn->outEdges != NULL) { bool to_check_var_src = check_var_src; - bool to_check_field_elem = check_field_elem; - if (cgn->nodeType!=NT_INSTFLD && cgn->nodeType!=NT_ARRELEM) - to_check_field_elem = true; for (it1 = cgn->outEdges->begin( ); it1 != cgn->outEdges->end( ); it1++ ) { next_node = (*it1)->cngNodeTo; #ifdef _DEBUG if (_setState) { - Log::out() <<"--scanAE 3 next: node " - <cngNodeId<<" opndId "<opndId <<" state "; + Log::out() <<"--scanAE 3 next: nodeId " + <cngNodeId<<" opId "<opndId <<" state "; printState(next_node); Log::out() << " " << nodeTypeToString(next_node) << " ref.type " << next_node->nodeRefType << std::endl; @@ -2915,7 +2106,7 @@ if (next_node->nodeType == NT_LDOBJ) if (next_node->nInst->getOpcode()==Op_LdVar && cgn->nodeType!=NT_VARVAL) to_check_var_src = true; - scanCnGNodeRefsAE(next_node,to_check_var_src,to_check_field_elem); + scanCnGNodeRefsAE(next_node,to_check_var_src); if ((*it1)->edgeType!=ET_POINT) nscan++; } @@ -2927,8 +2118,8 @@ next_node = findCnGNode_op(cgn->nInst->getSrc(i)->getId()); #ifdef _DEBUG if (_setState) { - Log::out() <<"--scanAE 4 next: node " - <cngNodeId<<" opndId "<opndId <<" state "; + Log::out() <<"--scanAE 4 next: nodeId " + <cngNodeId<<" opId "<opndId <<" state "; printState(next_node); Log::out() << std::endl; } #endif @@ -2936,95 +2127,614 @@ } } } - if (cgn->nodeType==NT_ARRELEM && check_field_elem) { - Inst* inst_addindex = ((Opnd*)(cgn->refObj))->getInst(); - Inst* inst_ldbase = inst_addindex->getSrc(0)->getInst(); - if (inst_addindex->getOpcode() == Op_LdArrayBaseAddr) - inst_ldbase = inst_addindex; - CnGNode* cgnode=findCnGNode_op(inst_ldbase->getSrc(0)->getId()); + #ifdef _DEBUG + if (_setState) { + Log::out() <<"--scanAE > 4: exit: nodeId "<cngNodeId + <<" opId "<opndId<<" state "; printState(cgn); + Log::out() <<" " << nodeTypeToString(cgn) <nodeType + <<" check_var_src " << check_var_src << std::endl; + } +#endif +} // scanCnGNodeRefsAE(CnGNode* cgn, bool check_var_src) + + +void +EscAnalyzer::checkSubobjectStates(CnGNode* node) { + CnGRefs::iterator it; + CnGNode* cgn; + CnGNode* cgn1; + bool arge = false; + bool calle = false; + bool gle = false; + bool no_mod = false; + Inst* n_inst = node->nInst;; + CnGNode* nt = node; + +#ifdef _DEBUG + if (_setState) { + Log::out() <<"--checkSOS 0: "; + printCnGNode(node,Log::out());Log::out() << std::endl; + } +#endif + if (scannedSucNodes->size()!=0) { + if (checkScannedSucNodes(node->cngNodeId)) { +#ifdef _DEBUG + if (_setState) { + Log::out() <<"--checkSOS ... : return " << std::endl; + } +#endif + return; + } + } + if (node->outEdges==NULL) { +#ifdef _DEBUG if (_setState) { - Log::out() <<"--scanAE 5 check1: "; - inst_ldbase->print(Log::out()); - Log::out() << std::endl; - Log::out() <<"--scanAE 5 check2: "; - if (cgnode==NULL) - Log::out() <<"cngnode==null "<< std::endl; - Log::out() <<"--scanAE 5 next: " << cgnode->cngNodeId << " - " - << cgnode->opndId << std::endl; + Log::out() <<"--checkSOS 1: return " << std::endl; } #endif - if (cgnode->outEdges != NULL) { - for (it1 = cgnode->outEdges->begin( ); it1 != cgnode->outEdges->end( ); it1++ ) { - next_node = (*it1)->cngNodeTo; + return; + } + + for (it = node->outEdges->begin( ); it != node->outEdges->end( ); it++ ) { + cgn = (*it)->cngNodeTo; #ifdef _DEBUG - if (_setState) { - Log::out() <<"--scanAE 5 next arrElem: node " - <cngNodeId<<" opndId "<opndId <<" state "; - printState(next_node); Log::out() << std::endl; - } + if (_setState) { + Log::out() <<"--checkSOS 2: "; + printCnGNode(cgn,Log::out());Log::out() << std::endl; + } #endif - scanCnGNodeRefsAE(next_node,check_var_src,false); + if (getEscState(cgn) < getEscState(node)) { + if (getEscState(cgn)==GLOBAL_ESCAPE) { + gle = true; + break; } + if (getEscState(cgn)==ARG_ESCAPE) { + arge = true; + continue; + } } - } - if (cgn->nodeType==NT_LDOBJ && check_field_elem) { - Inst* ldinst =((Opnd*)(cgn->refObj))->getInst(); - if (ldinst->getOpcode()==Op_TauLdInd) { - Inst* inst_fldaddr= ldinst->getSrc(0)->getInst(); - if (inst_fldaddr->getOpcode()==Op_LdFieldAddr) { - CnGNode* cgnode=findCnGNode_fl(inst_fldaddr,NT_INSTFLD); + if (getCalleeEscaped(node) == 0 && getCalleeEscaped(cgn) != 0) { + calle = true; + continue; + } + no_mod = true; + } #ifdef _DEBUG + if (_setState) { + Log::out() <<"--checkSOS 2: " << no_mod << " " << gle << " " << calle << " " << arge + << std::endl; + } +#endif + + if (gle || calle || arge) { + if (node->nodeType==NT_ARRELEM) { + if (n_inst->getOpcode() == Op_AddScaledIndex) { + n_inst = n_inst->getSrc(0)->getInst(); + nt = findCnGNode_op(n_inst->getSrc(0)->getId()); +#ifdef _DEBUG if (_setState) { - Log::out() <<"--scanAE 6 TO FIND 1 for opnd " - << cgn->opndId << std::endl; - ldinst->print(Log::out()); - Log::out() << std::endl; - inst_fldaddr->print(Log::out()); - Log::out() << std::endl; - Log::out() << cgn->cngNodeId << "-" - << cgn->opndId << " -> "; - Log::out() << cgnode->cngNodeId << "-" - << cgnode->opndId << std::endl; + Log::out() <<"--checkSOS 3: "; printCnGNode(nt,Log::out()); Log::out() << std::endl; } #endif - scanCnGNodeRefsAE(cgnode,check_var_src,false); - } else { - uint32 oc = inst_fldaddr->getOpcode(); - if (oc==Op_AddScaledIndex || oc == Op_LdArrayBaseAddr) { - CnGNode* cgnode=findCnGNode_op(ldinst->getSrc(0)->getId()); + if (nt->lNode != NULL) { + nt = nt->lNode; + } + } + } #ifdef _DEBUG - if (_setState) { - Log::out() << "--scanAE 6 TO FIND 2 for opnd " - << cgn->opndId << std::endl; - ldinst->print(Log::out()); - Log::out() << std::endl; - inst_fldaddr->print(Log::out()); - Log::out() << std::endl; - Log::out() << cgn->cngNodeId << "-" - << cgn->opndId << " -> "; - Log::out() << cgnode->cngNodeId << "-" - << cgnode->opndId << std::endl; - } + if (_setState) { + Log::out() <<"--checkSOS 4: found "; + printCnGNode(nt,Log::out());Log::out() << std::endl; + } #endif - scanCnGNodeRefsAE(cgnode,check_var_src,false); - } + if (gle) { + initNodeType = NT_STFLD; + } else { + if (calle) { + initNodeType = NT_DEFARG; + } else { + initNodeType = NT_ACTARG; } } + for (it = nt->outEdges->begin( ); it != nt->outEdges->end( ); it++ ) { + cgn1 = (*it)->cngNodeTo; + if (gle || calle) { + scanCnGNodeRefsGE((*it)->cngNodeTo,false); + } else { + curMDNode = 0; + scanCnGNodeRefsAE((*it)->cngNodeTo,false); + } + } } + if (!no_mod && gle && !calle && !arge) { #ifdef _DEBUG + if (_setState) { + Log::out() <<"--checkSOS 5: return " << std::endl; + } +#endif + return; + } + scannedSucNodes->push_back(node->cngNodeId); if (_setState) { - Log::out() <<"--scanAE > 4: exit: node "<cngNodeId - <<" opndId "<opndId<<" state "; printState(cgn); - Log::out() <<" " << nodeTypeToString(cgn) <nodeType - <<" check_var_src " << check_var_src - <<" check_field_elem " << check_field_elem << std::endl; + Log::out() <<"--checkSOS 6: added " << node->cngNodeId << std::endl; } + for (it = node->outEdges->begin( ); it != node->outEdges->end( ); it++ ) { + cgn = (*it)->cngNodeTo; + + checkSubobjectStates(cgn); + } +} // checkSubobjectStates(CnGNode* node) + + +uint32 +EscAnalyzer::getSubobjectStates(CnGNode* node) { + uint32 st = NO_ESCAPE, rs; + CnGRefs::iterator it; + CnGNode* cgn; + + if (scannedObjs->size()!=0) { + if (checkScannedObjs(node->cngNodeId)) + return st; + } + if (node->outEdges==NULL) + return st; + for (it = node->outEdges->begin( ); it != node->outEdges->end( ); it++ ) { + cgn = (*it)->cngNodeTo; +#ifdef _DEBUG + if (_setState) { + Log::out() <<"--getSOS : node " + <cngNodeId<<" opndId "<opndId <<" state "; + printState(cgn); + Log::out() << std::endl; + } #endif -} // scanCnGNodeRefsAE(CnGNode* cgn, bool check_var_src, bool check_field_elem) + if (st > getEscState(cgn)) + st = getEscState(cgn); + if (st == GLOBAL_ESCAPE) + return st; + scannedObjs->push_back(node->cngNodeId); + rs = getSubobjectStates(cgn); + scannedObjs->pop_back(); + if (st > rs) + st = rs; + if (st == GLOBAL_ESCAPE) + return st; + } + return st; +} // getSubobjectStates(CnGNode* node) +EscAnalyzer::CalleeMethodInfo* +EscAnalyzer::findMethodInfo(MethodDesc* mdesc,Inst* callInst) { + const char* ch1 = mdesc->getParentType()->getName(); + const char* ch2 = mdesc->getName(); + const char* ch3 = mdesc->getSignatureString(); + CalleeMethodInfo* mtdInfo = getMethodInfo(ch1,ch2,ch3); + if (mtdInfo == NULL) { +#ifdef _DEBUG + if (_scanMtds==1) { + Log::out() << " = = = = = = = = To scan method " << std::endl; + mdesc->printFullName(Log::out()); + Log::out() << std::endl; + callInst->print(Log::out()); + Log::out() << std::endl; + } +#endif + if (method_ea_level < maxMethodExamLevel) { + scanCalleeMethod(callInst); + mtdInfo=getMethodInfo(ch1,ch2,ch3); + } + } + return mtdInfo; +} // findMethodInfo(MethodDesc* mdesc) + + +EscAnalyzer::CalleeMethodInfo* +EscAnalyzer::getMethodInfo(const char* ch1,const char* ch2,const char* ch3) { + CalleeMethodInfos::iterator it; + if (calleeMethodInfos==NULL) + return NULL; + for (it = calleeMethodInfos->begin( ); it != calleeMethodInfos->end( ); it++ ) { + const char* c1 = (*it)->methodIdent->parentName; + const char* c2 = (*it)->methodIdent->name; + const char* c3 = (*it)->methodIdent->signature; + if (strcmp(c1,ch1)==0 && strcmp(c2,ch2)==0 && strcmp(c3,ch3)==0) + return (*it); + } + return NULL; +} // getMethodInfo(const char* ch1,const char* ch2,const char* ch3) + + void +EscAnalyzer::scanCalleeMethod(Inst* call) { + MethodDesc* methodDesc = 0; + +#ifdef _DEBUG + if (_scanMtds==1) { + Log::out() << "=="; + call->print(Log::out()); + Log::out() << std::endl; + } +#endif + if (call == NULL) { // scanned Op_DirectCall, not scanned Op_IndirectMemoryCall + Log::out() << "scanMethod: NULL" << std::endl; + return; + } + methodDesc = call->asMethodCallInst()->getMethodDesc(); + +#ifdef _DEBUG + if (_scanMtds==1) { + Log::out() << std::endl; + Log::out() << "scanMethod: " << methodDesc->getParentType()->getName() + << "." << methodDesc->getName() << methodDesc->getSignatureString() + << " " << methodDesc << std::endl; + Log::out() << " NumParams: " + << methodDesc->getNumParams()<< std::endl; + Log::out() << " isNative: " << methodDesc->isNative() << std::endl; + Log::out() << " isStatic: " << methodDesc->isStatic() << std::endl; + Log::out() << " isInstance: " << methodDesc->isInstance() << std::endl; + Log::out() << " isFinal: " << methodDesc->isFinal() << std::endl; + Log::out() << " isVirtual: " << methodDesc->isVirtual() << std::endl; + Log::out() << " isAbstract: " << methodDesc->isAbstract() << std::endl; + Log::out() << " isInstanceInitializer: " + << methodDesc->isInstanceInitializer() << std::endl; + Log::out() << " isOverridden: " << methodDesc->isOverridden() << std::endl; + } +#endif + + OpndManager& _opndManager(irManager.getOpndManager()); + Opnd *returnOpnd = 0; + if(call->getDst()->isNull()) + returnOpnd = _opndManager.getNullOpnd(); + else + returnOpnd = _opndManager.createSsaTmpOpnd(call->getDst()->getType()); + + IRManager* inlinedIRM = new (eaMemManager) IRManager(irManager.getMemoryManager(), irManager, *methodDesc, returnOpnd); + CompilationInterface& ci= inlinedIRM->getCompilationInterface(); + bool cibcmap = ci.isBCMapInfoRequired(); + if (cibcmap) { + ci.setBCMapInfoRequired(false); + } + + { + CompilationContext inlineCC(irManager.getMemoryManager(), &ci, ci.getCompilationContext()); + inlineCC.setHIRManager(inlinedIRM); + runTranslatorSession(inlineCC); + } + + optimizeTranslatedCode(*inlinedIRM); + + EscAnalyzer ea1(this, *inlinedIRM); + ea1.doAnalysis(); + + if (cibcmap) { + ci.setBCMapInfoRequired(true); + } +} // scanCalleeMethod(Inst* call) + + +void EscAnalyzer::runTranslatorSession(CompilationContext& inlineCC) { + TranslatorSession* traSession = (TranslatorSession*)translatorAction->createSession(inlineCC.getCompilationLevelMemoryManager()); + traSession->setCompilationContext(&inlineCC); + inlineCC.setCurrentSessionAction(traSession); + traSession->run(); + inlineCC.setCurrentSessionAction(NULL); +} + + +void +EscAnalyzer::optimizeTranslatedCode(IRManager& irm) { + // run ssa pass + OptPass::computeDominators(irm); + DominatorTree* dominatorTree = irm.getDominatorTree(); + ControlFlowGraph& flowGraph = irm.getFlowGraph(); + + DomFrontier frontier(irm.getNestedMemoryManager(),*dominatorTree,&flowGraph); + SSABuilder ssaBuilder(irm.getOpndManager(),irm.getInstFactory(),frontier,&flowGraph, + irm.getOptimizerFlags()); + ssaBuilder.convertSSA(irm.getMethodDesc()); + irm.setInSsa(true); + irm.setSsaUpdated(); + + // run devirt pass +// Devirtualizer pass(irm); +// pass.guardCallsInRegion(irm, dominatorTree); + +} // optimizeTranslatedCode(IRManager& irManager) + + +void +EscAnalyzer::saveScannedMethodInfo() { + CnGNodes::iterator it; + MethodDesc* mdesc = &irManager.getMethodDesc(); + MemoryManager& globalMM = irManager.getCurrentJITContext()->getGlobalMemoryManager(); +// MemoryManager& globalMM = eaMemManager; + const char* ch1 = mdesc->getParentType()->getName(); + const char* ch2 = mdesc->getName(); + const char* ch3 = mdesc->getSignatureString(); + if (calleeMethodInfos==NULL) { +//std::cout<< "*1****** lock "<parentName=mpname; + mident->name=mname; + mident->signature=msig; + minfo->methodIdent=mident; + uint32 numpar = mdesc->getNumParams(); + minfo->numberOfArgs=numpar; + ParamInfos* prminfos = new (globalMM) ParamInfos(globalMM); + minfo->paramInfos=prminfos; + minfo->retValueState=0; + if (mdesc->getReturnType()->isReference()) { + uint32 escstate = 3, bitstate = 0; + for (it = cngNodes->begin( ); it != cngNodes->end( ); it++) { + if ((*it)->nodeType==NT_EXITVAL) { + bitstate = bitstate|getCalleeEscaped(*it); + if (escstate > getEscState(*it)) + escstate=getEscState(*it); + } + } + minfo->retValueState=escstate|bitstate; + } + bool pmt = checkMonitorsOnThis(); + minfo->mon_on_this = pmt; + for (it = cngNodes->begin( ); it != cngNodes->end( ); it++) { + if ((*it)->nodeType==NT_DEFARG) { + ParamInfo* prminfo = new (globalMM) ParamInfo; + prminfo->state=getFullState(*it); + prminfo->paramNumber=(*it)->argNumber; + prminfos->push_back(prminfo); + } + } + calleeMethodInfos->push_back(minfo); +//std::cout<< "*2****** unlock "<methodIdent->parentName << " "; + Log::out() << minfo->methodIdent->name << " "; + Log::out() << minfo->methodIdent->signature << " "; + Log::out() << minfo->numberOfArgs<< " " << std::endl; + for (it2 = minfo->paramInfos->begin( ); it2 != minfo->paramInfos->end( ); it2++) { + Log::out() << (*it2)->paramNumber << " st." + << (*it2)->state << std::endl; + } + Log::out() << "==== end ===== calleeMethodInfo " << std::endl; + } +#endif +} // saveScannedMethodInfo(MemoryManager& mm) + + +/** + * Finds specified parameter in specified method info. + * Returns: + * state - for existent parameter, + * 0 - for another cases. + */ +uint32 +EscAnalyzer::getMethodParamState(CalleeMethodInfo* mi, uint32 np) { + ParamInfos::iterator it; + uint32 st = 0; + if (mi==NULL) + return 0; + for (it = mi->paramInfos->begin( ); it != mi->paramInfos->end( ); it++) { + if ((*it)->paramNumber == np) { + st = (*it)->state; + return st; + } + } + return st; +} // getMethodParamState(CalleeMethodInfo* mi, uint32 np) + + +void +EscAnalyzer::markNotEscInsts() { + CnGNodes::iterator it; + bool p2 = false; + StlMap nonEscInsts(eaMemManager); + typedef ::std::pair intPair; + + for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { + if ((*it)->nodeType == NT_OBJECT && getEscState(*it) > GLOBAL_ESCAPE) { + nonEscInsts.insert(intPair((*it)->instrId,getFullState(*it))); + } + } + if (p2 && Log::isEnabled()) { + Log::out() << "================ > "; + irManager.getMethodDesc().printFullName(Log::out()); + Log::out() << std::endl; + } +} // markNotEscInsts() + + +void +EscAnalyzer::eaFixupVars(IRManager& irm) { + OptPass::computeDominators(irm); + DominatorTree* dominatorTree = irm.getDominatorTree(); + ControlFlowGraph& flowGraph = irm.getFlowGraph(); + + DomFrontier frontier(irm.getNestedMemoryManager(),*dominatorTree,&flowGraph); + SSABuilder ssaBuilder(irm.getOpndManager(),irm.getInstFactory(),frontier,&flowGraph, irm.getOptimizerFlags()); + bool phiInserted = ssaBuilder.fixupVars(&irm.getFlowGraph(), irm.getMethodDesc()); + irm.setInSsa(true); + if (phiInserted) + irm.setSsaUpdated(); +} + + +void +EscAnalyzer::printCnGNodes(char* text,::std::ostream& os) { + CnGNodes::const_iterator it; + FieldDesc* fd; + std::string t1; + std::string t2; + os << " "<< text << std::endl; + for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { + os <<" "; + printCnGNode(*it,os); + os << std::endl; + os << " "; + if ((*it)->nodeType & (NT_OBJS|NT_EXITVAL|NT_LDVAL)) { //node of created or exit object + ((Opnd*)(*it)->refObj)->printWithType(os); + } + if ((*it)->nodeType == NT_RETVAL) { + os << std::endl; os << " "; + Inst* inst = ((Opnd*)(*it)->refObj)->getInst(); + inst->print(os); + if (inst->getOpcode()==Op_IndirectMemoryCall) { + MethodDesc* md; + if (inst->getSrc(0)->getInst()->getOpcode()== Op_LdVar) { + md = inst->getSrc(0)->getType()->asMethodPtrType()->getMethodDesc(); + } else { + md = inst->getSrc(0)->getInst()->asMethodInst()->getMethodDesc(); + } + os << std::endl; os << " "; + md->printFullName(os); + } + } + if ((*it)->nodeType & NT_ACTARG) { //node of actual method parameter + os << ((MethodDesc*)(*it)->refObj)->getParentType()->getName() << "::"; + os << ((MethodDesc*)(*it)->refObj)->getName() << std::endl; + os << " "; + os << ((MethodDesc*)(*it)->refObj)->getParamType((*it)->opndId)->getName(); + } + if ((*it)->nodeType & NT_STFLD) { //field node + fd = ((Inst*)(*it)->refObj)->asFieldAccessInst()->getFieldDesc(); + os << fd->getParentType()->getName() << "::"<< fd->getName() << std::endl; + os << " "<getFieldType()->getName(); + } + os << std::endl; + } +} // printCnGNodes(char* text,::std::ostream& os) + + +void +EscAnalyzer::printCnGNode(CnGNode* cgn,::std::ostream& os) { + std::string t2; + + os << "nodeId "<cngNodeId<<" "; + if (cgn->nodeType & (NT_OBJS|NT_LDVAL)) { //node of object created in the method + os << "opId "<opndId<<" "; + } else { + if (cgn->nodeType & NT_ACTARG) { //node of actual method parameter + os << "nArg "<argNumber<<" "; + os << "method "<refObj<<" "; + } + } + if (cgn->nodeType==NT_DEFARG) + os << " nArg "<argNumber<<" "; //Arg number for defarg + os << " inst "<instrId<<" ("<nodeType<<", "; + switch (cgn->nodeRefType) { + case NR_PRIM : t2="Prim-"; break; + case NR_REF : t2="Ref -"; break; + case NR_ARR : t2="Arr -"; break; + case NR_REFARR : t2="RArr-"; break; + default : t2=" -"; + } + os <nodeRefType<<") "; + if (cgn->lNode) { + os << "( " << cgn->lNode->cngNodeId << "-" << cgn->lNode->opndId << " ) "; + } + os << "st. "; + printState(cgn,os); os << " "; +} // printCnGNode(CnGNode* cgn,::std::ostream& os) + + +std::string +EscAnalyzer::nodeTypeToString(CnGNode* cgn) { + std::string t1; + switch (cgn->nodeType) { + case NT_OBJECT : t1="Obj -"; break; + case NT_DEFARG : t1="DArg-"; break; + case NT_RETVAL : t1="RVal-"; break; + case NT_CATCHVAL: t1="CVal-"; break; + case NT_STFLD : t1="SFld-"; break; + case NT_INSTFLD : t1="IFld-"; break; + case NT_LDOBJ : t1="LObj-"; break; + case NT_INTPTR : t1="IPtr-"; break; + case NT_VARVAL : t1="VVal-"; break; + case NT_ARRELEM : t1="ArEl-"; break; + case NT_REF : t1="REF -"; break; + case NT_ACTARG : t1="AArg-"; break; + case NT_EXITVAL : t1="EVal-"; break; + case NT_THRVAL : t1="TVal-"; break; + case NT_LDVAL : t1="LVal-"; break; + default : t1=" -"; + } + return t1; +} // nodeTypeToString(CnGNode* cgn) + + +void +EscAnalyzer::printCnGEdges(char* text,::std::ostream& os) { + CnGEdges* cge = cngEdges; + CnGEdges::iterator it; + CnGRefs::iterator it1; + os << " "<< text << std::endl; + if (cge==NULL) { + os <<" NULL"<< std::endl; + return; + } + for (it = cge->begin( ); it != cge->end( ); it++ ) { + os << " from "; + printCnGNode((*it)->cngNodeFrom,os); + os << " to " << std::endl; + for (it1 = (*it)->refList->begin( ); it1 != (*it)->refList->end( ); it1++ ) { + os << " "; + os <<(*it1)->cngNodeTo->cngNodeId<<" ("; + os <edgeType<<"), "; + printCnGNode(findCnGNode_id((*it1)->cngNodeTo->cngNodeId),os); + os << std::endl; + } + } +} // printCnGEdges(char* text,::std::ostream& os) + + +std::string +EscAnalyzer::edgeTypeToString(CnGRef* edr) { + std::string t1; + switch (edr->edgeType) { + case ET_POINT : t1="poi-"; break; + case ET_DEFER : t1="ref-"; break; + case ET_FIELD : t1="fld-"; break; + default : t1=" -"; + } + return t1; +} // edgeTypeToString(CnGRef* edr) + + +void EscAnalyzer::printRefInfo(::std::ostream& os) { CnGNodes::iterator it; os << "================ Static Fields" << std::endl; @@ -3066,6 +2776,426 @@ void +EscAnalyzer::printCnGNodeRefs(CnGNode* cgn, std::string text,::std::ostream& os) { + CnGNode* node; + CnGRefs::iterator it1; + Inst* inst; + os << text; + if (scannedObjs->size()!=0) { + if (checkScannedObjs(cgn->cngNodeId)) { + os << "nodeId " << cgn->cngNodeId << " . . . " << std::endl; + return; + } + } + printCnGNode(cgn,os); + os << std::endl; + os << text; cgn->nInst->print(os); os << std::endl; + scannedObjs->push_back(cgn->cngNodeId); + if (cgn->outEdges != NULL) { + for (it1 = cgn->outEdges->begin( ); it1 != cgn->outEdges->end( ); it1++ ) { + os << text << edgeTypeToString(*it1) << std::endl; + if ((node=findCnGNode_id((*it1)->cngNodeTo->cngNodeId))!=NULL) + printCnGNodeRefs(node,text+" ",os); + } + } + scannedObjs->pop_back(); + if (cgn->nodeType==NT_RETVAL) { + inst = cgn->nInst; + if (inst->getOpcode()==Op_IndirectMemoryCall) { + MethodDesc* md; + if (inst->getSrc(0)->getInst()->getOpcode()== Op_LdVar) { + md = inst->getSrc(0)->getType()->asMethodPtrType()->getMethodDesc(); + } else { + md = inst->getSrc(0)->getInst()->asMethodInst()->getMethodDesc(); + } + os << text << " "; + md->printFullName(os); os << std::endl; + } + } + if (cgn->nodeType==NT_LDOBJ && getEscState(cgn)!=GLOBAL_ESCAPE) { + inst = cgn->nInst; + lObjectHistory(inst,text,os); + scannedInsts->clear(); + } +} // printCnGNodeRefs(CnGNode* cgn, std::string text,::std::ostream& os) + + +void +EscAnalyzer::lObjectHistory(Inst* inst,std::string text,::std::ostream& os) { + Inst* inst1; + uint32 nsrc=inst->getNumSrcOperands(); + + if (scannedInsts->size()!=0) { + if (checkScannedInsts(inst->getId())) { + os << text << "instId " << inst->getId() << " . . . " << std::endl; + return; + } + } + os << text; inst->print(os); os << std::endl; + if (inst->getOpcode()==Op_DirectCall || inst->getOpcode()==Op_IndirectMemoryCall) { + Opnd *returnOpnd = inst->getDst(); + if (returnOpnd != NULL) { + CnGNode* n = findCnGNode_op(returnOpnd->getId()); + if (n != NULL) { + os<< text << " "; printCnGNode(n,os); os<< std::endl; + } + } + if (inst->getOpcode()==Op_IndirectMemoryCall) { + MethodDesc* md; + if (inst->getSrc(0)->getInst()->getOpcode()== Op_LdVar) { + md = inst->getSrc(0)->getType()->asMethodPtrType()->getMethodDesc(); + } else { + md = inst->getSrc(0)->getInst()->asMethodInst()->getMethodDesc(); + } + os << text << " "; md->printFullName(os); os << std::endl; + } + return; + } + scannedInsts->push_back(inst->getId()); + for (uint32 i=0; igetSrc(i)->getInst(); + if (!(Type::isTau(inst->getSrc(i)->getType()->tag))) + lObjectHistory(inst1,text+" ",os); + } +} // lObjectHistory(Inst* inst,std::string text,::std::ostream& os) + + +void +EscAnalyzer::printCreatedObjectsInfo(::std::ostream& os) { + CnGNodes::iterator it; + NodeMDs::iterator it1; + os << "================ Created Object States < "; + irManager.getMethodDesc().printFullName(os); + os << std::endl; + for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { + uint32 nt = (*it)->nodeType; + if (nt&(NT_OBJECT|NT_RETVAL) || nt==NT_LDOBJ) { + printCnGNode(*it,os); + ((Opnd*)(*it)->refObj)->printWithType(os); + if (getEscState(*it)==ARG_ESCAPE) { + for (it1 = (*it)->nodeMDs->begin(); it1 != (*it)->nodeMDs->end(); it1++) { + CnGNode* n=findCnGNode_id(*it1); + assert(n!=NULL); + os << std::endl; os <<" "; + printCnGNode(n,os); + os << std::endl; os <<" "; + ((MethodDesc*)n->refObj)->printFullName(os); + } + } + os << std::endl; + os << " =="; ((Opnd*)(*it)->refObj)->getInst()->print(os); + os << std::endl; + } + } + os << "================ > " ; + irManager.getMethodDesc().printFullName(os); + os << std::endl; +} // printCreatedObjectsInfo(::std::ostream& os) + + +/** + * Summarizes common number of objects with the same state. + * Prints statictics if required. + */ +void +EscAnalyzer::createdObjectInfo() { + CnGNodes::iterator it; + int n0 = 0; + int n_ge = 0; + int n_ae = 0; + int n_ne = 0; + uint32 state = 0; + + for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { + if ((*it)->nodeType == NT_OBJECT) { + n0++; + state = getEscState(*it); + if (state == GLOBAL_ESCAPE) + n_ge++; + if (state == ARG_ESCAPE) + n_ae++; + if (state == NO_ESCAPE) + n_ne++; + } + } + if (_printstat==1) { + Log::out() << "************** Created object info: "; + mh.printFullName(Log::out()); + Log::out() << std::endl; + Log::out() << " Number of created objects: " << n0 << std::endl; + if (n0>0) { + Log::out() << " Global escaped objects: " << n_ge << std::endl; + Log::out() << " Arg. escaped objects: " << n_ae << std::endl; + Log::out() << " Non escaped objects: " << n_ne << std::endl; + } + Log::out() << "************** " << std::endl; + } + + comObjStat._n0+=n0; + comObjStat._n_ge+=n_ge; + comObjStat._n_ae+=n_ae; + comObjStat._n_ne+=n_ne; + + if (_printstat==1) { + Log::out() << "************** Common created object info " << std::endl; + Log::out() << " Number of created objects: " << comObjStat._n0 << std::endl; + Log::out() << " Global escaped objects: " << comObjStat._n_ge << std::endl; + Log::out() << " Arg. escaped objects: " << comObjStat._n_ae << std::endl; + Log::out() << " Non escaped objects: " << comObjStat._n_ne << std::endl; + Log::out() << " Objects in loop: " << comObjStat._n_lo << std::endl; + Log::out() << "************** " << std::endl; + } +} // createdObjectInfo() + + +void +EscAnalyzer::printOriginObject(Inst* inst,std::string text) { + Inst* inst1 = NULL; + uint32 nsrc=inst->getNumSrcOperands(); + + if (scannedObjs->size()!=0) { + if (checkScannedObjs(inst->getId())) { +#ifdef _DEBUG + if (_seinfo || _scinfo) { + Log::out() << "instId " << inst->getId() + << " . . . " << std::endl; + } +#endif + return; + } + } +#ifdef _DEBUG + if (_seinfo || _scinfo) { + Log::out() << text; + inst->print(Log::out()); + Log::out() << std::endl; + } +#endif + if (inst->getOpcode()==Op_DirectCall || inst->getOpcode()==Op_IndirectMemoryCall) { + Opnd *returnOpnd = inst->getDst(); + if (returnOpnd != NULL) { + CnGNode* n = findCnGNode_op(returnOpnd->getId()); + if (n != NULL) { +#ifdef _DEBUG + if (_seinfo || _scinfo) { + Log::out()<< text << " "; + printCnGNode(n,Log::out()); + Log::out()<< std::endl; + } +#endif + } + } + if (inst->getOpcode()==Op_IndirectMemoryCall) { +#ifdef _DEBUG + MethodDesc* md; + if (inst->getSrc(0)->getInst()->getOpcode()== Op_LdVar) { + md = inst->getSrc(0)->getType()->asMethodPtrType()->getMethodDesc(); + } else { + md = inst->getSrc(0)->getInst()->asMethodInst()->getMethodDesc(); + } + if (_seinfo || _scinfo) { + Log::out() << text << " "; + md->printFullName(Log::out() ); + Log::out() << std::endl; + } +#endif + } + return; + } + if (inst->getOpcode()==Op_TauLdInd || inst->getOpcode()==Op_LdVar) { // ldind,ldvar + Opnd *dst = inst->getDst(); + CnGNode* n = findCnGNode_op(dst->getId()); + if (n != NULL) { +#ifdef _DEBUG + if (_seinfo || _scinfo) { + Log::out()<< text << " "; + printCnGNode(n,Log::out()); + Log::out()<< std::endl; + } +#endif + } + } + switch (inst->getOpcode()) { + case Op_LdRef: // ldref + case Op_NewObj: // newobj + case Op_NewArray: // newarray + case Op_NewMultiArray: // newmultiarray + case Op_DefArg: // defarg + { + CnGNode* n = findCnGNode_in(inst->getId()); + if (n != NULL) { +#ifdef _DEBUG + if (_seinfo || _scinfo) { + Log::out() << text << " "; + printCnGNode(n,Log::out() ); + Log::out() << std::endl; + // if (getEscState(n) == GLOBAL_ESCAPE) + // return; + } +#endif + } + break; + } + default: + break; + } + scannedObjs->push_back(inst->getId()); + for (uint32 i=0; igetSrc(i)->getInst(); + printOriginObject(inst1,text+" "); + } + scannedObjs->pop_back(); +} // printOriginObject(Inst* inst,std::string text) + + +void +EscAnalyzer::printOriginObject1(Inst* inst,std::string text) { + Inst* inst1; + uint32 nsrc=inst->getNumSrcOperands(); + + if (scannedObjs->size()!=0) { + if (checkScannedObjs(inst->getId())) { + if (_seinfo || _scinfo) { + Log::out() << "instId " << inst->getId() + << " . . . " << std::endl; + } + return; + } + } + if (_seinfo || _scinfo) { + Log::out() << text; + inst->print(Log::out()); + Log::out() << std::endl; + } + if (inst->getOpcode()==Op_DirectCall || inst->getOpcode()==Op_IndirectMemoryCall) { + Opnd *returnOpnd = inst->getDst(); + if (returnOpnd != NULL) { + CnGNode* n = findCnGNode_op(returnOpnd->getId()); + if (n != NULL) { + if (_seinfo || _scinfo) { + Log::out()<< text << " "; + printCnGNode(n,Log::out()); + Log::out()<< std::endl; + } + } + } + if (inst->getOpcode()==Op_IndirectMemoryCall) { + MethodDesc* md; + if (inst->getSrc(0)->getInst()->getOpcode()== Op_LdVar) { + md = inst->getSrc(0)->getType()->asMethodPtrType()->getMethodDesc(); + } else { + md = inst->getSrc(0)->getInst()->asMethodInst()->getMethodDesc(); + } + if (_seinfo || _scinfo) { + Log::out() << text << " "; + md->printFullName(Log::out() ); + Log::out() << std::endl; + } + } + return; + } + if (inst->getOpcode()==Op_TauLdInd || inst->getOpcode()==Op_LdVar) { // ldind,ldvar + Opnd *dst = inst->getDst(); + CnGNode* n = findCnGNode_op(dst->getId()); + if (n != NULL) { + if (_seinfo || _scinfo) { + Log::out()<< text << " "; + printCnGNode(n,Log::out()); + Log::out()<< std::endl; + } + } + } + switch (inst->getOpcode()) { + case Op_LdRef: // ldref + case Op_NewObj: // newobj + case Op_NewArray: // newarray + case Op_NewMultiArray: // newmultiarray + case Op_DefArg: // defarg + { + CnGNode* n = findCnGNode_in(inst->getId()); + if (n != NULL) { + if (_seinfo || _scinfo) { + Log::out() << text << " "; + printCnGNode(n,Log::out() ); + Log::out() << std::endl; + } + } + break; + } + default: + break; + } + scannedObjs->push_back(inst->getId()); + switch (inst->getOpcode()) { + case Op_TauLdInd: // ldind + case Op_AddScaledIndex: // addindex + inst1 = inst->getSrc(0)->getInst(); + printOriginObject1(inst1,text+" "); + break; + case Op_TauStInd: // stind + for (uint32 i=0; i<2; i++) { + inst1 = inst->getSrc(i)->getInst(); + printOriginObject1(inst1,text+" "); + } + break; + default: + for (uint32 i=0; igetSrc(i)->getInst(); + printOriginObject1(inst1,text+" "); + } + } + scannedObjs->pop_back(); +} // printOriginObject1(Inst* inst,std::string text) + + +void +EscAnalyzer::printMethodInfos() { + CalleeMethodInfos::iterator it1; + ParamInfos::iterator it2; + Log::out() << "==== debug ===== calleeMethodInfos; " << std::endl; + if (calleeMethodInfos==NULL) + Log::out() << " calleeMethodInfos is NULL " << std::endl; + if (calleeMethodInfos!=NULL) + for (it1 = calleeMethodInfos->begin( ); it1 != calleeMethodInfos->end( ); it1++) { + Log::out() << (*it1)->methodIdent->parentName << " "; + Log::out() << (*it1)->methodIdent->name << " "; + Log::out() << (*it1)->methodIdent->signature << " "; + Log::out() << (*it1)->numberOfArgs<< " " << std::endl; + for (it2 = (*it1)->paramInfos->begin( ); + it2 != (*it1)->paramInfos->end( ); it2++) { + Log::out() << (*it2)->paramNumber << " st." + << (*it2)->state << std::endl; + } + } + Log::out() << "==== end ===== calleeMethodInfos; " << std::endl; +} // printMethodInfos() + + +void +EscAnalyzer::printMethodInfo(CalleeMethodInfo* mi) { + ParamInfos::iterator it2; + Log::out() << "==== debug ===== calleeMethodInfo " << std::endl; + if (mi==NULL) + Log::out() << " calleeMethodInfo is NULL " << std::endl; + else { + Log::out() << mi->methodIdent->parentName << " "; + Log::out() << mi->methodIdent->name << " "; + Log::out() << mi->methodIdent->signature << " "; + Log::out() << "Number of parameters: " << mi->numberOfArgs<< " " << std::endl; + for (it2 = mi->paramInfos->begin( ); it2 != mi->paramInfos->end( ); it2++) { + Log::out() << (*it2)->paramNumber << " st."; + printState((*it2)->state); + Log::out() << std::endl; + } + Log::out() << "Return value state: "; + printState(mi->retValueState); + Log::out() << " " << std::endl; + } + Log::out() << "==== end ===== calleeMethodInfo " << std::endl; +} // printMethodInfo(CalleeMethodInfo* mi) + + +void EscAnalyzer::what_inst(Inst* inst,::std::ostream& os) { if (inst->asCallInst()) os << " CallInst" << std::endl; @@ -3252,129 +3382,12 @@ } // debug_opnd_info(Opnd* opnd,::std::ostream& os) -EscAnalyzer::CnGNode* -EscAnalyzer::addCnGNode(Inst* inst, Type* type, uint32 ntype) { - CnGNode* cgnode = new (eaMemManager) CnGNode; // new CG node - cgnode->cngNodeId = ++lastCnGNodeId; - cgnode->fgNode = inst->getNode(); - cgnode->instrId = inst->getId(); - cgnode->nodeType = ntype; - cgnode->lNode = NULL; - cgnode->nInst = inst; - cgnode->outEdges = NULL; - if (cgnode->nodeType==NT_DEFARG) - cgnode->argNumber = defArgNumber; // number of formal parameter - else - cgnode->argNumber = 0; - if ((ntype==NT_STFLD)||ntype==NT_THRVAL) - setFullState(cgnode,GLOBAL_ESCAPE); - else { - if (ntype==NT_ACTARG) { - setFullState(cgnode,ARG_ESCAPE); - if (inst->getOpcode()==Op_IndirectMemoryCall) - setVirtualCall(cgnode); - } else - setFullState(cgnode,NO_ESCAPE); - } - if (ntype==NT_EXITVAL) - setCalleeEscaped(cgnode); - cgnode->nodeMDs = NULL; - if (type->isReference()) { - if (type->isArray()) { - if (type->asArrayType()->getElementType()->isReference()) { - cgnode->nodeRefType = NR_REFARR; - } else - cgnode->nodeRefType = NR_ARR; - } else - cgnode->nodeRefType = NR_REF; - if (ntype&(NT_OBJECT|NT_RETVAL)||ntype==NT_LDOBJ) { - cgnode->nodeMDs = new (eaMemManager) NodeMDs(eaMemManager); // to collect methods receiving object - } - } else { - cgnode->nodeRefType = NR_PRIM; - } - cngNodes->push_back(cgnode); - return cgnode; -} // addCnGNode(Inst* inst, Type* type, uint32 ntype) +/* **************************************** + Monitors elimination optimization +**************************************** */ - -EscAnalyzer::CnGNode* -EscAnalyzer::addCnGNode_op(Inst* inst, Type* type, uint32 ntype) { - CnGNode* cgnode = addCnGNode(inst, type, ntype); // new CG node - Opnd* opnd = inst->getDst(); - - cgnode->opndId = opnd->getId(); - cgnode->refObj = opnd; -#ifdef _DEBUG - if (_cngnodes) { - Log::out() <<"++++ addNode "; printCnGNode(cgnode,Log::out()); - Log::out() << std::endl; - } -#endif - return cgnode; -} // addCnGNode_op(Inst* inst, Type* type, uint32 ntype) - - -EscAnalyzer::CnGNode* -EscAnalyzer::addCnGNode_mp(Inst* inst, MethodDesc* md, uint32 ntype, uint32 narg) { - Type* type = md->getParamType(narg); - CnGNode* cgnode = addCnGNode(inst, type, ntype); // new CG node - - cgnode->opndId = 0; - cgnode->argNumber = narg; - cgnode->refObj = md; -#ifdef _DEBUG - if (_cngnodes) { - Log::out() <<"++++ addNode "; printCnGNode(cgnode,Log::out()); - Log::out() << std::endl; - } -#endif - return cgnode; -} // addCnGNode_mp(Inst* inst, MethodDesc* md, uint32 ntype, uint32 narg) - - -EscAnalyzer::CnGNode* -EscAnalyzer::addCnGNode_ex(Inst* inst, uint32 ntype) { - Type* type = inst->getSrc(0)->getType(); - CnGNode* cgnode = addCnGNode(inst, type, ntype); // new CG node - - cgnode->opndId = 0; - cgnode->refObj = inst->getSrc(0); // returned or thrown operand -#ifdef _DEBUG - if (_cngnodes) { - Log::out() <<"++++ addNode "; printCnGNode(cgnode,Log::out()); - Log::out() << std::endl; - } -#endif - return cgnode; -} // addCnGNode_ex(Inst* inst, uint32 ntype) - - -EscAnalyzer::CnGNode* -EscAnalyzer::addCnGNode_fl(Inst* inst, uint32 ntype) { - Type* type = inst->getDst()->getType(); - CnGNode* cgnode = addCnGNode(inst, type, ntype); // new CG node - - cgnode->opndId = 0; - cgnode->refObj = inst; // returned or thrown operand -#ifdef _DEBUG - if (_cngnodes) { - Log::out() <<"++++ addNode "; printCnGNode(cgnode,Log::out()); - Log::out() << std::endl; - } -#endif - return cgnode; -} // addCnGNode_fl(Inst* inst, uint32 ntype) - - void -EscAnalyzer::addInst(cfgNode* cfgn, Inst* inst) { - cfgn->instructions->push_back(inst); -} // addInst(cfgNode* cfgn, Inst* inst) - - -void EscAnalyzer::addMonInst(Inst* inst) { uint32 monOpndId = inst->getSrc(0)->getId(); MonUnit* monUnit = NULL; @@ -3387,18 +3400,9 @@ monUnit->icallInsts = NULL; } monUnit->monInsts->push_back(inst); -} // addMonInst(MemoryManager& memManager, Inst* inst) +} // addMonInst(Inst* inst) -void -EscAnalyzer::addMonUnitVCall(MonUnit* mu, Inst* inst) { - if (mu->icallInsts == NULL) { - mu->icallInsts = new (eaMemManager) Insts(eaMemManager); - } - mu->icallInsts->push_back(inst); -} // addMonUnitVCall(MemoryManager& memManager, MonUnit* mu, Inst* inst) - - EscAnalyzer::MonUnit* EscAnalyzer::findMonUnit(uint32 opndId) { MonInstUnits::iterator it; @@ -3412,1149 +3416,1182 @@ void -EscAnalyzer::instrExam(cfgNode* cfgnode) { - Node* node = cfgnode->fgNode; - Inst *headInst = (Inst*)node->getFirstInst(); - int insnum=0; - Type* type; - CnGNode* cgnode; - uint32 ntype=0; - MethodDesc* md; - uint32 n; - bool addinst; - Inst* method_inst; +EscAnalyzer::addMonUnitVCall(MonUnit* mu, Inst* inst) { + if (mu->icallInsts == NULL) { + mu->icallInsts = new (eaMemManager) Insts(eaMemManager); + } + mu->icallInsts->push_back(inst); +} // addMonUnitVCall(MonUnit* mu, Inst* inst) - cfgnode->instructions=new (eaMemManager) Insts(eaMemManager); - for (Inst* inst=headInst->getNextInst();inst!=NULL;inst=inst->getNextInst()) { - insnum++; - ntype=0; - if (_instrInfo) { - Log::out() <<"instrExam:" << std::endl; - Log::out() <<"++Node Id."<getId()<<" "<getDfNum()<getId()<<" "<getDfNum()<print(Log::out()); - Log::out() << std::endl; - } - switch (inst->getOpcode()) { - case Op_LdRef: // ldref - case Op_NewObj: // newobj - case Op_NewArray: // newarray - case Op_NewMultiArray: // newmultiarray - ntype=NT_OBJECT; // for 4 cases above - case Op_LdConstant: // ldc - if (ntype==0) - ntype=NT_LDOBJ; // loads only ref null - case Op_DefArg: // defarg - if (ntype==0) { - ntype=NT_DEFARG; // for Op_DefArg - defArgNumber++; - } -#ifdef _DEBUG - if (_instrInfo) { - Log::out() <<"Node Id."<getId()<getDst()->getType()->isObject()) { - type=inst->getDst()->getType(); - assert(findCnGNode_op(inst->getDst()->getId())==NULL); - cgnode = addCnGNode_op(inst,type,ntype); - } - break; +/** + * Checks, that method contains monitor instructions with parameter + * which is this or subobject of this. + * Returns: true, if such monitors exist, false overwise. + */ +bool +EscAnalyzer::checkMonitorsOnThis() { + MonInstUnits::iterator it; + Insts::iterator it1; + CnGNode* node; - case Op_Conv: // conv -#ifdef _DEBUG - if (_instrInfo) { - Log::out() <<"Node Id."<getId()<getDst()->getType()->isObject()) { - type=inst->getDst()->getType(); - assert(findCnGNode_op(inst->getDst()->getId())==NULL); - cgnode = addCnGNode_op(inst,type,NT_OBJECT); - } - break; + if (monitorInstUnits==NULL) + return false; + for (it = monitorInstUnits->begin( ); it != monitorInstUnits->end( ); it++ ) { + node = findCnGNode_op((*it)->opndId); - case Op_LdFieldAddr: // ldflda - ntype=NT_INSTFLD; - case Op_LdStaticAddr: // ldsflda - if (ntype==0) - ntype=NT_STFLD; // for LdStaticAddr + Inst* opndInst = node->nInst; #ifdef _DEBUG - if (_instrInfo) { - Log::out() <<"Node Id."<getId()<print(Log::out()); + Log::out() << std::endl; + } #endif - FieldAccessInst* fainst; - if ((fainst=inst->asFieldAccessInst())!=NULL) { - type=fainst->getFieldDesc()->getFieldType(); //field type - if (type->isReference()) { - assert(findCnGNode_op(inst->getDst()->getId())==NULL); - cgnode = addCnGNode_op(inst,type,NT_REF); - CnGNode* n = findCnGNode_fl(inst,ntype); - if (n==NULL) { - n = addCnGNode_fl(inst,ntype); - } - cgnode->lNode=n; // stick nodes - addInst(cfgnode, inst); - } else { - if (ntype==NT_INSTFLD) { - assert(findCnGNode_op(inst->getDst()->getId())==NULL); - cgnode = addCnGNode_op(inst,type,NT_REF); - CnGNode* n = findCnGNode_fl(inst,ntype); - if (n==NULL) { - n = addCnGNode_fl(inst,ntype); - } - addInst(cfgnode, inst); - cgnode->lNode=n; // stick nodes - } - } - } - break; - - case Op_TauLdInd: // ldind + if (opndInst->getOpcode()==Op_DefArg && opndInst->getDefArgModifier()==NonNullThisArg) { #ifdef _DEBUG - if (_instrInfo) { - Log::out() <<"Node Id."<getId()<getDefArgModifier()) << " " << + (opndInst->getDefArgModifier()==DefArgNoModifier) << " " << + (opndInst->getDefArgModifier()==NonNullThisArg) << " " << + (opndInst->getDefArgModifier()==DefArgBothModifiers) << " state: "; + printState(node,Log::out()); + Log::out() << std::endl; + if (getEscState(node) != GLOBAL_ESCAPE) { + Log::out() << " defarg.ths isn't global "<< std::endl; } + } #endif - type = inst->getDst()->getType(); - if (type->isReference()) { //isObject()) { -// type=inst->getDst()->getType(); - assert(findCnGNode_op(inst->getDst()->getId())==NULL); - cgnode = addCnGNode_op(inst,type,NT_LDOBJ); - addInst(cfgnode, inst); - } - if (inst->getSrc(0)->getInst()->getOpcode()==Op_LdStaticAddr) - break; - if (type->isValue()) { - assert(findCnGNode_op(inst->getDst()->getId())==NULL); - cgnode = addCnGNode_op(inst,type,NT_LDVAL); - addInst(cfgnode, inst); - } - break; + return true; + } + } + return false; +} // checkMonitorsOnThis() - case Op_LdArrayBaseAddr: // ldbase - case Op_AddScaledIndex: // addindex + +void +EscAnalyzer::scanSyncInsts() { + MonInstUnits::iterator it; + Insts::iterator it1; + NodeMDs::iterator it2; + Insts* syncInsts; + Insts* vcInsts; + CnGNode* node; + uint32 checkedState = 0; + uint32 nState = 0; + bool to_fix_ssa = false; + BitSet fgnodes(eaMemManager,irManager.getFlowGraph().getMaxNodeId()); + + if (monitorInstUnits == NULL) + return; + #ifdef _DEBUG - if (_instrInfo) { - Log::out() <<"Node Id."<getId()<size() > 0) { + Log::out() << "Synchronized units: " << monitorInstUnits->size() << std::endl; + } + } #endif -// if (inst->getSrc(0)->getInst()->getOpcode()==Op_VMHelperCall) { -// Log::out() << "break "; inst->print(Log::out()); Log::out() << std::endl; -// break; -// } - if (inst->getDst()->getType()->isReference()) { - type=inst->getDst()->getType(); - assert(findCnGNode_op(inst->getDst()->getId())==NULL); - cgnode = addCnGNode_op(inst,type,NT_ARRELEM); - addInst(cfgnode, inst); - } - break; - - case Op_VMHelperCall: // callvmhelper + for (it = monitorInstUnits->begin( ); it != monitorInstUnits->end( ); it++ ) { + node = findCnGNode_op((*it)->opndId); + checkedState = 0; + nState = getEscState(node); + if (node->nodeType == NT_OBJECT || nState == GLOBAL_ESCAPE) + checkedState = nState; + if (nState != GLOBAL_ESCAPE && (node->nodeType != NT_OBJECT)) { + checkedState = checkState(node->nInst,nState); + scannedObjs->clear(); + if (checkedState != nState && checkedState != 0) { #ifdef _DEBUG - if (_instrInfo) { - Log::out() <<"Node Id."<getId()<cngNodeId<<" opndId "<opndId + <<" state "; + printState(node); + Log::out()<<" to esc.state "<< checkedState << std::endl; } #endif - if (!inst->getDst()->isNull()) { - if (inst->getDst()->getType()->isObject()) { - CompilationInterface::RuntimeHelperId callId = - inst->asVMHelperCallInst()->getVMHelperId(); - switch(callId) { - case CompilationInterface::Helper_GetTLSBase: - ntype = NT_ARRELEM; - break; - case CompilationInterface::Helper_NewObj_UsingVtable: - case CompilationInterface::Helper_NewVector_UsingVtable: - ntype = NT_OBJECT; - break; - default: - ntype = 0; - assert(0); - } - type=inst->getDst()->getType(); - assert(findCnGNode_op(inst->getDst()->getId())==NULL); - cgnode = addCnGNode_op(inst,type,ntype); - // addInst(cfgnode, inst); - } - } - break; - - case Op_TauStInd: // stind + setEscState(node,checkedState); + } + } #ifdef _DEBUG - if (_instrInfo) { - Log::out() <<"Node Id."<getId()<cngNodeId << " - " << node->opndId << " "; + printCnGNode(node,Log::out()); + Log::out() << std::endl; + if (node->nodeMDs !=NULL) { + Log::out() << " Callee methods (nodeMDs): " << std::endl; + for (it2 = node->nodeMDs->begin(); it2 != node->nodeMDs->end(); it2++) { + CnGNode* n=findCnGNode_id(*it2); + assert(n!=NULL); + Log::out() << " " << n->nInst->getNode()->getId() << " "; + FlowGraph::printLabel(Log::out(),n->nInst->getNode()); + Log::out() << " "; n->nInst->print(Log::out()); + Log::out()<< std::endl; } + } else { + Log::out() << " no Callee methods (nodeMDs) " << std::endl; + } + } #endif - if ((type=inst->getSrc(0)->getType())->isObject() || type->isValue()) { - addInst(cfgnode, inst); - } - break; - case Op_DirectCall: // call + syncInsts = (*it)->monInsts; + vcInsts = (*it)->icallInsts; #ifdef _DEBUG - if (_instrInfo) { - Log::out() <<"Node Id."<getId()<begin( ); it1 != syncInsts->end( ); it1++ ) { + Log::out() << " -"; + (*it1)->print(Log::out()); + Log::out() << " // node " + << (*it1)->getNode()->getId() << " "; + FlowGraph::printLabel(Log::out(),(*it1)->getNode()); + Log::out()<< std::endl; + } + if (vcInsts != NULL) { + Log::out() << " VCallee methods (icallInsts): " << std::endl; + for (it1 = vcInsts->begin( ); it1 != vcInsts->end( ); it1++ ) { + Log::out() << " node " + << (*it1)->getNode()->getId() << " "; + FlowGraph::printLabel(Log::out(),(*it1)->getNode()); + Log::out() << " "; + (*it1)->print(Log::out()); Log::out() << std::endl; } + } else { + Log::out() << " no VCallee methods (icallInsts) " << std::endl; + } + } #endif - if (!inst->getDst()->isNull()) { - if (inst->getDst()->getType()->isObject()) { - type=inst->getDst()->getType(); - assert(findCnGNode_op(inst->getDst()->getId())==NULL); - cgnode = addCnGNode_op(inst,type,NT_RETVAL); +#ifdef _DEBUG + if (getEscState(node) == GLOBAL_ESCAPE) + checkSencEscState(node,syncInsts); +#endif + if (getVirtualCall(node)!=0) { + if (checkedState > GLOBAL_ESCAPE && do_sync_removal_vc) { +/* if (!checkSencEscState(node,syncInsts)) { + if (_seinfo) { + Log::out() << "=-=- cannot be optimized" << std::endl; + printCnGNode(node,Log::out()); Log::out() << std::endl; } + continue; + }*/ + uint32 bs_size = irManager.getFlowGraph().getMaxNodeId(); + if (fgnodes.getSetSize() < bs_size) { + fgnodes.resizeClear(bs_size); + } else { + fgnodes.clear(); } - md=inst->asMethodInst()->getMethodDesc(); - n=md->getNumParams(); - addinst=false; - for (uint32 i = 0; i < n; i++) { - Type* tt = md->getParamType(i); - if (!tt->isReference()) { - continue; - } - addinst=true; - assert(findCnGNode_mp(inst->getId(),i)==NULL); - cgnode = addCnGNode_mp(inst,md,NT_ACTARG, i); - } - if (addinst) { - addInst(cfgnode, inst); - } -#ifdef _DEBUG + markLockedNodes(&fgnodes,syncInsts); +#ifdef _DEBUG if (_seinfo) { - if (method_ea_level == 0) { - Log::out() <<"iE: call "; - if (md->isSynchronized()) - Log::out() << "sync "; - if (md->isStatic()) - Log::out() << "stat "; - if (Log::isEnabled()) - inst->print(Log::out()); - Log::out()<printFullName(Log::out()); - Log::out() << std::endl; - } + Log::out() << "=-=- vc loc.esc." << std::endl; + printOriginObject(node->nInst); + scannedObjs->clear(); } #endif - break; - - case Op_IndirectMemoryCall: //callimem + if (node->nodeType==NT_OBJECT) { #ifdef _DEBUG - if (_instrInfo) { - Log::out() <<"Node Id."<getId()<getDst()->isNull()) { - if (inst->getDst()->getType()->isObject()) { - type=inst->getDst()->getType(); - assert(findCnGNode_op(inst->getDst()->getId())==NULL); - cgnode = addCnGNode_op(inst,type,NT_RETVAL); - } + fixMonitorInstsVCalls(*it,&fgnodes); } - method_inst=inst->getSrc(0)->getInst(); - if (method_inst->getOpcode() == Op_LdVar) { - Opnd* funptr = inst->getSrc(0); - Type* optype = funptr->getType(); - MethodPtrType* opmtype = optype->asMethodPtrType(); - md = opmtype->getMethodDesc(); - } else { - md=method_inst->asMethodInst()->getMethodDesc(); - } - n=md->getNumParams(); - addinst=false; - for (uint32 i = 0; i < n; i++) { - Type* tt = md->getParamType(i); - if (!tt->isReference()) { - continue; + if (node->nodeType==NT_RETVAL) { +#ifdef _DEBUG + if (_seinfo) { + Log::out() << "=-=- vc to optimize retval" << std::endl; } - addinst=true; - assert(findCnGNode_mp(inst->getId(),i)==NULL); - cgnode = addCnGNode_mp(inst,md,NT_ACTARG,i); +#endif + fixMonitorInstsVCalls(*it,&fgnodes); } - if (addinst) { - addInst(cfgnode, inst); + to_fix_ssa = true; + } else { +#ifdef _DEBUG + if (_seinfo && do_sync_removal_vc) { + Log::out() << "=-=- vc gl.esc." << std::endl; + printOriginObject(node->nInst); + scannedObjs->clear(); } -#ifdef _DEBUG +#endif + } + } else { + if (node->nodeType==NT_OBJECT && getEscState(node) != GLOBAL_ESCAPE) { +#ifdef _DEBUG if (_seinfo) { - if (method_ea_level == 0) { - Log::out() <<"iE: callimem "; - if (md->isSynchronized()) - Log::out() << "sync "; - if (md->isStatic()) - Log::out() << "stat "; - if (Log::isEnabled()) - inst->print(Log::out()); - Log::out()<printFullName(Log::out()); - Log::out() << std::endl; - } + Log::out() << "++++ to optimize (remove) object" << std::endl; } #endif - break; + removeMonitorInsts(syncInsts); + } - case Op_Catch: // catch + if (node->nodeType==NT_DEFARG && getEscState(node) != GLOBAL_ESCAPE + && node->nInst->getDefArgModifier()==NonNullThisArg && mh.isSynchronized()) { #ifdef _DEBUG - if (_instrInfo) { - Log::out() <<"Node Id."<getId()<getDst()->getType()->isObject()) { - type=inst->getDst()->getType(); - assert(findCnGNode_op(inst->getDst()->getId())==NULL); - cgnode = addCnGNode_op(inst,type,NT_CATCHVAL); +#ifndef PLATFORM_POSIX + if (do_sync_removal_sm) { + fixSyncMethodMonitorInsts(syncInsts); } - break; +#endif + } + } + } +#ifndef PLATFORM_POSIX + if (do_sync_removal_sm) { + checkCallSyncMethod(); + } +#endif + // to fix var operand inserted by fixMonitorInstsVCalls method + if (to_fix_ssa) { + eaFixupVars(irManager); + } + return; +} // scanSyncInsts() - case Op_StVar: // stvar + +void +EscAnalyzer::markLockedNodes(BitSet* bs, Insts* syncInsts) { + Insts::iterator si_i; + Opnd* mop = NULL; + Inst* inst = NULL; + Node* n = NULL; + if (syncInsts == NULL) { + return; + } + scannedObjs->clear(); + mop = syncInsts->front()->getSrc(0); + for (si_i = syncInsts->begin(); si_i != syncInsts->end(); si_i++) { + if ((*si_i)->getOpcode() == Op_TauMonitorEnter) { //monenter + n = (*si_i)->getNode(); + bs->setBit(n->getId(),true); #ifdef _DEBUG - if (_instrInfo) { - Log::out() <<"Node Id."<getId()<getId() << " "; + FlowGraph::printLabel(Log::out(),n); Log::out() << " "; + (*si_i)->print(Log::out()); Log::out() << std::endl; + } #endif - type = inst->getDst()->getType(); - if (type->isObject()) { - assert(findCnGNode_op(inst->getDst()->getId())==NULL); - cgnode = addCnGNode_op(inst,type,NT_VARVAL); - addInst(cfgnode, inst); - } - break; + inst = (Inst*)(n->getLastInst()); + assert(inst!=NULL); + if (inst->getOpcode() == Op_TauMonitorExit) { + continue; + } + if (n->getOutDegree() != 0) { + markLockedNodes2(n, bs, mop); + } + } + } +} // markLockedNodes(BitSet* bs, Insts* syncInsts) - case Op_Phi: // phi + +bool +EscAnalyzer::markLockedNodes2(Node* node, BitSet* bs, Opnd* moninstop) { + const Edges& oedges = node->getOutEdges(); + Edges::const_iterator eit; + Inst* inst; + Node* n; + bool found = true; + + if (scannedObjs->size()!=0) { + if (checkScannedObjs(node->getId())) { #ifdef _DEBUG - if (_instrInfo) { - Log::out() <<"Node Id."<getId()<getId() << " "; + FlowGraph::printLabel(Log::out(),node); + Log::out() << std::endl; + } #endif - type = inst->getDst()->getType(); - if (type->isReference()) { - assert(findCnGNode_op(inst->getDst()->getId())==NULL); - cgnode = addCnGNode_op(inst,type,NT_VARVAL); - addInst(cfgnode, inst); - } - break; - - case Op_LdVar: // ldvar + return found; + } + } + scannedObjs->push_back(node->getId()); + for (eit=oedges.begin(); eit!=oedges.end(); eit++) { + n = (*eit)->getTargetNode(); + bs->setBit(n->getId(),true); #ifdef _DEBUG - if (_instrInfo) { - Log::out() <<"Node Id."<getId()<getId() << " "; + FlowGraph::printLabel(Log::out(),n); + Log::out() << std::endl; + } #endif - type = inst->getDst()->getType(); - if (type->isReference()) { - assert(findCnGNode_op(inst->getDst()->getId())==NULL); - cgnode = addCnGNode_op(inst,type,NT_LDOBJ); - addInst(cfgnode, inst); - } - break; - - case Op_Return: // return - ntype=NT_EXITVAL; - case Op_Throw: // throw - if (ntype==0) - ntype=NT_THRVAL; + inst = (Inst*)(n->getLastInst()); + if (inst !=NULL) { + if (inst->getOpcode() == Op_TauMonitorExit) { #ifdef _DEBUG - if (_instrInfo) { - Log::out() <<"Node Id."<getId()<getId() << " "; + FlowGraph::printLabel(Log::out(),n); Log::out() << " "; + inst->print(Log::out()); Log::out() << std::endl; } #endif - if (inst->getNumSrcOperands()>0) { - if (inst->getSrc(0)->getType()->isObject()) { - assert(findCnGNode_in(inst->getId())==NULL); - cgnode = addCnGNode_ex(inst,ntype); - addInst(cfgnode, inst); - } - } - break; + continue; + } + } + if (n->getOutDegree() != 0) { + found = markLockedNodes2(n,bs,moninstop); + } else { + found = false; + } + } + return found; +} // markLockedNodes2(BitSet* bs, Insts* syncInsts) - case Op_TauStaticCast: // staticcast - case Op_TauCast: // cast + +/** + * Checks state for NT_LDOBJ nodes. + * Returns + * GLOBAL_ESCAPE - for global escaped NT_OBJECT, NT_RETVAL, NT_DEFARG + * node state - for not global escaped NT_OBJECT + * 0 - for not global escaped ?NT_RETVAL, NT_DEFARG + */ +uint32 +EscAnalyzer::checkState(Inst* inst,uint32 st) { + uint32 st1; + Inst* inst1; + Opnd* opnd1; + uint32 nsrc=inst->getNumSrcOperands(); + + if (st <= GLOBAL_ESCAPE) + return st; + if (scannedObjs->size()!=0) { + if (checkScannedObjs(inst->getId())) { + return st; + } + } + if (inst->getOpcode()==Op_DirectCall || inst->getOpcode()==Op_IndirectMemoryCall) { + Opnd *returnOpnd = inst->getDst(); + if (returnOpnd != NULL) { + CnGNode* n = findCnGNode_op(returnOpnd->getId()); + if (n != NULL) { + st1 = getEscState(n); + if (st > st1) + st=st1; + } + } + return st; + } + if (st <= GLOBAL_ESCAPE) + return st; + if (inst->getOpcode()==Op_TauLdInd || inst->getOpcode()==Op_LdVar) { // ldind, ldvar + Opnd *dst = inst->getDst(); + CnGNode* n = findCnGNode_op(dst->getId()); + if (n != NULL) { + st1 = getEscState(n); + if (st > st1) + st=st1; + } + } + if (st <= GLOBAL_ESCAPE) + return st; + switch (inst->getOpcode()) { + case Op_LdRef: // ldref + case Op_NewObj: // newobj + case Op_NewArray: // newarray + case Op_NewMultiArray: // newmultiarray + case Op_DefArg: // defarg + { + CnGNode* n = findCnGNode_in(inst->getId()); + if (n != NULL) { + st1 = getEscState(n); + if (st > st1) + st=st1; + } + break; + } + default: + break; + } + if (st <= GLOBAL_ESCAPE) + return st; + scannedObjs->push_back(inst->getId()); + for (uint32 i=0; igetSrc(i); + if (opnd1->isVarOpnd()) { + inst1 = opnd1->asVarOpnd()->getVarAccessInsts(); + } else { + inst1 = opnd1->getInst(); + } + st1 = checkState(inst1,st); + if (st > st1) + st=st1; + if (st<=GLOBAL_ESCAPE) + break; + } + scannedObjs->pop_back(); + return st; +} // checkState(Inst* inst,uint32 st) + + +bool +EscAnalyzer::checkSencEscState(CnGNode* node,Insts* syncInsts) { + CnGEdges::iterator it; + Insts::iterator it1; + CnGRefs::iterator it2; + Inst* einst; + bool pLocalObj = true; + bool pLocalCurObj = false; #ifdef _DEBUG - if (_instrInfo) { - Log::out() <<"Node Id."<getId()<cngNodeId + << std::endl; + } #endif - type = inst->getDst()->getType(); - if (type->isObject()) { - assert(findCnGNode_op(inst->getDst()->getId())==NULL); - cgnode = addCnGNode_op(inst,type,NT_LDOBJ); - addInst(cfgnode, inst); - } - break; - - case Op_SaveRet: // saveret + scannedSucNodes->clear(); // prepared for successor collection + for (it = cngEdges->begin( ); it != cngEdges->end( ); it++ ) { + for (it2 = (*it)->refList->begin( ); it2 != (*it)->refList->end( ); it2++ ) { + if ((*it2)->cngNodeTo == node) { + pLocalCurObj = false; + einst = (*it2)->edgeInst; #ifdef _DEBUG - if (_instrInfo) { - Log::out() <<"Node Id."<getId()<getNode()->getId() << " "; + FlowGraph::printLabel(Log::out(),einst->getNode()); + Log::out() << " "; einst->print(Log::out()); + Log::out() << std::endl; } #endif - type = inst->getDst()->getType(); - if (type->isIntPtr()) { - cgnode = findCnGNode_op(inst->getDst()->getId()); - if (cgnode == NULL) - cgnode = addCnGNode_op(inst,type,NT_INTPTR); + if (einst->getOpcode() == Op_DirectCall) { + MethodDesc* md=einst->asMethodInst()->getMethodDesc(); + const char* ch1 = md->getParentType()->getName(); + const char* ch2 = md->getName(); + const char* ch3 = md->getSignatureString(); + CalleeMethodInfo* mtdInfo = getMethodInfo(ch1,ch2,ch3); + if (mtdInfo==NULL) { +#ifdef _DEBUG + if (_seinfo) { + Log::out() << "=- Methodinfo is NULL"; + Log::out() << std::endl; + } +#endif + } else { + uint32 st = getMethodParamState(mtdInfo,(*it)->cngNodeFrom->argNumber); +#ifdef _DEBUG + if (_seinfo) { + Log::out() << "=-=- Method param " + << (*it)->cngNodeFrom->argNumber << " state is "; + printState(st); + Log::out() << std::endl; + } +#endif + if ((st&ESC_MASK)>GLOBAL_ESCAPE) { + pLocalCurObj = true; +#ifdef _DEBUG + if (_seinfo) { + Log::out() << "=- Method param " + << (*it)->cngNodeFrom->argNumber << " state is "; + printState(st); + Log::out() << std::endl; + } +#endif + } else { +#ifdef _DEBUG + if (_seinfo) { + printMethodInfo(mtdInfo); + } +#endif + } + } } - break; - - case Op_TauMonitorEnter: // monenter - case Op_TauMonitorExit: // monexit - if (do_sync_removal && method_ea_level == 0) { - addMonInst(inst); + if (_seinfo) { + printOriginObject1(einst); + } + collectSuccessors(einst->getNode()); + } + } + for (it1 = syncInsts->begin(); it1 != syncInsts->end( ); it1++ ) { + if (scannedSucNodes->size()!=0) { + if (checkScannedSucNodes((*it1)->getNode()->getId())!=0) { #ifdef _DEBUG if (_seinfo) { - Log::out() << "iE: monX Node Id." - << node->getId() << " "; - if (Log::isEnabled()) - inst->print(Log::out()); - Log::out()<getNode()->getId() << " "; + FlowGraph::printLabel(Log::out(),(*it1)->getNode()); + Log::out() << std::endl; } #endif + if (!pLocalCurObj) + pLocalObj = false; } - break; - - case Op_TypeMonitorEnter:// tmonenter - case Op_TypeMonitorExit: // tmonexit - break; - - case Op_TauVirtualCall: // callvirt - case Op_IndirectCall: // calli - case Op_IntrinsicCall: // callintr - - case Op_TauStRef: - case Op_TauStField: - case Op_TauStElem: - case Op_TauStStatic: - case Op_Copy: - - case Op_Box: - - if (_instrInfo) { - Log::out() <<"--Node Id."<getId()<print(Log::out()); - Log::out() << std::endl; - } - break; - - default: - - if (_instrInfo) { - Log::out() <<"~~Node Id."<getId()<print(Log::out()); - Log::out() << std::endl; - } + } } + scannedSucNodes->clear(); } - return; -} // instrExam(cfgNode* cfgnode) +#ifdef _DEBUG + if (_seinfo) { + if (pLocalObj) { + Log::out() << "=- may be optimized" + << std::endl; + } + } +#endif + return pLocalObj; +} // checkSencEscState(CnGNode* node,Insts* syncInsts) +/** + * Collect all reachable from specified node nodes in FlowGraph. + * scannedSucNodes - result of collection. + */ void -EscAnalyzer::instrExam2(cfgNode* node) { - Insts *instrs = node->instructions; - int insnum=0; - Insts::iterator it; - Inst* inst; - Type* type; - CnGNode* cgnode; - CnGNode* cgn_src; - uint32 ntype=0; - MethodDesc* md; - uint32 n; - Inst* method_inst; - bool not_exam = false; +EscAnalyzer::collectSuccessors(Node* node) { + Node* n; + Edges::const_iterator eit; + const Edges& out_edges = node->getOutEdges(); + if (scannedSucNodes->size()!=0) { + if (checkScannedSucNodes(node->getId())!=0) { + return; + } + } + scannedSucNodes->push_back(node->getId()); + for (eit = out_edges.begin(); eit != out_edges.end(); ++eit) { + n = (*eit)->getTargetNode(); + collectSuccessors(n); + } +} // collectSuccessors(Node* node) - for (it = instrs->begin( ); it != instrs->end( ); it++ ) { - inst=*it; - insnum++; - ntype=0; +void +EscAnalyzer::collectGlobalNodeSuccessors(CnGNode* node) { + CnGEdges::iterator it; + CnGRefs::iterator it2; + Inst* einst; + bool pGlobalObj = false; #ifdef _DEBUG - if (_instrInfo2) { - Log::out() <<"instrExam2: Node Id."<fgNode->getId()<cngNodeId + << std::endl; + } #endif - - switch (inst->getOpcode()) { - case Op_LdFieldAddr: // ldflda - ntype=NT_INSTFLD; - case Op_LdStaticAddr: // ldsflda - if (ntype==0) - ntype=NT_STFLD; // for LdStaticAddr - FieldAccessInst* fainst; - if ((fainst=inst->asFieldAccessInst())!=NULL) { - bool isref = fainst->getFieldDesc()->getFieldType()->isReference(); - if (isref || ntype==NT_INSTFLD) { - cgn_src=findCnGNode_op(inst->getDst()->getId()); // field address node - if (isref) - assert(cgn_src!=NULL); - cgnode=findCnGNode_fl(inst,ntype); // field node - assert(cgnode!=NULL); - // adding edge from fld node to address node - if (ntype == NT_INSTFLD) { - cgn_src=findCnGNode_op(inst->getSrc(0)->getId()); // instance node - // adding fld edge for ldflda - addEdge(cgn_src,cgnode,ET_FIELD,inst); - // special for java/lang/String::value - FieldDesc* fd=inst->asFieldAccessInst()->getFieldDesc(); - if (fd->getParentType()->isSystemString()&&strcmp(fd->getName(),"value")==0) { - addEdge(cgnode,cgn_src,ET_DEFER,inst); - } - } - } + scannedSucNodes->clear(); // prepared for successor collection + for (it = cngEdges->begin( ); it != cngEdges->end( ); it++ ) { + for (it2 = (*it)->refList->begin( ); it2 != (*it)->refList->end( ); it2++ ) { + if ((*it2)->cngNodeTo == node) { + pGlobalObj = false; + einst = (*it2)->edgeInst; +#ifdef _DEBUG + if (_seinfo) { + Log::out() << "=-ggns "; + Log::out() << einst->getNode()->getId() + << " "; + einst->print(Log::out()); + Log::out() << std::endl; } - break; - - case Op_TauLdInd: // ldind - type=inst->getDst()->getType(); - if (type->isObject()) { - cgnode=findCnGNode_op(inst->getDst()->getId()); - assert(cgnode!=NULL); - // ref to loaded object - cgn_src=findCnGNode_op(inst->getSrc(0)->getId()); - assert(cgn_src!=NULL); - addEdge(cgn_src,cgnode,ET_POINT,inst); - } - if (type->isValue()) { - cgnode=findCnGNode_op(inst->getDst()->getId()); - assert(cgnode!=NULL); - // ref to loaded object - cgn_src=findCnGNode_op(inst->getSrc(0)->getId()); - assert(cgn_src!=NULL); - addEdge(cgn_src,cgnode,ET_POINT,inst); - } - break; - - case Op_LdArrayBaseAddr: // ldbase - case Op_AddScaledIndex: // addindex - if (inst->getDst()->getType()->isReference()) { - cgnode=findCnGNode_op(inst->getDst()->getId()); - assert(cgnode!=NULL); - // ref to loaded address - if (inst->getOpcode()==Op_LdArrayBaseAddr) { - cgn_src=findCnGNode_op(inst->getSrc(0)->getId()); - assert(cgn_src!=NULL); - addEdge(cgn_src,cgnode,ET_FIELD,inst); // ref to base element - } - if (inst->getOpcode()==Op_AddScaledIndex) { - if (inst->getSrc(0)->getInst()->getOpcode()==Op_LdArrayBaseAddr) { - cgn_src=findCnGNode_op( - inst->getSrc(0)->getInst()->getSrc(0)->getId()); - assert(cgn_src!=NULL); - addEdge(cgn_src,cgnode,ET_FIELD,inst); // ref from array object to inner objects +#endif + if (einst->getOpcode() == Op_DirectCall) { + MethodDesc* md=einst->asMethodInst()->getMethodDesc(); + const char* ch1 = md->getParentType()->getName(); + const char* ch2 = md->getName(); + const char* ch3 = md->getSignatureString(); + CalleeMethodInfo* mtdInfo = getMethodInfo(ch1,ch2,ch3); + if (mtdInfo==NULL) { + pGlobalObj = true; +#ifdef _DEBUG + if (_seinfo) { + Log::out() << "ggns=- Methodinfo is NULL"; + Log::out() << std::endl; } +#endif + } else { + uint32 st = getMethodParamState(mtdInfo,(*it)->cngNodeFrom->argNumber); +#ifdef _DEBUG + if (_seinfo) { + Log::out() << "ggns=-=- Method param " + << (*it)->cngNodeFrom->argNumber << " state is "; + printState(st); + Log::out() << std::endl; + } +#endif + if ((st&ESC_MASK)<=GLOBAL_ESCAPE) { + pGlobalObj = true; +#ifdef _DEBUG + if (_seinfo) { + Log::out() << "ggns=- Method param " + << (*it)->cngNodeFrom->argNumber << " state is "; + printState(st); + Log::out() << std::endl; + } +#endif + } } } - break; - - case Op_TauStInd: // stind - if (inst->getSrc(0)->getType()->isObject()) { - // ref to loaded address - cgn_src=findCnGNode_op(inst->getSrc(0)->getId()); - assert(cgn_src!=NULL); - cgnode=findCnGNode_op(inst->getSrc(1)->getId()); - assert(cgnode!=NULL); - addEdge(cgnode,cgn_src,ET_DEFER,inst); - break; - } - if ((type=inst->getSrc(0)->getType())->isValue()) { - uint32 src_opcode = inst->getSrc(1)->getInst()->getOpcode(); - if (src_opcode==Op_LdStaticAddr) - break; - cgn_src=findCnGNode_op(inst->getSrc(0)->getId()); - if (cgn_src==NULL) { - cgn_src = addCnGNode_op(inst->getSrc(0)->getInst(),type,NT_LDVAL); + if (einst->getOpcode() == Op_IndirectMemoryCall) + pGlobalObj = true; + if (einst->getOpcode() == Op_TauStInd) { + Inst* i1 = einst->getSrc(0)->getInst(); + if (i1->getOpcode()==Op_LdStaticAddr) + pGlobalObj = true; + uint32 st = getContainingObjState(i1); + if ((st&ESC_MASK)<=GLOBAL_ESCAPE) { + pGlobalObj = true; } - cgnode=findCnGNode_op(inst->getSrc(1)->getId()); - assert(cgnode!=NULL); - addEdge(cgnode,cgn_src,ET_DEFER,inst); } - break; + printOriginObject1(einst); + if (pGlobalObj) + collectSuccessors(einst->getNode()); + } + } + } +} // collectGlobalNodeSuccessors(CnGNode* node) - case Op_DirectCall: // call - md=inst->asMethodInst()->getMethodDesc(); - n=md->getNumParams(); - for (uint32 i = 0; i < n; i++) { - Type* tt = md->getParamType(i); - if (!tt->isReference()) - continue; - cgnode=findCnGNode_mp(inst->getId(),i); - assert(cgnode!=NULL); - cgn_src=findCnGNode_op(inst->getSrc(2+i)->getId()); - assert(cgn_src!=NULL); - addEdge(cgnode,cgn_src,ET_DEFER,inst); - } - break; - case Op_IndirectMemoryCall: //callimem - method_inst=inst->getSrc(0)->getInst(); - if (method_inst->getOpcode() == Op_LdVar) { - MethodPtrType* mpt = inst->getSrc(0)->getType()->asMethodPtrType(); - md = mpt->getMethodDesc(); - } else { - md=method_inst->asMethodInst()->getMethodDesc(); - } - n=md->getNumParams(); - for (uint32 i = 0; i < n; i++) { - Type* tt = md->getParamType(i); - if (!tt->isReference()) - continue; - cgnode = findCnGNode_mp(inst->getId(),i); - assert(cgnode!=NULL); - cgn_src=findCnGNode_op(inst->getSrc(3+i)->getId()); - assert(cgn_src!=NULL); - addEdge(cgnode,cgn_src,ET_DEFER,inst); - } - break; +uint32 +EscAnalyzer::getContainingObjState(Inst* linst) { + Opnd* cop = NULL; + if (linst->getOpcode()==Op_LdStaticAddr) + return GLOBAL_ESCAPE; + if (linst->getOpcode()==Op_LdFieldAddr || linst->getOpcode()==Op_LdArrayBaseAddr) + cop = linst->getSrc(0); + if (linst->getOpcode()==Op_AddScaledIndex) + cop = linst->getSrc(0)->getInst()->getSrc(0); + else + return GLOBAL_ESCAPE; + CnGNode* n = findCnGNode_op(cop->getId()); + return n->state; +} // getContainingObjState(Inst* linst) - case Op_StVar: // stvar - if (inst->getDst()->getType()->isObject()) { - cgnode = findCnGNode_op(inst->getDst()->getId()); - assert(cgnode!=NULL); - cgn_src=findCnGNode_op(inst->getSrc(0)->getId()); - assert(cgn_src!=NULL); - addEdge(cgn_src,cgnode,ET_DEFER,inst); - } - break; - case Op_Phi: // phi - if (inst->getDst()->getType()->isObject()) { - uint32 nsrc=inst->getNumSrcOperands(); - cgnode = findCnGNode_op(inst->getDst()->getId()); - assert(cgnode!=NULL); - for (uint32 i=0; igetSrc(i)->getId()); - assert(cgn_src!=NULL); - addEdge(cgn_src,cgnode,ET_DEFER,inst); - } - } - break; +void +EscAnalyzer::fixMonitorInstsVCalls(MonUnit* mu, BitSet* bs) { + Inst* opi = findCnGNode_op(mu->opndId)->nInst; + OpndManager& _opndManager = irManager.getOpndManager(); + InstFactory& _instFactory = irManager.getInstFactory(); + TypeManager& _typeManager = irManager.getTypeManager(); + Type* typeInt32 = _typeManager.getInt32Type(); + VarOpnd* muflag = _opndManager.createVarOpnd(typeInt32, false); + Inst* stvar0; // = _instFactory.makeStVar(muflag, i32_0); + Inst* stvar1; + Insts::iterator inst_it; + Insts* vcInsts = mu->icallInsts;; + Insts* syncInsts = mu->monInsts; + Node* oldCallNode = NULL; + Node* addedMonNode = NULL; + Node* newCallNode = NULL; + ControlFlowGraph& fg = irManager.getFlowGraph(); +#ifdef _DEBUG + Node* entry_node = fg.getEntryNode(); + Node* muo_node = opi->getNode(); +// Node* node; +#endif - case Op_LdVar: // ldvar - type = inst->getDst()->getType(); - if (type->isReference()) { - cgnode = findCnGNode_op(inst->getDst()->getId()); - assert(cgnode!=NULL); - cgn_src=findCnGNode_op(inst->getSrc(0)->getId()); - assert(cgn_src!=NULL); - addEdge(cgn_src,cgnode,ET_DEFER,inst); // load ldobj - } - break; + // values 0 and 1 to set flag variable +#ifdef _DEBUG + if (_seinfo) { + Log::out() << "=-=- w0 Before " << std::endl; + FlowGraph::print(Log::out(),entry_node); + } +#endif + insertLdConst(1); + insertLdConst(0); +#ifdef _DEBUG + if (_seinfo) { + Log::out() << "=-=- w0 After " << std::endl; + FlowGraph::print(Log::out(),entry_node); + } +#endif - case Op_Return: // return - ntype=NT_EXITVAL; - case Op_Throw: // throw - if (ntype==0) - ntype=NT_THRVAL; - if (inst->getNumSrcOperands()>0) { - cgnode = findCnGNode_in(inst->getId()); - assert(cgnode!=NULL); - cgn_src=findCnGNode_op(inst->getSrc(0)->getId()); - assert(cgn_src!=NULL); - addEdge(cgnode,cgn_src,ET_DEFER,inst); - } - break; + // insert flag=0 after monitor instruction opnd creation instruction +#ifdef _DEBUG + if (_seinfo) { + Log::out() << "=-=- w1 Before " << std::endl; + FlowGraph::print(Log::out(),muo_node); + } +#endif + stvar0 = _instFactory.makeStVar(muflag, i32_0); + stvar0->insertBefore(opi); +#ifdef _DEBUG + if (_seinfo) { + Log::out() << "=-=- w1 After " << std::endl; + FlowGraph::print(Log::out(),muo_node); + } +#endif - case Op_TauStaticCast: // staticcast - case Op_TauCast: // cast - type = inst->getDst()->getType(); - cgnode = findCnGNode_op(inst->getDst()->getId()); - assert(cgnode!=NULL); - cgn_src=findCnGNode_op(inst->getSrc(0)->getId()); - assert(cgn_src!=NULL); - addEdge(cgnode,cgn_src,ET_DEFER,inst); - break; - - case Op_TauMonitorEnter: // monenter - case Op_TauMonitorExit: // monexit - case Op_TypeMonitorEnter:// tmonenter - case Op_TypeMonitorExit: // tmonexit - break; - - default: - if (_instrInfo2) { - not_exam = true; - } + // insert flag=1 before virtual call instructions +#ifdef _DEBUG + if (_seinfo) { + Log::out() << "=-=-=-=- Start w2" << std::endl; + } +#endif + for (inst_it = vcInsts->begin( ); inst_it != vcInsts->end( ); inst_it++ ) { + oldCallNode = (*inst_it)->getNode(); + addedMonNode = NULL; + newCallNode = NULL; +#ifdef _DEBUG + // node = (*inst_it)->getNode(); + if (_seinfo) { + Log::out() << "=-=- w2 Before " << std::endl; + FlowGraph::print(Log::out(),oldCallNode); + if (bs->getBit(oldCallNode->getId())) { + Log::out() << "=-=- monenter is needed " << std::endl; + } else { + Log::out() << "=-=- monenter isn't needed " << std::endl; + } } - if (_instrInfo2) { - if (not_exam) { - Log::out() <<"!!! Not examined."<insertBefore(*inst_it); + if (bs->getBit((*inst_it)->getNode()->getId())) { + Inst* mi = syncInsts->front(); + Inst* ime = _instFactory.makeTauMonitorEnter(mi->getSrc(0), mi->getSrc(1)); + ime->insertBefore(*inst_it); + newCallNode = fg.splitNodeAtInstruction(ime,true,false,_instFactory.makeLabel()); + SsaTmpOpnd* opflag = _opndManager.createSsaTmpOpnd(typeInt32); + _instFactory.makeLdVar(opflag,(VarOpnd*)muflag)->insertBefore(stvar1); + Inst* branch_inst = _instFactory.makeBranch(Cmp_EQ, Type::Int32, + opflag, i32_1, (LabelInst*)(newCallNode->getFirstInst())); + // insert flag check + branch_inst->insertBefore(stvar1); + addedMonNode = fg.splitNodeAtInstruction(branch_inst,true, false, _instFactory.makeLabel()); + fg.addEdge(oldCallNode,newCallNode); + } +#ifdef _DEBUG + if (_seinfo) { + if (bs->getBit(oldCallNode->getId())) { + Log::out() << "=-=- monenter is inserted " << std::endl; } + Log::out() << "=-=- w2 After " << std::endl; + FlowGraph::print(Log::out(),oldCallNode); + if (addedMonNode != NULL) { + FlowGraph::print(Log::out(),addedMonNode); + } + if (newCallNode != NULL) { + FlowGraph::print(Log::out(),newCallNode); + } } +#endif } - return; -} // instrExam2(cfgNode* node) +#ifdef _DEBUG + if (_seinfo) { + Log::out() << "=-=-=-=- Finish w2" << std::endl; + } +#endif + insertFlagCheck(syncInsts,muflag,0); -void -EscAnalyzer::printCnGNode(CnGNode* cgn,::std::ostream& os) { - std::string t2; +} // fixMonitorInstsVCalls(MonUnit* mu) - os << "nodeId "<cngNodeId<<" "; - if (cgn->nodeType & (NT_OBJS|NT_LDVAL)) { //node of object created in the method - os << "opId "<opndId<<" "; - } else { - if (cgn->nodeType & NT_ACTARG) { //node of actual method parameter - os << "nArg "<argNumber<<" "; - os << "method "<refObj<<" "; - } - } - if (cgn->nodeType==NT_DEFARG) - os << " nArg "<argNumber<<" "; //Arg number for defarg - os << " inst "<instrId<<" ("<nodeType<<", "; - switch (cgn->nodeRefType) { - case NR_PRIM : t2="Prim-"; break; - case NR_REF : t2="Ref -"; break; - case NR_ARR : t2="Arr -"; break; - case NR_REFARR : t2="RArr-"; break; - default : t2=" -"; - } - os <nodeRefType<<") "; - if (cgn->lNode) - os << "( " << cgn->lNode->cngNodeId << "-" << cgn->lNode->opndId << " ) "; - os << "st. "; - printState(cgn,os); os << " "; -} // printCnGNode(CnGNode* cgn,::std::ostream& os) +/** + * Inserts flag check before monitor instruction. + * If flag = i32_chk value monitor instruction isn't executed. + * Operand flag may be VarOpnd* or SsaTmpOpnd* type. + */ +void +EscAnalyzer::insertFlagCheck(Insts* syncInsts, Opnd* muflag, uint32 chk) { + Insts::iterator inst_it; + OpndManager& _opndManager = irManager.getOpndManager(); + InstFactory& _instFactory = irManager.getInstFactory(); + ControlFlowGraph& fg = irManager.getFlowGraph(); + TypeManager& _typeManager = irManager.getTypeManager(); + Type* typeInt32 = _typeManager.getInt32Type(); + SsaTmpOpnd* chk_opnd = NULL; -std::string -EscAnalyzer::nodeTypeToString(CnGNode* cgn) { - std::string t1; - switch (cgn->nodeType) { - case NT_OBJECT : t1="Obj -"; break; - case NT_DEFARG : t1="DArg-"; break; - case NT_RETVAL : t1="RVal-"; break; - case NT_CATCHVAL: t1="CVal-"; break; - case NT_STFLD : t1="SFld-"; break; - case NT_INSTFLD : t1="IFld-"; break; - case NT_LDOBJ : t1="LObj-"; break; - case NT_INTPTR : t1="IPtr-"; break; - case NT_VARVAL : t1="VVal-"; break; - case NT_ARRELEM : t1="ArEl-"; break; - case NT_REF : t1="REF -"; break; - case NT_ACTARG : t1="AArg-"; break; - case NT_EXITVAL : t1="EVal-"; break; - case NT_THRVAL : t1="TVal-"; break; - case NT_LDVAL : t1="LVal-"; break; - default : t1=" -"; + // check flag before monitor instructions + assert(muflag->isVarOpnd()||muflag->isSsaTmpOpnd()); + if (chk == 0) { + chk_opnd = insertLdConst(0); } - return t1; -} // nodeTypeToString(CnGNode* cgn) - - -std::string -EscAnalyzer::edgeTypeToString(CnGRef* edr) { - std::string t1; - switch (edr->edgeType) { - case ET_POINT : t1="poi-"; break; - case ET_DEFER : t1="ref-"; break; - case ET_FIELD : t1="fld-"; break; - default : t1=" -"; + if (chk == 1) { + chk_opnd = insertLdConst(1); } - return t1; -} // edgeTypeToString(CnGRef* edr) - - -void -EscAnalyzer::printCnGNodes(char* text,::std::ostream& os) { - CnGNodes::const_iterator it; - FieldDesc* fd; - std::string t1; - std::string t2; - os << " "<< text << std::endl; - for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { - os <<" "; - printCnGNode(*it,os); - os << std::endl; - os << " "; - if ((*it)->nodeType & (NT_OBJS|NT_EXITVAL|NT_LDVAL)) { //node of created or exit object - ((Opnd*)(*it)->refObj)->printWithType(os); - } - if ((*it)->nodeType == NT_RETVAL) { - os << std::endl; os << " "; - Inst* inst = ((Opnd*)(*it)->refObj)->getInst(); - inst->print(os); - if (inst->getOpcode()==Op_IndirectMemoryCall) { - MethodDesc* md; - if (inst->getSrc(0)->getInst()->getOpcode()== Op_LdVar) { - md = inst->getSrc(0)->getType()->asMethodPtrType()->getMethodDesc(); - } else { - md = inst->getSrc(0)->getInst()->asMethodInst()->getMethodDesc(); - } - os << std::endl; os << " "; - md->printFullName(os); - } + assert(chk_opnd!=NULL); +#ifdef _DEBUG + if (_seinfo) { + Log::out() << "=-=-=-=- Start w3" << std::endl; + } +#endif + for (inst_it = syncInsts->begin( ); inst_it != syncInsts->end( ); inst_it++ ) { + Inst* curMonInst = (*inst_it); + Node* oldnode = curMonInst->getNode(); +#ifdef _DEBUG + if (_seinfo) { + Log::out() << "=-=- w3 Before " << std::endl; + FlowGraph::print(Log::out(),oldnode); } - if ((*it)->nodeType & NT_ACTARG) { //node of actual method parameter - os << ((MethodDesc*)(*it)->refObj)->getParentType()->getName() << "::"; - os << ((MethodDesc*)(*it)->refObj)->getName() << std::endl; - os << " "; - os << ((MethodDesc*)(*it)->refObj)->getParamType((*it)->opndId)->getName(); +#endif + Node* afterMonInstBlock = NULL; + Node* tiInstBlock = NULL; + if ((*inst_it)->getNextInst()!=NULL) { + // monitor inst isn'n last + tiInstBlock = fg.splitNodeAtInstruction(curMonInst, true, false, _instFactory.makeLabel()); + afterMonInstBlock = tiInstBlock; + } else { + // monitor inst is last + afterMonInstBlock = (Node*)(oldnode->getUnconditionalEdge()->getTargetNode()); } - if ((*it)->nodeType & NT_STFLD) { //field node - fd = ((Inst*)(*it)->refObj)->asFieldAccessInst()->getFieldDesc(); - os << fd->getParentType()->getName() << "::"<< fd->getName() << std::endl; - os << " "<getFieldType()->getName(); + SsaTmpOpnd* i32_flag; + if (muflag->isVarOpnd()) { + i32_flag = _opndManager.createSsaTmpOpnd(typeInt32); + _instFactory.makeLdVar(i32_flag,(VarOpnd*)muflag)->insertBefore(curMonInst); + } else { + i32_flag = (SsaTmpOpnd*)muflag; } - os << std::endl; - } -} // printCnGNodes(char* text,::std::ostream& os) - - -void -EscAnalyzer::printCnGNodeRefs(CnGNode* cgn, std::string text,::std::ostream& os) { - CnGNode* node; - CnGRefs::iterator it1; - Inst* inst; - os << text; - if (scannedObjs->size()!=0) { - if (checkScannedObjs(cgn->cngNodeId)) { - os << "nodeId " << cgn->cngNodeId << " . . . " << std::endl; - return; - } - } - printCnGNode(cgn,os); - os << std::endl; - os << text; cgn->nInst->print(os); os << std::endl; - scannedObjs->push_back(cgn->cngNodeId); - if (cgn->outEdges != NULL) { - for (it1 = cgn->outEdges->begin( ); it1 != cgn->outEdges->end( ); it1++ ) { - os << text << edgeTypeToString(*it1) << std::endl; - if ((node=findCnGNode_id((*it1)->cngNodeTo->cngNodeId))!=NULL) - printCnGNodeRefs(node,text+" ",os); - } - } - scannedObjs->pop_back(); - if (cgn->nodeType==NT_RETVAL) { - inst = cgn->nInst; - if (inst->getOpcode()==Op_IndirectMemoryCall) { - MethodDesc* md; - if (inst->getSrc(0)->getInst()->getOpcode()== Op_LdVar) { - md = inst->getSrc(0)->getType()->asMethodPtrType()->getMethodDesc(); - } else { - md = inst->getSrc(0)->getInst()->asMethodInst()->getMethodDesc(); + Inst* branch_inst = _instFactory.makeBranch(Cmp_EQ, Type::Int32, + i32_flag, chk_opnd, (LabelInst*)(afterMonInstBlock->getFirstInst())); + // insert flag check + branch_inst->insertBefore(curMonInst); +#ifdef _DEBUG + Node* monInstBlock = +#endif + fg.splitNodeAtInstruction(branch_inst,true, false, _instFactory.makeLabel()); + fg.addEdge(oldnode,afterMonInstBlock); +#ifdef _DEBUG + if (_seinfo) { + Log::out() << "=-=- w3 After " << std::endl; + FlowGraph::print(Log::out(),oldnode); + FlowGraph::print(Log::out(),monInstBlock); + if (tiInstBlock != NULL) { + FlowGraph::print(Log::out(),tiInstBlock); } - os << text << " "; - md->printFullName(os); os << std::endl; } +#endif } - if (cgn->nodeType==NT_LDOBJ && getEscState(cgn)!=GLOBAL_ESCAPE) { - inst = cgn->nInst; - lObjectHistory(inst,text,os); - scannedInsts->clear(); +#ifdef _DEBUG + if (_seinfo) { + Log::out() << "=-=-=-=- Finish w3" << std::endl; } -} // printCnGNodeRefs(CnGNode* cgn, std::string text,::std::ostream& os) +#endif +} // insertFlagCheck(Insts* syncInsts, Opnd* muflag, uint32 chk) void -EscAnalyzer::lObjectHistory(Inst* inst,std::string text,::std::ostream& os) { - Inst* inst1; - uint32 nsrc=inst->getNumSrcOperands(); +EscAnalyzer::removeMonitorInsts(Insts* syncInsts) { + ControlFlowGraph& fg = irManager.getFlowGraph(); + Insts::iterator it1; + Edge* excedge = NULL; + Node* targetnode = NULL; + Inst* reminst; +#ifdef _DEBUG + bool canthrow = false; +#endif - if (scannedInsts->size()!=0) { - if (checkScannedInsts(inst->getId())) { - os << text << "instId " << inst->getId() << " . . . " << std::endl; - return; + for (it1 = syncInsts->begin( ); it1 != syncInsts->end( ); it1++ ) { + reminst = *it1; + if (reminst->getOperation().canThrow()==true) { + excedge = (Edge*)reminst->getNode()->getExceptionEdge(); + if (excedge != NULL) + targetnode = excedge->getTargetNode(); + else + targetnode = NULL; + } else { + excedge = NULL; + targetnode = NULL; } - } - os << text; inst->print(os); os << std::endl; - if (inst->getOpcode()==Op_DirectCall || inst->getOpcode()==Op_IndirectMemoryCall) { - Opnd *returnOpnd = inst->getDst(); - if (returnOpnd != NULL) { - CnGNode* n = findCnGNode_op(returnOpnd->getId()); - if (n != NULL) { - os<< text << " "; printCnGNode(n,os); os<< std::endl; +#ifdef _DEBUG + if (_seinfo) { + canthrow = reminst->getOperation().canThrow(); + Log::out() << " "; + reminst->print(Log::out()); + Log::out() << std::endl; + Log::out() << " canThrow "<< canthrow; + Log::out() << std::endl; + if (excedge==NULL) { + Log::out() << " exception edge is NULL " << std::endl; + } else { + Log::out() << " target node is " + << targetnode->getId() << std::endl; } + if (canthrow && (excedge==NULL)) { + const Edges& out_edges = reminst->getNode()->getOutEdges(); + Edges::const_iterator eit; + Node* n; + for (eit = out_edges.begin(); eit != out_edges.end(); ++eit) { + n = (*eit)->getTargetNode(); + Log::out() << " edge to node " + << n->getId() << " kind " << (*eit)->getKind() << std::endl; + } + } } - if (inst->getOpcode()==Op_IndirectMemoryCall) { - MethodDesc* md; - if (inst->getSrc(0)->getInst()->getOpcode()== Op_LdVar) { - md = inst->getSrc(0)->getType()->asMethodPtrType()->getMethodDesc(); +#endif + + reminst->unlink(); +#ifdef _DEBUG + if (_seinfo) { + Log::out() << " unlinked: "; + reminst->print(Log::out()); + Log::out() << std::endl; + } +#endif + if (targetnode != NULL) { + if (targetnode->getInEdges().size() > 1) { + fg.removeEdge(excedge); +#ifdef _DEBUG + if (_seinfo) { + Log::out() << " removed edge: " + << excedge->getSourceNode()->getId() << " -> " + << excedge->getTargetNode()->getId() << " kind " << excedge->getKind(); + Log::out() << std::endl; + } +#endif } else { - md = inst->getSrc(0)->getInst()->asMethodInst()->getMethodDesc(); + scannedObjs->clear(); + removeNode(targetnode); + scannedObjs->clear(); } - os << text << " "; md->printFullName(os); os << std::endl; } - return; } - scannedInsts->push_back(inst->getId()); - for (uint32 i=0; igetSrc(i)->getInst(); - if (!(Type::isTau(inst->getSrc(i)->getType()->tag))) - lObjectHistory(inst1,text+" ",os); - } -} // lObjectHistory(Inst* inst,std::string text,::std::ostream& os) +} // removeMonitorInsts(Insts* syncInsts) -void -EscAnalyzer::printCnGEdges(char* text,::std::ostream& os) { - CnGEdges* cge = cngEdges; - CnGEdges::iterator it; - CnGRefs::iterator it1; - std::string t1; - std::string t2; - os << " "<< text << std::endl; - if (cge==NULL) { - os <<" NULL"<< std::endl; - return; + +void +EscAnalyzer::removeNode(Node* node) { + const Edges& out_edges = node->getOutEdges(); + Edges::const_iterator eit; + Node* n; + +#ifdef _DEBUG + if (_seinfo) { + Log::out() << " to remove node " + << node->getId() << std::endl; + } +#endif + if (scannedObjs->size()!=0) { + if (checkScannedObjs(node->getId())) { + return; + } } - for (it = cge->begin( ); it != cge->end( ); it++ ) { - os << " from "; - printCnGNode((*it)->cngNodeFrom,os); - os << " to " << std::endl; - for (it1 = (*it)->refList->begin( ); it1 != (*it)->refList->end( ); it1++ ) { - os << " "; - os <<(*it1)->cngNodeTo->cngNodeId<<" ("; - switch ((*it1)->edgeType) { - case ET_POINT : t1="poi-"; break; - case ET_DEFER : t1="ref-"; break; - case ET_FIELD : t1="fld-"; break; - default : t1=" -"; - } - os <edgeType<<"), "; - printCnGNode(findCnGNode_id((*it1)->cngNodeTo->cngNodeId),os); - os << std::endl; + scannedObjs->push_back(node->getId()); + Nodes nodes2delete(irManager.getMemoryManager()); + for (eit = out_edges.begin(); eit != out_edges.end(); ++eit) { + n = (*eit)->getTargetNode(); + if (n->getInEdges().size() == 1) { + nodes2delete.push_back(n); } } -} // printCnGEdges(char* text,::std::ostream& os) - - -EscAnalyzer::CnGNode* -EscAnalyzer::findCnGNode_op(uint32 nId) { - CnGNodes::iterator it; - for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { - if ((*it)->opndId==nId && ((*it)->nodeType & (NT_OBJS|NT_LDVAL))) - return (*it); + Nodes::iterator iter = nodes2delete.begin(), end = nodes2delete.end(); + for (; iter != end; ++iter) { + n = (*iter); + removeNode(n); } - return(NULL); -} // findCnGNode_op(uint32 nId) - - -EscAnalyzer::CnGNode* -EscAnalyzer::findCnGNode_id(uint32 nId) { - CnGNodes::iterator it; - for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { - if ((*it)->cngNodeId==nId) - return (*it); + irManager.getFlowGraph().removeNode(node); + scannedObjs->pop_back(); +#ifdef _DEBUG + if (_seinfo) { + Log::out() << " removed node " + << node->getId() << std::endl; } - return(NULL); -} // findCnGNode_id(uint32 nId) +#endif +} // removeNode(Node* node) -EscAnalyzer::CnGNode* -EscAnalyzer::findCnGNode_in(uint32 nId) { - CnGNodes::iterator it; - for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { - if ((*it)->instrId==nId) - return (*it); - } - return(NULL); -} // findCnGNode_in(uint32 nId) +void +EscAnalyzer::fixSyncMethodMonitorInsts(Insts* syncInsts) { + SsaTmpOpnd* stThis = (SsaTmpOpnd*)insertReadJitHelperCall(); + insertFlagCheck(syncInsts,stThis,1); +} // fixSyncMethodMonitorInsts(Insts* syncInsts) -EscAnalyzer::CnGNode* -//EscAnalyzer::findCnGNode_mp(MethodDesc* md, uint32 nId) { -EscAnalyzer::findCnGNode_mp(uint32 iId, uint32 aId) { - CnGNodes::iterator it; - for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { - if ((*it)->instrId==iId && (*it)->argNumber==aId && - (*it)->nodeType == NT_ACTARG) - return (*it); - } - return(NULL); -} // findCnGNode_mp(uint32 iId, uint32 aId) +Opnd* +EscAnalyzer::insertReadJitHelperCall() { + ControlFlowGraph& fg = irManager.getFlowGraph(); + Node* oldBlock = fg.getEntryNode(); + Inst* inst_after = (Inst*)oldBlock->getFirstInst(); + TypeManager& _typeManager = irManager.getTypeManager(); + Type* typeInt32 = _typeManager.getInt32Type(); + OpndManager& _opndManager = irManager.getOpndManager(); + SsaTmpOpnd* stThis = _opndManager.createSsaTmpOpnd(typeInt32); + Node* newBlock = NULL; - -EscAnalyzer::CnGNode* -EscAnalyzer::findCnGNode_fl(Inst* inst, uint32 ntype) { - CnGNodes::iterator it; - FieldDesc* fd1; - FieldDesc* fd2; - uint32 idr = 0; - if (ntype==NT_INSTFLD) - idr=inst->getSrc(0)->getId(); - assert(inst->asFieldAccessInst()!=NULL); - fd1 = inst->asFieldAccessInst()->getFieldDesc(); - for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { - if ((*it)->nodeType==ntype) { - assert(((Inst*)((*it)->refObj))->asFieldAccessInst()!=NULL); - fd2 = ((Inst*)((*it)->refObj))->asFieldAccessInst()->getFieldDesc(); - if ( fd1->getParentType()==fd2->getParentType() && - strcmp(fd1->getName(),fd2->getName())==0) { - if (ntype==NT_INSTFLD) { - uint32 idf=((Inst*)((*it)->refObj))->getSrc(0)->getId(); - if (idr!=idf) { #ifdef _DEBUG - if (_cngedges) { - Log::out() - << "++++ findCnGNode_fl: required " << idr - << " - found " << idf << " not found" << std::endl; - } + if (_seinfo) { + Log::out() << "++++ insertRJHC: before" << std::endl; + FlowGraph::print(Log::out(),oldBlock); + Log::out() << "++++ insertRJHC: before end" << std::endl; + } #endif - continue; - } + // insert jit helper call + Opnd** args = NULL; + InstFactory& instfactory = irManager.getInstFactory(); + Inst* jhcinst = instfactory.makeJitHelperCall( + stThis, ReadThisState, 0, args); + jhcinst->insertAfter(inst_after); + newBlock = fg.splitNodeAtInstruction(jhcinst,true, false,instfactory.makeLabel()); + fg.addEdge(oldBlock,fg.getUnwindNode()); + insertLdConst(0); #ifdef _DEBUG - if (_cngedges) { - Log::out() - << "++++ findCnGNode_fl: required " << idr - << " - found " << idf << std::endl; - } + if (_seinfo) { + Log::out() << "++++ insertRJHC: after" << std::endl; + FlowGraph::print(Log::out(),oldBlock); + FlowGraph::print(Log::out(),newBlock); + Log::out() << "++++ insertRJHC: after end" << std::endl; + } #endif - } - return (*it); - } - } - } - return(NULL); -} // findCnGNode_fl(Opnd* opnd, uint32 ntype) + insertSaveJitHelperCall((Inst*)(newBlock->getFirstInst()),i32_0); // to restore default value + return stThis; +} // insertReadJitHelperCall() -/** - * Creates edge if it doesn't exist yet. - */ void -EscAnalyzer::addEdge(CnGNode* cgnfrom, CnGNode* cgnto, - uint32 etype, Inst* inst) { - CnGEdges::iterator it; - CnGRefs* el; - CnGRef* ref; - CnGNode* cgn1=cgnfrom; - CnGNode* cgn2=cgnto; - bool done = false; +EscAnalyzer::checkCallSyncMethod() { + CnGNodes::iterator it; + CnGRefs::iterator it2; + CnGNode* node; + CnGNode* aanode; + MethodDesc* md; + CalleeMethodInfo* mtdInfo; + uint32 callee_state; - if (cgnfrom->lNode) { - cgn1=findCnGNode_id(cgnfrom->lNode->cngNodeId); - assert(cgn1!=NULL); - } - + for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { + node = (*it); + if (node->nodeType == NT_ACTARG && node->argNumber == 0) { + md = (MethodDesc*)(node->refObj); + if (md->isSynchronized() && node->nInst->getOpcode()==Op_DirectCall) { + const char* ch1 = md->getParentType()->getName(); + const char* ch2 = md->getName(); + const char* ch3 = md->getSignatureString(); + mtdInfo = getMethodInfo(ch1,ch2,ch3); + if (mtdInfo==NULL) { + callee_state = 0; #ifdef _DEBUG - if (_cngedges) { - Log::out() - << "++++ addEdge: " << cgnfrom->cngNodeId << "-" << cgnfrom->opndId - << " ( "<cngNodeId << "-" << cgn1->opndId << " ) to " - << cgnto->cngNodeId << "-" << cgnto->opndId << " ( " - << cgn2->cngNodeId << "-" << cgn2->opndId << " )" << std::endl; - } + if (_seinfo) { + Log::out() << "=- Methodinfo is NULL"; + Log::out() << std::endl; + } #endif - if (cgn1==cgn2) { + } else { + callee_state = getMethodParamState(mtdInfo,0); + } #ifdef _DEBUG - if (_cngedges) { - Log::out() << "+++++++ equal " - << cgnfrom->cngNodeId<< "-" << cgnfrom->opndId - << " ( "<cngNodeId << "-" << cgn1->opndId << " ) to " - << cgnto->cngNodeId << "-" << cgnto->opndId << " ( " - << cgn2->cngNodeId << "-" << cgn2->opndId << " )" << std::endl; - } + if (_seinfo) { + Log::out() << "---- checkCallSyncMethod:" << std::endl; + node->nInst->print(Log::out()); + Log::out() << std::endl; + printCnGNode(node,Log::out()); + Log::out() << std::endl; + if (node->outEdges != NULL) { + for (it2 = node->outEdges->begin(); it2 != node->outEdges->end(); it2++ ) { + Log::out() << " ccsm: "; + printState(callee_state); + Log::out() << " "; + printCnGNode((*it2)->cngNodeTo,Log::out()); + Log::out() << std::endl; + } + } + Log::out() << "++++ checkCallSyncMethod: "; + Log::out() << " instance: " << md->isInstance() << + " initializer: " << md->isInstanceInitializer() << " end" << std::endl; + } #endif - return; - } - for ( it = cngEdges->begin( ); it != cngEdges->end( ); it++ ) { - if ((*it)->cngNodeFrom == cgn1) { - CnGRefs::iterator itr; - if (etype==ET_FIELD || cgn1->nodeType==NT_ACTARG) { - for ( itr = (*it)->refList->begin( ); itr != (*it)->refList->end( ); itr++ ) { - if ((*itr)->cngNodeTo == cgn2) { + if (callee_state == 0) + callee_state = GLOBAL_ESCAPE; + if (!isGlobalState(callee_state)) { + assert(node->outEdges->size()==1); + aanode = node->outEdges->front()->cngNodeTo; + if (!isGlobalState(aanode->state)&& + (aanode->nodeType==NT_OBJECT||aanode->nodeType==NT_RETVAL)) { #ifdef _DEBUG - if (_cngedges) { - Log::out() << "++++ addEdge: ET_FIELD || cgn1-> ==NT_ACTARG && *->cngNodeTo == cgn2" << std::endl; + if (_seinfo) { + Log::out() + << "=-=- sm this.agr.saving" << std::endl; } #endif - return; + insertLdConst(1); + insertSaveJitHelperCall(node->nInst,i32_1); +#ifdef _DEBUG + if (_seinfo) { + Log::out() + << " checkCSM: this was saved" + << std::endl; + } + } else { + if (_seinfo) { + Log::out() + << " checkCSM: this wasn't saved" + << std::endl; + } +#endif } } - } else { -/* for ( itr = (*it)->refList->begin( ); itr != (*it)->refList->end( ); itr++ ) - if ((*itr)->cngNodeTo == cgn2) { // needed edge exists - done = true; -#ifdef _DEBUG - if (_cngedges) { - Log::out() << "++++ addEdge: needed edge exists" << std::endl; - } -#endif - }--nvg */ } - if (!done) { - ref = new (eaMemManager) CnGRef; - ref->cngNodeTo=cgn2; - ref->edgeType=etype; - ref->edgeInst=inst; - (*it)->refList->push_back(ref); + } + } +} // checkCallSyncMethod() + + +void +EscAnalyzer::insertSaveJitHelperCall(Inst* inst_before, SsaTmpOpnd* stVal) { + Node* icBlock = stVal->getInst()->getNode(); + Node* oldBlock = inst_before->getNode(); + ControlFlowGraph& fg = irManager.getFlowGraph(); + #ifdef _DEBUG - if (_cngedges) { - Log::out() << "++++ addEdge: added CnGRef" << std::endl; - } + if (_seinfo) { + Log::out() << "++++ insertSJHC: before" << std::endl; + if (icBlock != oldBlock) + FlowGraph::print(Log::out(),icBlock); + FlowGraph::print(Log::out(),oldBlock); + Log::out() << "++++ insertSJHC: before end" << std::endl; + } #endif - } - return; - } + // create jit helper call + Opnd* args[1] = {stVal}; + InstFactory& instfactory = irManager.getInstFactory(); + Inst* jhcinst = instfactory.makeJitHelperCall( + OpndManager::getNullOpnd(), SaveThisState, 1, args); + // insert jit helper + if (inst_before->getNode()->getFirstInst() == inst_before) { + jhcinst->insertAfter(inst_before); + } else { + jhcinst->insertBefore(inst_before); } - ref = new (eaMemManager) CnGRef; - ref->cngNodeTo=cgn2; - ref->edgeType=etype; - ref->edgeInst=inst; - CnGEdge* cgedge=new (eaMemManager) CnGEdge; - el=new CnGRefs(eaMemManager); - cgedge->cngNodeFrom=cgn1; - el->push_back(ref); - cgedge->refList=el; - cngEdges->push_back(cgedge); - cgn1->outEdges=el; + Node* newBlock = fg.splitNodeAtInstruction(jhcinst, true, false, instfactory.makeLabel()); + // add dispatch edge to oldBlock + fg.addEdge(oldBlock,fg.getUnwindNode()); #ifdef _DEBUG - if (_cngedges) { - Log::out() << "++++ addEdge: added edge" << std::endl; + if (_seinfo) { + Log::out() << "++++ insertSJHC: after" << std::endl; + if (icBlock != oldBlock) + FlowGraph::print(Log::out(),icBlock); + FlowGraph::print(Log::out(),oldBlock); + FlowGraph::print(Log::out(),newBlock); + Log::out() << "++++ insertSJHC: after end" << std::endl; } #endif +} // insertSaveJitHelperCall(Inst* inst_before, SsaTmpOpnd* stVal) -} // addEdge(CnGNode* cgnfrom, CnGNode* cgnto, uint32 etype, Inst* inst) +SsaTmpOpnd* +EscAnalyzer::insertLdConst(uint32 value) { + TypeManager& _typeManager = irManager.getTypeManager(); + Type* typeInt32 = _typeManager.getInt32Type(); + OpndManager& _opndManager = irManager.getOpndManager(); + InstFactory& _instFactory = irManager.getInstFactory(); + Inst* ildc = NULL; + if (value == 0) + if (i32_0 == NULL) { + i32_0 = _opndManager.createSsaTmpOpnd(typeInt32); + ildc = _instFactory.makeLdConst(i32_0, 0); + } + if (value == 1) + if (i32_1 == NULL) { + i32_1 = _opndManager.createSsaTmpOpnd(typeInt32); + ildc = _instFactory.makeLdConst(i32_1, 1); + } + if (ildc != NULL) { + ildc->insertAfter(irManager.getFlowGraph().getEntryNode()->getFirstInst()); + } + if (value == 0) + return i32_0; + return i32_1; +} // insertLdConst(uint32 value) -/* + + +/* **************************************** Scalar replacement optimization -*/ +**************************************** */ void EscAnalyzer::scanLocalObjects() { @@ -4578,7 +4615,7 @@ prTitle = false; } lo_count++; // number of local objects - stnode = checkCnG(*it,true); + stnode = checkCnGtoScalarize(*it,true); if (stnode != NULL) { if (stnode->nodeType == NT_OBJECT) { if (lnoids == NULL) { @@ -4687,8 +4724,8 @@ CnGNodes::iterator it; uint32 vco_count=0; // number of local objects uint32 ob_ref_type=0; // object ref type - ObjIds* lnoids = NULL; // list of new opnds to optimize - ObjIds* lloids = NULL; // list of load opnds to optimize + ObjIds* lnoids = NULL; // list of CnG node Ids for new opnds to optimize + ObjIds* lloids = NULL; // list of CnG node Ids for load opnds to optimize ObjIds::iterator lo_it; bool prTitle = true; CnGNode* stnode = NULL; @@ -4714,7 +4751,7 @@ prTitle = false; } - stnode = checkCnG(*it,false); + stnode = checkCnGtoScalarize(*it,false); if (stnode != NULL) { if (stnode->nodeType == NT_OBJECT) { if (lnoids == NULL) { @@ -4903,7 +4940,7 @@ sco->fldVarOpnd = fl_var_opnd; if (_scinfo) { - os_sc<<" PoitedType "; fl_type1->print(os_sc); os_sc <print(os_sc); os_sc <print(os_sc); os_sc <isReference()) { @@ -5039,7 +5076,7 @@ if (lobj_opt) { #ifdef _DEBUG if (_scinfo) { - findObject1(onode->nInst); + printOriginObject1(onode->nInst); } #endif if (onode->nInst->getOpcode() != Op_LdVar) { @@ -5289,7 +5326,6 @@ _instFactory.makeStVar(ob_var_opnd,ob_init_opnd)->insertBefore(nobj_inst); if (lobj_opt) { _instFactory.makeStVar(ob_flag_opnd, i32_1)->insertAfter(lonode->nInst); -// _instFactory.makeLdNull(ob_init_opnd)->insertBefore(nobj_inst); _instFactory.makeStVar(ob_var_opnd,(Opnd*)(lonode->refObj))->insertAfter(lonode->nInst); } if (methodEndInsts->size()!=0) @@ -5524,7 +5560,6 @@ if (!check_loc) if (opcode == Op_IndirectMemoryCall || opcode == Op_DirectCall) continue; - if (_scinfo) { os_sc << " no remove " << opnd->getId() << std::endl; } @@ -5535,11 +5570,16 @@ os_sc << " lo "; FlowGraph::printLabel(os_sc,inst->getNode()); os_sc << " "; inst->print(os_sc); os_sc << std::endl; } - if (opcode == Op_Branch || opcode == Op_TauCheckNull - || opcode == Op_TauIsNonNull || opcode == Op_TauHasType) { + if (opcode == Op_Branch) { checkInsts->push_back(inst); continue; } + if (opcode == Op_TauCheckNull || opcode == Op_TauIsNonNull || opcode == Op_TauHasType) { + if (checkTauOpnd(inst)) { + checkInsts->push_back(inst); + continue; + } + } if (opcode == Op_MethodEnd) { methodEndInsts->push_back(inst); continue; @@ -5575,6 +5615,81 @@ bool +EscAnalyzer::checkTauOpnd(Inst* tau_inst) { + const Nodes& nodes = irManager.getFlowGraph().getNodes(); + Nodes::const_iterator niter; + bool maydo = true; + uint32 tau_opnd_id = tau_inst->getDst()->getId(); + uint32 sc_opnd_id = tau_inst->getSrc(0)->getId(); + Inst* inst1; + + if (_scinfo) { + os_sc << " -------- Check tau opnd " << std::endl; + } + 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()) { + if (inst->getOpcode() == Op_InitObj) { + if (_scinfo) { + os_sc << " Op_InitObj: "; + inst->print(os_sc); os_sc << std::endl; + } + } + uint32 nsrc = inst->getNumSrcOperands(); + for (uint32 i=0; igetSrc(i))->isSsaOpnd()) // check ssa operands + continue; + if (opnd->getId()==tau_opnd_id) { + uint32 opcode=inst->getOpcode(); + if (_scinfo) { + os_sc << " "; FlowGraph::printLabel(os_sc,inst->getNode()); + os_sc << " "; inst->print(os_sc); os_sc << std::endl; + if (opcode == Op_IndirectMemoryCall || opcode == Op_DirectCall) { + MethodDesc* md = getMD(inst); + if (md->isNative()) + os_sc << " native " << std::endl; + if (opcode==Op_IndirectMemoryCall) { + os_sc << " ";md->printFullName(os_sc); os_sc << std::endl; + } + } + } + if (opcode == Op_IndirectMemoryCall || opcode == Op_DirectCall) { + for (uint32 i1=0; i1getSrc(i)->getId() == sc_opnd_id) + break; + if (i1 == nsrc) { + maydo = false; + } + } + } + if (opcode == Op_TauLdInd || opcode == Op_TauStInd) { + if (opcode == Op_TauLdInd) + inst1 = inst->getSrc(0)->getInst(); + else + inst1 = inst->getSrc(1)->getInst(); + if (inst1->getOpcode() != Op_LdFieldAddr) + maydo = false; + if (inst1->getSrc(0)->getId() != sc_opnd_id) + maydo = false; + if (_scinfo) { + os_sc << " "; FlowGraph::printLabel(os_sc,inst1->getNode()); + os_sc << " "; inst1->print(os_sc); os_sc << std::endl; + } + } + if (maydo == false) { + return maydo; + } + } + } + } + } + return maydo; +} // checkTauOpnd(Inst* tau_inst) + + +bool EscAnalyzer::checkOpndUsage(uint32 lobjid) { const Nodes& nodes = irManager.getFlowGraph().getNodes(); Nodes::const_iterator niter; @@ -5631,7 +5746,7 @@ EscAnalyzer::CnGNode* -EscAnalyzer::checkCnG(CnGNode* scnode, bool check_loc) { +EscAnalyzer::checkCnGtoScalarize(CnGNode* scnode, bool check_loc) { uint32 ob_ref_type=0; // object ref type uint32 ob_fld_count=0; // number of object references to fields uint32 ob_fin_fld_count=0; // number of object references to final fields @@ -5816,7 +5931,7 @@ CnGNode* lobj = getLObj(vnode); // scalarizable load object if (lobj != NULL) { if (_scinfo) { - findObject1(lobj->nInst," "); + printOriginObject1(lobj->nInst," "); } bool notnullsrcs = checkVVarSrcs(lobj->nInst); if (_scinfo) { @@ -5829,7 +5944,7 @@ os_sc << "----check srcs opernds for optimized load object (cng node): " << lobj->cngNodeId << std::endl; } - rnode = checkCnG(lobj,check_loc); + rnode = checkCnGtoScalarize(lobj,check_loc); if (rnode!=NULL) { storeId =true; } @@ -5913,7 +6028,7 @@ } return NULL; -} // checkCnG(CnGNode* scnode, bool check_loc) +} // checkCnGtoScalarize(CnGNode* scnode, bool check_loc) double @@ -5949,7 +6064,7 @@ double -EscAnalyzer::checkNextNodes(Node* n, uint32 obId, double cprob, std::string text) { +EscAnalyzer::checkNextNodes(Node* n, uint32 obId, double cprob) { Node* node = n; Inst *headInst = (Inst*)node->getFirstInst(); Opnd* opnd; @@ -5966,21 +6081,9 @@ } return r; } -#ifdef _DEBUG -/* if (_scinfo) { - os_sc << text << " From node : "; FlowGraph::printLabel(os_sc,node); - os_sc << " id." << node->getId() - << " execCount " << node->getExecCount() - << " in prob " << cprob << std::endl; - }*/ -#endif + if (scannedObjs->size()!=0) { if (checkScannedObjs(node->getId())) { -#ifdef _DEBUG -/* if (_scinfo) { - os_sc << text << " . . . " << std::endl; - }*/ -#endif if (scannedSucNodes->size()!=0) { if (checkScannedSucNodes(node->getId())) return cprob; @@ -5992,19 +6095,6 @@ return no; // node scan is not completed } } -#ifdef _DEBUG -/* const Edges &out_edges = node->getOutEdges(); - if (_scinfo) { - for (eit = out_edges.begin(); eit != out_edges.end(); ++eit) { - double ecount = (*eit)->getTargetNode()->getExecCount(); - double prob = (*eit)->getEdgeProb(); - os_sc << text << " edge to : "; FlowGraph::printLabel(os_sc,(*eit)->getTargetNode()); - os_sc << " id." << (*eit)->getTargetNode()->getId() - << " execCount " << ecount << " edgeProb " << prob << " edgeKind " - << (*eit)->getKind() << std::endl; - } - }*/ -#endif for (Inst* inst=headInst->getNextInst();inst!=NULL;inst=inst->getNextInst()) { if (inst->getOpcode()==Op_IndirectMemoryCall || inst->getOpcode()==Op_DirectCall) { uint32 nsrc = inst->getNumSrcOperands(); @@ -6028,34 +6118,13 @@ double r2=-1; if ((tn1=node->getUnconditionalEdgeTarget())!=NULL) { - r0 = checkNextNodes(tn1,obId,r,text+" "); -#ifdef _DEBUG -/* if (_scinfo) { - os_sc << text << " "; FlowGraph::printLabel(os_sc,node); - os_sc << " id." << node->getId() - << " uncon. returned prob " << r0 << std::endl; - }*/ -#endif + r0 = checkNextNodes(tn1,obId,r); } else { if ((tn1=node->getTrueEdgeTarget())!=NULL) { - r1 = checkNextNodes(tn1,obId,r,text+" "); -#ifdef _DEBUG -/* if (_scinfo) { - os_sc << text << " "; FlowGraph::printLabel(os_sc,node); - os_sc << " id." << node->getId() - << " true returned prob " << r1 << std::endl; - }*/ -#endif + r1 = checkNextNodes(tn1,obId,r); } if ((tn2=node->getFalseEdgeTarget())!=NULL) { - r2 = checkNextNodes(tn2,obId,r,text+" "); -#ifdef _DEBUG -/* if (_scinfo) { - os_sc << text << " "; FlowGraph::printLabel(os_sc,node); - os_sc << " id." << node->getId() - << " false returned prob " << r2 << std::endl; - }*/ -#endif + r2 = checkNextNodes(tn2,obId,r); } if (r1==-1 && r2==-1) r0=no; @@ -6072,7 +6141,7 @@ return r0; return r; -} // checkNextNodes(Node* n, uint32 obId, double cprob, std::string text)) +} // checkNextNodes(Node* n, uint32 obId, double cprob)) void @@ -6086,7 +6155,8 @@ Node* node_before = NULL; // node with call inst before opt Node* node_obj = NULL; // node with restored newobj after opt Node* node_obj1 = NULL; // node with restored obj fields init after opt - Node* node_var = NULL; // node with call inst after opt + Node* node_var = NULL; // node with call inst after opt or chknull tau + Node* node_var1 = NULL; // node with call inst after opt Node* node_after1 = NULL; // node with field var opnds updating after call ScObjFlds::iterator ito; const bool splitAfter = true; @@ -6123,10 +6193,58 @@ ldobj->insertBefore(vc); // reset call inst parameters Inst* old_newobj = vc->getSrc(i)->getInst(); - for (uint32 i1=i; i1getSrc(i1)->getId()==oid) { vc->setSrc(i1,ob_opnd ); } + if (Type::isTau(vc->getSrc(i1)->getType()->tag)) { + Inst* tau_inst = NULL; + Insts::iterator iit; + uint32 to_id = vc->getSrc(i1)->getId(); + for (iit=checkInsts->begin(); iit!=checkInsts->end(); iit++) { + if ((*iit)->getDst()->isNull()) { + continue; + } + if ((*iit)->getDst()->getId()!=to_id) { + continue; + } + + Inst* ti = *iit; + uint32 ti_oc = ti->getOpcode(); + if (ti_oc == Op_TauCheckNull || ti_oc == Op_TauIsNonNull || ti_oc == Op_TauHasType) { + tau_inst = NULL; + SsaTmpOpnd* to = _opndManager.createSsaTmpOpnd(_typeManager.getTauType()); + if (ti_oc == Op_TauCheckNull) { + tau_inst = _instFactory.makeTauCheckNull(to,ob_opnd); + } + if (ti_oc == Op_TauIsNonNull) { + tau_inst = _instFactory.makeTauIsNonNull(to,ob_opnd); + } + if (ti_oc == Op_TauHasType) { + tau_inst = _instFactory.makeTauHasType(to,ob_opnd,ti->asTypeInst()->getTypeInfo()); + } + if (tau_inst != NULL) { + break; + } + } + } + if (tau_inst == NULL) { + continue; + } + if (_scinfo) { + os_sc << "---- tau_inst can throw " << tau_inst->getOperation().canThrow() << " "; + tau_inst->print(os_sc); os_sc << std::endl; + os_sc << std::endl; + } + tau_inst->insertBefore(vc); + vc->setSrc(i1,tau_inst->getDst()); + if (tau_inst->getOperation().canThrow() == true) { + node_var1=fg.splitNodeAtInstruction(tau_inst,splitAfter,false, + _instFactory.makeLabel()); + fg.addEdge(tau_inst->getNode(),fg.getUnwindNode()); + } + } + } // adding newobj inst SsaTmpOpnd* nob_opnd = _opndManager.createSsaTmpOpnd(ob_var_opnd->getType()); @@ -6243,6 +6361,9 @@ FlowGraph::print(os_sc,node_obj1); } FlowGraph::print(os_sc,node_var); + if (node_var1 != NULL) { + FlowGraph::print(os_sc,node_var1); + } if (node_after1 != NULL) { FlowGraph::print(os_sc,node_after1); } @@ -6536,9 +6657,6 @@ } Inst* inst = (*iit); uint32 opcode = inst->getOpcode(); - if (opcode == Op_TauCheckNull) { - removeInst(inst); - } if (opcode == Op_Branch) { excedge = NULL; if (inst->getComparisonModifier()==Cmp_Zero) { @@ -6557,7 +6675,7 @@ removeInst(inst); } } - if (opcode == Op_TauIsNonNull) { + if (opcode == Op_TauIsNonNull || opcode == Op_TauCheckNull || opcode == Op_TauHasType) { if (inst->getOperation().canThrow()==true) { excedge = (Edge*)inst->getNode()->getExceptionEdge(); if (_scinfo) { @@ -6568,17 +6686,6 @@ } removeInst(inst); } - if (opcode == Op_TauHasType) { - if (inst->getOperation().canThrow()==true) { - excedge = (Edge*)inst->getNode()->getExceptionEdge(); - if (_scinfo) { - os_sc <<"-- exc edge to "; - ((Inst*)(excedge->getTargetNode()->getLabelInst()))->print(os_sc); - os_sc << std::endl; - } - } - removeInst(inst); - } } } // fixCheckInsts(uint32 opId) @@ -6595,7 +6702,7 @@ if (_scinfo) { os_sc << "########################" << std::endl; printCnGNode(onode,os_sc); os_sc << std::endl; - checkOpndUsage(onode->opndId); +// checkOpndUsage(onode->opndId); // to collect stind & ldind instructions scObjFlds->clear(); collectStLdInsts(onode, scObjFlds); @@ -6716,4 +6823,3 @@ } //namespace Jitrino - Index: vm/jitrino/src/optimizer/escanalyzer.h =================================================================== --- vm/jitrino/src/optimizer/escanalyzer.h (revision 532241) +++ vm/jitrino/src/optimizer/escanalyzer.h (working copy) @@ -32,16 +32,46 @@ namespace Jitrino { -// -// Escape analyzer (synchronization removing) -// +/** + * Performs escape analysis for the compiled method. + * Creates data connection graph, sets states (local, argument escaped, global escaped) + * for objects created in compiled method, runs escape analysis related optimizations: + * - monitor elimination optimization; + * - scalar replacement optimization. + * Saves information about method arguments and return value states for future usage. + */ + class EscAnalyzer { public: +/** + * Creates EscAnalyzer class for compiled method. + * @param mm - memory manager, + * @param argSource - session action, + * @param irm - compiled method IR manager. + */ EscAnalyzer(MemoryManager& mm, SessionAction* argSource, IRManager& irm); +/** + * Performs escape analysis and runs escape analysis related optimizations. + */ void doAnalysis(); + // read from command line to output debug information + uint32 allProps; + +private: +/** + * Creates EscAnalyzer class for callee method escape analysis. + * @param parent - parent (caller method) EscAnalyzer class + * @param irm - compiled method IR manager. + */ + EscAnalyzer(EscAnalyzer* parent, IRManager& irm); + + // initial level to start callee method escape analysis + static const int maxMethodExamLevel_default = 0; + + // Connection Graph Structure // CnG node types static const uint32 NT_OBJECT = 8; // Op_LdRef,Op_NewObj,Op_NewArray,Op_NewMultiArray static const uint32 NT_DEFARG = NT_OBJECT+1; // formal parameter - Op_DefArg @@ -53,7 +83,7 @@ static const uint32 NT_VARVAL = NT_LDOBJ+2; // Op_StVar,Op_Phi static const uint32 NT_ARRELEM = NT_LDOBJ+3; // Op_LdArrayBaseAddr,Op_AddScaledIndex static const uint32 NT_REF = NT_LDOBJ+4; // reference value - Op_LdFieldAddr, - // Op_LdStaticAddr + // Op_LdStaticAddr, Op_TauCast, Op_TauStaticCast static const uint32 NT_STFLD = 64; // Op_LdStaticAddr static const uint32 NT_INSTFLD = NT_STFLD+1; // Op_LdFieldAddr static const uint32 NT_ACTARG = 128; // Op_DirectCall,Op_IndirectMemoryCall @@ -80,7 +110,6 @@ static const uint32 CALLEE_ESCAPED = 16; static const uint32 VIRTUAL_CALL = 32; - typedef StlList NodeMDs; struct CnGNode; struct CnGRef { @@ -91,7 +120,9 @@ typedef StlList CnGRefs; typedef StlList Insts; + typedef StlList NodeMDs; + // connection graph node structure struct CnGNode { uint32 cngNodeId; // CnG node id uint32 opndId; // opnd id (0 for NT_ACTARG) @@ -99,8 +130,7 @@ uint32 nodeType; // CnG node types uint32 nodeRefType; // CnG node reference types uint32 instrId; - CnGNode* lNode; // ldind from lNode - Node* fgNode; + CnGNode* lNode; // ldind from lNode for ldflda & ldsflda uint32 state; // escape state NodeMDs* nodeMDs; // list of NT_ACTARG nodes Inst* nInst; // ref to inst @@ -131,7 +161,8 @@ typedef StlList ParamInfos; - struct CalledMethodInfo { + // structure of saved by EA information about compiled method + struct CalleeMethodInfo { MemberIdent* methodIdent; uint32 numberOfArgs; uint32 properties; // native, final, virtual ... @@ -140,170 +171,425 @@ bool mon_on_this; }; - typedef StlList CalledMethodInfos; + // list of saved by EA information about compiled methods + typedef StlList CalleeMethodInfos; - struct MonUnit { - uint32 opndId; - Insts* monInsts; - Insts* icallInsts; + // connection graph edge structure + struct CnGEdge { + CnGNode* cngNodeFrom; + CnGRefs* refList; }; - MemoryManager& eaMemManager; + // list of connection graph nodes definition + typedef StlList CnGNodes; + // list of connection graph edges definition + typedef StlList CnGEdges; + // list of object Ids definition + typedef StlList ObjIds; - static CalledMethodInfos* calledMethodInfos; - static Mutex calledMethodInfosLock; + + static CalleeMethodInfos* calleeMethodInfos; + static Mutex calleeMethodInfosLock; - uint32 allProps; + // variables to read command line options const char* debug_method; bool do_sync_removal; + bool do_sync_removal_vc; + bool do_sync_removal_sm; bool do_scalar_repl; bool do_esc_scalar_repl; bool do_scalar_repl_only_final_fields; bool scalarize_final_fields; const char* execCountMultiplier_string; double ec_mult; + bool print_scinfo; bool compressedReferencesArg; // for makeTauLdInd -private: - static const int maxMethodExamLevel_default = 0; + TranslatorAction* translatorAction; - struct CnGEdge { - CnGNode* cngNodeFrom; - CnGRefs* refList; - }; - - typedef StlList CnGNodes; - typedef StlList CnGEdges; - - struct cfgNode { - uint32 nodeId; - Node* fgNode; - Insts* instructions; - }; - - typedef StlList ObjIds; - - typedef StlList MonInstUnits; - - EscAnalyzer(EscAnalyzer* parent, IRManager& irm); - - uint32 maxMethodExamLevel; + MemoryManager& eaMemManager; IRManager& irManager; MethodDesc& mh; // analyzed method header + CompilationInterface &compInterface; + + // list of connection graph nodes CnGNodes* cngNodes; + // list of connection graph edges CnGEdges* cngEdges; + // list of instructions for edge creation + Insts* exam2Insts; + + // maximum level to analyze callee methods (from command line or default set) + uint32 maxMethodExamLevel; + // set level for escape analysis + uint32 method_ea_level; + uint32 lastCnGNodeId; uint32 curMDNode; int defArgNumber; - uint32 method_ea_level; + uint32 initNodeType; // type of initial scanned node + + // lists to help do CFG scan ObjIds *scannedObjs; ObjIds *scannedObjsRev; ObjIds *scannedInsts; ObjIds *scannedSucNodes; - uint32 initNodeType; // type of initial scanned node - MonInstUnits* monitorInstUnits ; + + // format 32 0 operand used by the optimizations SsaTmpOpnd* i32_0; + // format 32 1 operand used by the optimizations SsaTmpOpnd* i32_1; - TranslatorAction* translatorAction; + + // list of Op_MethodEnd instructions (for scalar replacement optimization) Insts* methodEndInsts; + // list of Op_Branch and Op_TauCheckNull instructions (for scalar replacement optimization) Insts* checkInsts; - std::ostream& os_sc; - bool print_scinfo; + // variable used to output debug information + int _cfgirun; + int _instrInfo; + int _instrInfo2; + int _cngnodes; + int _cngedges; + int _scanMtds; + int _setState; + int _printstat; + int _eainfo; + int _seinfo; + int _scinfo; +#define prsNum 10 + int prsArr[prsNum]; - struct ScObjFld { - VarOpnd* fldVarOpnd; - Insts* ls_insts; - FieldDesc* fd; - bool isFinalFld; - }; - typedef StlList ScObjFlds; - -#ifdef _DEBUG - void prPrN(cfgNode pr_n[],int maxInd) { - Log::out()<<"--------------------"<getId(); - Log::out() <NULL. + */ + CnGNode* findCnGNode_op(uint32 nId); + +/** + * Finds CnG node for specified CnG node Id. + * @param nId - CnG node Id. + * @return found CnGnode, or NULL. + */ CnGNode* findCnGNode_id(uint32 nId); - CnGNode* findCnGNode_op(uint32 nId); + +/** + * Finds CnG node for specified instruction Id. + * @param nId - instruction Id. + * @return found CnGnode, or NULL. + */ CnGNode* findCnGNode_in(uint32 nId); + +/** + * Finds NT_ACTARG CnG node for specified instruction Id and argument number. + * @param iId - instruction Id, + * @param aId - argument number. + * @return found CnGnode, or NULL. + */ CnGNode* findCnGNode_mp(uint32 iId, uint32 aId); + +/** + * Finds field CnG node for specified instruction and CnG node type. + * @param inst - instruction, + * @param ntype - CnG node type. + * @return found CnGnode, or NULL. + */ CnGNode* findCnGNode_fl(Inst* inst, uint32 ntype); - void printCnGNodeRefs(CnGNode* cgn, std::string text,::std::ostream& os); - void printRefInfo(::std::ostream& os); - void addInst(cfgNode* cfgn, Inst* inst); - void scanCnGNodeRefsGE(CnGNode* cgn, bool check_var_src, bool check_field_elem=true); -// void scanCnGNodeRefsEV(CnGNode* cgn); -// void scanCnGNodeRefsDA(CnGNode* cgn); - void scanCnGNodeRefsAE(CnGNode* cgn, bool check_var_src, bool check_field_elem=true); + +/** + * Creates new CnG edge for specified instruction, adds it to cngEdges and + * cgnfrom->outEdges lists. + * @param cgnfrom - CnG node from, + * @param cgnto - CnG node to, + * @param etype - edge type, + * @param inst - instruction. + * @return created CnGnode. + */ + void addEdge(CnGNode* cgnfrom, CnGNode* cgnto, uint32 etype, Inst* inst); + +/** + * Sets escape state for method created objects. + */ + void setCreatedObjectStates(); + +/** + * Scans CnG nodes beginning with specified node to set + * GLOBAL_ESCAPE or VIRTUAL_CALL states. + * @param cgnfrom - CnG node to begin scan, + * @param check_var_src - sign to check variable operands. + */ + void scanCnGNodeRefsGE(CnGNode* cgn, bool check_var_src); + +/** + * Scans CnG nodes beginning with specified node to set + * ARG_ESCAPE states. + * @param cgnfrom - CnG node to begin scan, + * @param check_var_src - sign to check variable operands. + */ + void scanCnGNodeRefsAE(CnGNode* cgn, bool check_var_src); + +/** + * Scans connection graph nodes beginning with specified not global escaped node to set + * corresponding state to array elements and fields values. + * @param node - connection graph node to begin scan. + */ + void checkSubobjectStates(CnGNode* node); + +/** + * Scans connection graph nodes specified NT_EXITVAL node refers to. + * @param node - NT_EXITVAL connection graph node. + * @return GLOBAL_ESCAPE, if any of nodes node reference to is GLOBAL_ESCAPE, otherwise + * ARG_ESCAPE, if any of nodes node reference to is ARG_ESCAPE, otherwise + * NO_ESCAPE. + */ + uint32 getSubobjectStates(CnGNode* node); + +/** + * Finds specified method escape analysis information in the common repository and compiles + * the method if it is required and possible. + * @param md - method description, + * @param inst - method call instruction. + * @return method info, if it was found, NULL - otherwise. + */ + CalleeMethodInfo* findMethodInfo(MethodDesc* md,Inst* inst); + +/** + * Finds specified method escape analysis information in the common repository. + * @param ch1 - method package name, + * @param ch2 - method name, + * @param ch3 - method signature. + * @return method info, if it was found, NULL - otherwise. + */ + CalleeMethodInfo* getMethodInfo(const char* ch1,const char* ch2,const char* ch3); + +/** + * Runs escape analysis for direct call method. + * @param call - direct call instruction. + */ void scanCalleeMethod(Inst* call); + +/** + * Runs translator session for callee method. + * @param inlineCC - compilation interface. + */ + void runTranslatorSession(CompilationContext& inlineCC); + +/** + * Runs optimizations for callee method. + * @param irManager - IR manager. + */ void optimizeTranslatedCode(IRManager& irManager); - void setCreatedObjectStates(); - void printCreatedObjectsInfo(::std::ostream& os); -// void printLocalObjectsInfo(::std::ostream& os); //nvg - void printMethodInfos(); //? - void printMethodInfo(CalledMethodInfo* mi); - CalledMethodInfo* getMethodInfo(const char* ch1,const char* ch2,const char* ch3); - CalledMethodInfo* findMethodInfo(MethodDesc* md,Inst* inst); + +/** + * Saves escape analysis method information into common repository. + */ void saveScannedMethodInfo(); - uint32 getMethodParamState(CalledMethodInfo* mi, uint32 np); + +/** + * Returns specified method parameter state. + * @param mi - escape analysis method information, + * @param np - parameter number. + * @return specified parameter state. + */ + uint32 getMethodParamState(CalleeMethodInfo* mi, uint32 np); + +/** + * Collects instructions creating objects that are not GLOBAL_ESCAPE. + */ void markNotEscInsts(); - void createdObjectInfo(); - void addMonInst(Inst* inst); - void addMonUnitVCall(MonUnit* mu, Inst* inst); - MonUnit* findMonUnit(uint32 opndId); - void scanSyncInsts(); - void fixSyncMethodMonitorInsts(Insts* syncInsts); - void checkCallSyncMethod(); - void insertSaveJitHelperCall(CnGNode* node); - Opnd* insertReadJitHelperCall(); - bool checkMonitorsOnThis(); - void setSencEscState(CnGNode* node,Insts* syncInsts); - void collectSuccessors(Node* node); - void collectGlobalNodeSuccessors(CnGNode* node); - uint32 getContainingObjState(Inst* linst); - void removeMonitorInsts(Insts* syncInsts); - void removeNode(Node* node); - SsaTmpOpnd* insertLdConst(uint32 value); - void fixMonitorInstsVCalls(MonUnit* mu); - void insertFlagCheck(Insts* syncInsts, Opnd* muflag); - void printNode(Node* n,::std::ostream& os); - uint32 checkState(Inst* inst,uint32 st); - void findObject(Inst* inst,std::string text=" "); - void findObject1(Inst* inst,std::string text=" "); +/** + * Performs variable operands fixup after done optimizations. + * @param irManager - IR manager. + */ + void eaFixupVars(IRManager& irm); + +/** + * Outputs connection graph nodes information into the specified log. + * @param text - output information naming, + * @param os - log. + */ + void printCnGNodes(char* text,::std::ostream& os); + +/** + * Outputs connection graph node information into the specified log. + * @param cgn - connection graph node, + * @param os - log. + */ + void printCnGNode(CnGNode* cgn,::std::ostream& os); + +/** + * Creates string representing CnG node type. + * @param cgn - connection graph node. + * @return srting representing CnG node type. + */ + std::string nodeTypeToString(CnGNode* cgn); + +/** + * Outputs connection graph edges information into the specified log. + * @param text - output information naming, + * @param os - log. + */ + void printCnGEdges(char* text,::std::ostream& os); + +/** + * Creates string representing CnG edge type. + * @param cgn - connection graph node. + * @return srting representing CnG edge type. + */ + std::string edgeTypeToString(CnGRef* edr); + +/** + * Outputs information about reference objects created in analyzed method into the specified log. + * @param os - log. + */ + void printRefInfo(::std::ostream& os); + +/** + * Outputs information about CnG node with all nodes it refers to. + * @param cgn - connection graph node, + * @param text - text printed before CnG node information, + * @param os - log. + */ + void printCnGNodeRefs(CnGNode* cgn, std::string text,::std::ostream& os); + +/** + * Outputs origin operands of specified instruction operands that aren't tau operand + * into the specified log. + * @param inst - instruction, + * @param text - text to print before the instruction, + * @param os - log. + */ void lObjectHistory(Inst* inst,std::string text,::std::ostream& os); - uint32 getSubobjectStates(CnGNode* node); +/** + * Outputs information about objects created in analyzed method into the specified log. + * @param os - log. + */ + void printCreatedObjectsInfo(::std::ostream& os); + +/** + * Outputs common information about created objects into log file. + */ + void createdObjectInfo(); + +/** + * Prints origin operands of specified instruction operands. + * @param inst - instruction, + * @param text - text to print before the instruction. + */ + void printOriginObject(Inst* inst,std::string text=" "); + +/** + * Prints origin operands of specified instruction main operand. + * @param inst - instruction, + * @param text - text to print before the instruction. + */ + void printOriginObject1(Inst* inst,std::string text=" "); + +/** + * Prints escape analysis method information stored in common repository. + */ + void printMethodInfos(); + +/** + * Prints escape analysis method information for specified parameter. + * @param mi - method info from common repository. + */ + void printMethodInfo(CalleeMethodInfo* mi); + +/** + * Outputs information about instruction kind into the specified log. + * @param inst - instruction, + * @param os - log. + */ + void what_inst(Inst* inst,::std::ostream& os); + +/** + * Outputs debug information about the specified type into the specified log. + * @param type - reference type, + * @param os - log. + */ + void ref_type_info(Type* type,::std::ostream& os); + +/** + * Outputs debug information about the specified instruction into the specified log. + * @param inst - instruction, + * @param os - log. + */ + void debug_inst_info(Inst* inst,::std::ostream& os); + +/** + * Outputs debug information about the specified operand into the specified log. + * @param opnd - operand, + * @param os - log. + */ + void debug_opnd_info(Opnd* opnd,::std::ostream& os); + + bool checkScanned(ObjIds* ids, uint32 id) { ObjIds::iterator it; if (ids == NULL) { @@ -371,11 +657,197 @@ return true; return false; } - void runTranslatorSession(CompilationContext& inlineCC); - // Scalar replacement optimization +// Monitors elimination optimization + + struct MonUnit { + uint32 opndId; + Insts* monInsts; + Insts* icallInsts; + }; + typedef StlList MonInstUnits; + // list to collect info about monitor instruction operands + MonInstUnits* monitorInstUnits ; + /** + * Adds monitor instruction to monitorInstUnits. + * @param inst - monitor instruction. + */ + void addMonInst(Inst* inst); + +/** + * Finds opndId specified monitor unit in monitorInstUnits. + * @param opndId - monitor instruction operand Id. + * @return MonUnit, if found, or NULL otherwise. + */ + MonUnit* findMonUnit(uint32 opndId); + +/** + * Adds call instruction to the specified monitor unit. + * @param mu - monitor unit, + * @param inst - call instruction. + */ + void addMonUnitVCall(MonUnit* mu, Inst* inst); + +/** + * Checks, that method contains monitor instructions with parameter + * which is this or subobject of this. + * @return true, if such monitors exist, or false otherwise. + */ + bool checkMonitorsOnThis(); + +/** + * Performs monitors elimination optimization. + */ + void scanSyncInsts(); + +/** + * Marks (in CFG nodes bitset) nodes that are 'locked' by monitor instructions. + * @param bs - CFG nodes bitset, + * @param syncInsts - list of monitor instruction for the same operand. + */ + void markLockedNodes(BitSet* bs, Insts* syncInsts); + + /** + * Marks (in CFG nodes bitset) nodes that are 'locked' by monitor instructions. + * @param node - next CFG node to search monexit instruction, + * @param bs - CFG nodes bitset, + * @param moninstop - monitor instruction operand, + * @return true, if such monexit was found, or false otherwise. + */ + bool markLockedNodes2(Node* node, BitSet* bs, Opnd* moninstop); + +/** + * Checks instruction source operand states for specified instruction. + * @param inst - specified instruction, + * @param st - instruction target operand state. + * @return GLOBAL_ESCAPE, if any of source operand state is GLOBAL_ESCAPE, + * ARG_ESCAPE, if any of source operand state or st is ARG_ESCAPE, + * NO_ESCAPE otherwise. + */ + uint32 checkState(Inst* inst,uint32 st); + +/** + * Checks if CnGNode operand is GLOBAL_ESCAPED while monitor instructions are executed. + * @param node - specified operand CnGNode, + * @param syncInsts - list of monitor instructions for specified operand. + * @return true, specified operand is global, when monitor instruction are executed, + * false, otherwise. + */ + bool checkSencEscState(CnGNode* node,Insts* syncInsts); + +/** + * Collects all reachable in FlowGraph nodes from the specified node to scannedSucNodes list. + * @param node - FlowGraph node, + * @param syncInsts - instruction target operand state. + */ + void collectSuccessors(Node* node); + +/** + * Collects global node successors to scannedSucNodes list. + * @param node - CnG node. + */ + void collectGlobalNodeSuccessors(CnGNode* node); + +/** + * Returns state of object containing address for Op_TauStInd instruction. + * @param linst - Op_TauStInd instruction. + * @return object state. + */ + uint32 getContainingObjState(Inst* linst); + +/** + * Inserts flag for specified monitor unit. Flag is set to 0 after operand creation instruction. + * Flag is set to 1 before call instruction from vcInsts list. + * Inserts flag check before monitor instruction from monInsts list. + * If flag is equal to 0, monitor instruction isn't executed. + * @param mu - monitor unit, + * @param bs - CFG nodes bitset (with marked nodes for specified monitor unit). + */ + void fixMonitorInstsVCalls(MonUnit* mu, BitSet* bs); + +/** + * Inserts flag check before monitor instruction. + * If flag = 0 monitor instruction isn't executed. + * @param syncInsts - monitor instruction list, + * @param chk - value to check with (0 or 1), + * @param muflag - monitor flag operand (VarOpnd* or SsaTmpOpnd*). + */ + void insertFlagCheck(Insts* syncInsts, Opnd* muflag, uint32 chk); + +/** + * Removes monitor instructions from the specified monitor instruction list. + * @param syncInsts - monitor instruction list. + */ + void removeMonitorInsts(Insts* syncInsts); + +/** + * Removes flow graph node. + * @param node - flow graph node. + */ + void removeNode(Node* node); + +/** + * Performs monitors elimination optimization for specified monitor instructions with + * method this argument. + * @param syncInsts - monitor instruction list. + */ + void fixSyncMethodMonitorInsts(Insts* syncInsts); + +/** + * Inserts ReadJitHelperCall instruction to read state of method this argument + * after first instruction in entry block. + * @return this argument state + * 0 - this argument is thread local, + * 1 - this argument is thread global. + */ + Opnd* insertReadJitHelperCall(); + +/** + * Checks this argument of direct call synchronized methods. + * If the argument doesn't escape callee method, and actual argument isn't global, + * calls 'insertSaveJitHelperCall' to transfer this argument state + * to callee method. + */ + void checkCallSyncMethod(); + +/** + * Inserts SaveJitHelperCall instruction to store state of method this argument + * before the specified instruction. + * @param inst_before - instruction to insert SaveJitHelperCall before, + * @param stVal - stored value. + */ + void insertSaveJitHelperCall(Inst* inst_before, SsaTmpOpnd* stVal); + +/** + * Creates i32_0 or i32_1 SsaTmpOpnd (in accordance with value: 0 or 1) + * if it wasn't created before. + * Inserts ldc0 or ldc1 instruction after first instruction in entry Node, + * if SsaTmpOpnd was created. + * @param value - 0 or 1. + * @return i32_0, if value = 0 + * i32_1, if value = 1 + */ + SsaTmpOpnd* insertLdConst(uint32 value); + + + +// Scalar replacement optimization + + struct ScObjFld { + VarOpnd* fldVarOpnd; + Insts* ls_insts; + FieldDesc* fd; + bool isFinalFld; + }; + // list to collect scalarized object candidates + typedef StlList ScObjFlds; + + // output stream for scalar replacement optimization + std::ostream& os_sc; + +/** * Performs scalar replacement optimization for local objects * (class instances and arrays). */ @@ -388,51 +860,59 @@ /** * Performs scalar replacement optimization for local objects from the specified list. - * @param loids - list of local objects CnG nodes Ids - * @param os - output stream + * @param loids - list of local objects CnG nodes Ids, */ void doLOScalarReplacement(ObjIds* loids); /** * Performs scalar replacement optimization for method escaped objects from the specified list. - * @param loids - list of local objects CnG nodes Ids + * @param loids - list of optimized objects CnG nodes Ids. */ void doEOScalarReplacement(ObjIds* loids); /** * Collects (using connection graph) information of onode object fields usage. * @param onode - connection graph node fields usage of which is collected - * @param scObjFlds - list to collect onode fields usage + * @param scObjFlds - list to collect onode field's usage. */ void collectStLdInsts(CnGNode* onode, ScObjFlds* scObjFlds); /** * Collects (using connection graph) call instructions which use optimized object * as a parameter. - * @param n - optimized obgect connection graph node Id; - * @param vc_insts - list of call instructions; + * @param n - optimized object connection graph node Id, + * @param vc_insts - list of call instructions, * @param vcids - list of call instructions ids. */ void collectCallInsts(uint32 n, Insts* vc_insts, ObjIds* vcids); /** * Performs scalar replacement optimization for optimized object field usage. - * @param scfld - optimized object scalarizable field + * @param scfld - optimized object scalarizable field. */ void scalarizeOFldUsage(ScObjFld* scfld); /** * Checks if an object from the specified list can be removed and its fields/elements scalarized. * If an object cannot be optimized it is removed from the list. - * @param loids - list of local object CnG nodes Ids + * @param lnoids - list of new object CnG nodes Ids, + * @param lloids - list of load object CnG nodes Ids, * @param check_loc - if true checks for local objects, * if false checks for virtual call escaped objects. */ void checkOpndUsage(ObjIds* lnoids, ObjIds* lloids, bool check_loc); /** + * Checks if a tau operand may be removed/replaced. + * @param tau_inst - object CnG nodes Ids. + * @return true if tau operand may be removed; + * false otherwise. + */ + bool checkTauOpnd(Inst* tau_inst); + +/** * Checks if an object can be removed and its fields/elements scalarized. - * @param lobjid - object CnG nodes Ids + * @param lobjid - object CnG nodes Ids. * @return true if an object is used only in ldflda or ldbase instructions; * false otherwise. */ @@ -441,16 +921,16 @@ /** * Performs checks for CnGNode operand using connection graph. * @param scnode - CnG node of optimized operand - * @param check_loc - * @param check_loc - if true checks for local objects, + * @param check_loc - if true checks for local objects, * if false checks for virtual call escaped objects. * @return CnGNode* for operand that may be optimized; * NULL otherwise. */ - CnGNode* checkCnG(CnGNode* scnode, bool check_loc); + CnGNode* checkCnGtoScalarize(CnGNode* scnode, bool check_loc); /** - * Checks if there is a path in CFG from node where object created by a nob_inst instruction - * to EXIT node and this object is not escaped to any method call. + * Checks if there is a path in CFG from node where object is created by a nob_inst instruction + * to EXIT node and this object is not escaped to any method call on this path. * @param nob_inst - object creation instruction. * @return execCount of this path execution; * 0 otherwise. @@ -460,22 +940,22 @@ /** * Checks if there is a path in CFG from node where object created by a nob_inst instruction * to EXIT node and this object is not escaped to any method call. - * @param n - CFG node to scan - * @param obId - escaped optimized object Id - * @param cExecCount - current execCount + * @param n - CFG node to scan, + * @param obId - escaped optimized object Id, + * @param cExecCount - current execCount. * @return execCount the most value of execCount and - * checkNextNodes execution for next after n node; + * checkNextNodes execution for next after n node. */ - double checkNextNodes(Node* n, uint32 obId, double cExecCount, std::string text=""); + double checkNextNodes(Node* n, uint32 obId, double cExecCount); /** * Checks flag and creates object before call instruction (if it was not created yet). - * @param vc_insts - list of call instructions optimized object is escaped to - * @param objs - list of optimized object fields - * @param ob_var_opnd - varOpnd replacing optimized object - * @param ob_flag_var_opnd - sign if optimized object was created - * @param tnode - target CFG node for newobj instruction exception edge - * @param oid - escaped optimized object Id + * @param vc_insts - list of call instructions optimized object is escaped to, + * @param objs - list of optimized object fields, + * @param ob_var_opnd - varOpnd replacing optimized object, + * @param ob_flag_var_opnd - sign if optimized object was created, + * @param tnode - target CFG node for newobj instruction exception edge, + * @param oid - escaped optimized object Id. */ void restoreEOCreation(Insts* vc_insts, ScObjFlds* objs, VarOpnd* ob_var_opnd, VarOpnd* ob_flag_var_opnd, Node* tnode, uint32 oid); @@ -483,7 +963,7 @@ /** * Removes specified instruction from ControlFlowGraph. * If instruction can throw exception removes corresponding CFGEdge. - * @param reminst - removed instruction + * @param reminst - removed instruction. */ void removeInst(Inst* reminst); @@ -498,14 +978,14 @@ /** * Replaces first source operand of Op_MethodEnd instruction by NULL * for scalar replacement optimized object. - * @param ob_id - optimized object Id + * @param ob_id - optimized object Id. */ void fixMethodEndInsts(uint32 ob_id); /** * Finds (using connection graph) load varOpnd that should be optimized with * new object operand. - * @param vval - CnG node of target stvar instruction varOpnd + * @param vval - CnG node of target stvar instruction varOpnd. * @return CnGNode* - found optimized load varOpnd CnG node * NULL otherwise. */ @@ -530,8 +1010,8 @@ /** * Checks that all load varOpnd fields are in new object field usage list. - * @param nscObjFlds - list of used fields of optimized new object - * @param lscObjFlds - list of used fields of optimized load varOpnd + * @param nscObjFlds - list of used fields of optimized new object, + * @param lscObjFlds - list of used fields of optimized load varOpnd. * @return true if list of new object used field contains all * load varOpnd used field; * false otherwise. @@ -540,52 +1020,37 @@ /** * Removes check instructions for optimized load varOpnd. - * @param ob_id - optimized load variable operand Id + * @param ob_id - optimized load variable operand Id. */ void fixCheckInsts(uint32 opId); /** * Checks (using connection graph) if CnGNode operand has final fields and adds it to - * the list of posible optimized final fields operands. - * @param onode - CnG node of optimized operand - * @param scObjFlds - list to collect onode operand field usage + * the list of possible optimized final fields operands. + * @param onode - CnG node of optimized operand, + * @param scObjFlds - list to collect onode operand field usage. */ void checkToScalarizeFinalFiels(CnGNode* onode, ScObjFlds* scObjFlds); - // BCMap support +// BCMap support + // Byte code map info + bool isBCmapRequired; + VectorHandler* bc2HIRMapHandler; /** * Sets bcmap offset in bc2HIRMapHandler. - * @param new_i - instruction to set offset - * @param old_i - offset of old_i instruction is set to new_i instruction + * @param new_i - instruction to set offset, + * @param old_i - offset of old_i instruction is set to new_i instruction. */ void setNewBCMap(Inst* new_i, Inst* old_i); /** * Removes bcmap offset in bc2HIRMapHandler. - * @param inst - instruction to remove offset + * @param inst - instruction to remove offset. */ void remBCMap(Inst* inst); - int _cfgirun; - int _instrInfo; - int _instrInfo2; - int _cngnodes; - int _cngedges; - int _scanMtds; - int _setState; - int _printstat; - int _eainfo; - int _seinfo; - int _scinfo; -#define prsNum 10 - int prsArr[prsNum]; - - CompilationInterface &compInterface; - // Byte code map info - bool isBCmapRequired; - VectorHandler* bc2HIRMapHandler; }; } //namespace Jitrino