Index: vm/jitrino/config/em64t/server.emconf =================================================================== --- vm/jitrino/config/em64t/server.emconf (revision 517749) +++ vm/jitrino/config/em64t/server.emconf (working copy) @@ -62,7 +62,7 @@ -XDjit.SD2_OPT.path=opt_init,translator,optimizer,hir2lir,codegen --XDjit.SD2_OPT.path.optimizer=ssa,simplify,dce,uce,devirt_virtual,edge_annotate,unguard,devirt_intf,inline,uce,purge,simplify,dce,uce,so2-,simplify,dce,uce,hvn,dce,uce,dessa,statprof,peel,ssa,hvn,simplify,dce,uce,lower,dce,uce,memopt,reassoc,dce,uce,hvn,dce,uce,abcd,dce,uce,gcm,dessa,statprof,markglobals +-XDjit.SD2_OPT.path.optimizer=ssa,simplify,dce,uce,devirt_virtual,edge_annotate,unguard,devirt_intf,inline,uce,purge,simplify,dce,uce,so2-,simplify,dce,uce,escape-,hvn,dce,uce,dessa,statprof,peel,ssa,hvn,simplify,dce,uce,lower,dce,uce,memopt,reassoc,dce,uce,hvn,dce,uce,abcd,dce,uce,gcm,dessa,statprof,markglobals -XDjit.SD2_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 -XDjit.SD2_OPT.path.dce1=cg_dce -XDjit.SD2_OPT.path.dce2=cg_dce Index: vm/jitrino/config/ia32/server.emconf =================================================================== --- vm/jitrino/config/ia32/server.emconf (revision 517749) +++ vm/jitrino/config/ia32/server.emconf (working copy) @@ -63,7 +63,7 @@ -XDjit.SD2_OPT.path=opt_init,translator,optimizer,hir2lir,codegen --XDjit.SD2_OPT.path.optimizer=ssa,simplify,dce,uce,devirt_virtual,edge_annotate,unguard,devirt_intf,inline,uce,purge,simplify,dce,uce,lazyexc,so2-,simplify,dce,uce,inline_helpers,purge,simplify,uce,dce,dessa,statprof,peel,ssa,hvn,simplify,dce,uce,lower,dce,uce,memopt,reassoc,dce,uce,hvn,dce,uce,abcd,dce,uce,gcm,dessa,statprof,markglobals +-XDjit.SD2_OPT.path.optimizer=ssa,simplify,dce,uce,devirt_virtual,edge_annotate,unguard,devirt_intf,inline,uce,purge,simplify,dce,uce,lazyexc,so2-,simplify,dce,uce,escape,inline_helpers,purge,simplify,uce,dce,dessa,statprof,peel,ssa,hvn,simplify,dce,uce,lower,dce,uce,memopt,reassoc,dce,uce,hvn,dce,uce,abcd,dce,uce,gcm,dessa,statprof,markglobals -XDjit.SD2_OPT.path.codegen=lock_method,bbp,btr,gcpoints,cafl,dce1,i8l,api_magic,early_prop,peephole,itrace-,native,constraints,dce2,regalloc,spillgen,layout,copy,rce+,stack,break-,iprof-,peephole,emitter!,si_insts,gcmap,info,unlock_method -XDjit.SD2_OPT.path.dce1=cg_dce -XDjit.SD2_OPT.path.dce2=cg_dce Index: vm/jitrino/src/optimizer/escanalyzer.cpp =================================================================== --- vm/jitrino/src/optimizer/escanalyzer.cpp (revision 517749) +++ vm/jitrino/src/optimizer/escanalyzer.cpp (working copy) @@ -34,12 +34,26 @@ #include "optpass.h" #include "devirtualizer.h" #include "DrlVMInterface.h" +//#include "Windows.h" namespace Jitrino { +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_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" + " escape.do_scalar_repl_only_final_fields[={on,OFF}] \n" + " escape.scalarize_final_fields[={on,OFF}] - scalarize final field usage when\n" + " escaped object wasn't optimized\n" + " escape.exec_count_mult[=0] - entry node execCount multiplier\n"; + DEFINE_SESSION_ACTION(EscapeAnalysisPass, escape, "Escape Analysis") + struct ComObjStat { ComObjStat() :_n0(0), _n_ge(0), _n_ae(0), _n_ne(0), _n_lo(0) {}; uint32 _n0; @@ -82,29 +96,48 @@ EscAnalyzer::EscAnalyzer(MemoryManager& mm, SessionAction* argSource, IRManager& irm) -: eaMemManager(mm), irManager(irm), mh(irm.getMethodDesc()) +: eaMemManager(mm), irManager(irm), mh(irm.getMethodDesc()),os_sc(Log::out()), + compInterface(irm.getCompilationInterface()) { 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_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); + execCountMultiplier_string = argSource->getStringArg("exec_count_mult", NULL); + ec_mult = ( execCountMultiplier_string==NULL ? 0 : atof(execCountMultiplier_string) ); + do_scalar_repl_only_final_fields = argSource->getBoolArg("do_scalar_repl_only_final_fields",false); + scalarize_final_fields = argSource->getBoolArg("scalarize_final_fields",false); + const char* translatorName = argSource->getStringArg("translatorActionName", "translator"); translatorAction = (TranslatorAction*)PMF::getAction(argSource->getPipeline(), translatorName); assert(translatorAction); init(); + + if (compInterface.isBCMapInfoRequired()) { + isBCmapRequired = true; + MethodDesc* meth = compInterface.getMethodToCompile(); + bc2HIRMapHandler = new VectorHandler(bcOffset2HIRHandlerName, meth); + } else { + isBCmapRequired = false; + bc2HIRMapHandler = NULL; + } } EscAnalyzer::EscAnalyzer(EscAnalyzer* parent, IRManager& irm) -: eaMemManager(parent->eaMemManager), irManager(irm), mh(irm.getMethodDesc()) +: eaMemManager(parent->eaMemManager), irManager(irm), mh(irm.getMethodDesc()), os_sc(Log::out()), + compInterface(irm.getCompilationInterface()) { maxMethodExamLevel = parent->maxMethodExamLevel; allProps = parent->allProps; debug_method = parent->debug_method; translatorAction = parent->translatorAction; method_ea_level = parent->method_ea_level + 1; - + init(); } @@ -115,9 +148,12 @@ initNodeType = 0; // type of initial scanned node scannedObjs = new (eaMemManager) ObjIds(eaMemManager); + scannedObjsRev = new (eaMemManager) ObjIds(eaMemManager); scannedInsts = new (eaMemManager) ObjIds(eaMemManager); scannedSucNodes = new (eaMemManager) ObjIds(eaMemManager); monitorInstUnits = new (eaMemManager) MonInstUnits(eaMemManager); + methodEndInsts = new (eaMemManager) Insts(eaMemManager); + checkInsts = new (eaMemManager) Insts(eaMemManager); _cfgirun=0; _instrInfo=0; @@ -129,6 +165,13 @@ _printstat=0; _eainfo=0; _seinfo=0; + if (Log::isEnabled()) + _scinfo = 1; + else + if (print_scinfo) + _scinfo=1; + else + _scinfo=0; std::fill(prsArr, prsArr + prsNum, 0); @@ -157,6 +200,20 @@ } } +void +EscAnalyzer::showFlags(std::ostream& os) { + os << " escape flags:"<begin( ); it != cngNodes->end( ); it++ ) { @@ -371,6 +439,21 @@ 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::scanSyncInsts() { MonInstUnits::iterator it; Insts::iterator it1; @@ -613,12 +696,12 @@ } // checkCallSyncMethod() -/* -* 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. -*/ +/** + * 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; @@ -661,15 +744,15 @@ } // insertSaveJitHelperCall(CnGNode* node) -/* -* 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 -*/ +/** + * 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(); @@ -710,11 +793,11 @@ } // insertReadJitHelperCall() -/* -* Checks, that method contains monitor instructions with parameter -* which is this or subobject of this. -* Returns: true, if such monitors exist, false overwise. -*/ +/** + * 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; @@ -830,8 +913,8 @@ printMethodInfo(mtdInfo); } #endif - } - } + } + } } findObject1(einst); collectSuccessors(einst->getNode()); @@ -867,10 +950,10 @@ } // setSencEscState(CnGNode* node,Insts* syncInsts) -/* -* Collect all reachable from specified node nodes in FlowGraph. -* scannedSucNodes - result of collection. -*/ +/** + * Collect all reachable from specified node nodes in FlowGraph. + * scannedSucNodes - result of collection. + */ void EscAnalyzer::collectSuccessors(Node* node) { Node* n; @@ -892,7 +975,7 @@ void EscAnalyzer::collectGlobalNodeSuccessors(CnGNode* node) { CnGEdges::iterator it; - CnGRefs::iterator it2; + CnGRefs::iterator it2; Inst* einst; bool pGlobalObj = false; #ifdef _DEBUG @@ -954,7 +1037,7 @@ } #endif } - } + } } if (einst->getOpcode() == Op_IndirectMemoryCall) pGlobalObj = true; @@ -1069,7 +1152,6 @@ scannedObjs->clear(); } } - } } // removeMonitorInsts(Insts* syncInsts) @@ -1116,15 +1198,15 @@ } // removeNode(Node* node) -/* -* 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 -*/ +/** + * 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(); @@ -1243,11 +1325,11 @@ } // fixMonitorInstsVCalls(MonUnit* mu) -/* -* Insers flag check before monitor instruction. -* If flag = 0 monitor instruction isn't executed. -* Operand flag may be VarOpnd* or SsaTmpOpnd* type. -*/ +/** + * 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; @@ -1340,13 +1422,13 @@ } // printNode(Node* n,::std::ostream& os) -/* -* 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 -*/ +/** + * 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; @@ -1387,7 +1469,7 @@ if (st <= GLOBAL_ESCAPE) return st; switch (inst->getOpcode()) { - case Op_LdRef: // ldstr + case Op_LdRef: // ldref case Op_NewObj: // newobj case Op_NewArray: // newarray case Op_NewMultiArray: // newmultiarray @@ -1433,7 +1515,7 @@ if (scannedObjs->size()!=0) { if (checkScannedObjs(inst->getId())) { #ifdef _DEBUG - if (_seinfo) { + if (_seinfo || _scinfo) { Log::out() << "instId " << inst->getId() << " . . . " << std::endl; } @@ -1442,7 +1524,7 @@ } } #ifdef _DEBUG - if (_seinfo) { + if (_seinfo || _scinfo) { Log::out() << text; if (Log::isEnabled()) inst->print(Log::out()); @@ -1455,7 +1537,7 @@ CnGNode* n = findCnGNode_op(returnOpnd->getId()); if (n != NULL) { #ifdef _DEBUG - if (_seinfo) { + if (_seinfo || _scinfo) { Log::out()<< text << " "; if (Log::isEnabled()) printCnGNode(n,Log::out()); @@ -1466,8 +1548,13 @@ } if (inst->getOpcode()==Op_IndirectMemoryCall) { #ifdef _DEBUG - MethodDesc* md = inst->getSrc(0)->getInst()->asMethodInst()->getMethodDesc(); - if (_seinfo) { + 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() ); @@ -1482,7 +1569,7 @@ CnGNode* n = findCnGNode_op(dst->getId()); if (n != NULL) { #ifdef _DEBUG - if (_seinfo) { + if (_seinfo || _scinfo) { Log::out()<< text << " "; if (Log::isEnabled()) printCnGNode(n,Log::out()); @@ -1492,7 +1579,7 @@ } } switch (inst->getOpcode()) { - case Op_LdRef: // ldstr + case Op_LdRef: // ldref case Op_NewObj: // newobj case Op_NewArray: // newarray case Op_NewMultiArray: // newmultiarray @@ -1501,7 +1588,7 @@ CnGNode* n = findCnGNode_in(inst->getId()); if (n != NULL) { #ifdef _DEBUG - if (_seinfo) { + if (_seinfo || _scinfo) { Log::out() << text << " "; if (Log::isEnabled()) printCnGNode(n,Log::out() ); @@ -1525,9 +1612,9 @@ } // findObject(Inst* inst,std::string text) -/* -* Finds (prints) origin objects of monitor instruction operand. -*/ +/** + * Finds (prints) origin objects of monitor instruction operand. + */ void EscAnalyzer::findObject1(Inst* inst,std::string text) { Inst* inst1; @@ -1535,48 +1622,45 @@ if (scannedObjs->size()!=0) { if (checkScannedObjs(inst->getId())) { -#ifdef _DEBUG - if (_seinfo) { + if (_seinfo || _scinfo) { Log::out() << "instId " << inst->getId() << " . . . " << std::endl; } -#endif return; } } -#ifdef _DEBUG - if (_seinfo) { + if (_seinfo || _scinfo) { Log::out() << text; if (Log::isEnabled()) 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) { + 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 = inst->getSrc(0)->getInst()->asMethodInst()->getMethodDesc(); - if (_seinfo) { + 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; } @@ -1584,18 +1668,16 @@ Opnd *dst = inst->getDst(); CnGNode* n = findCnGNode_op(dst->getId()); if (n != NULL) { -#ifdef _DEBUG - if (_seinfo) { + if (_seinfo || _scinfo) { Log::out()<< text << " "; if (Log::isEnabled()) printCnGNode(n,Log::out()); Log::out()<< std::endl; } -#endif } } switch (inst->getOpcode()) { - case Op_LdRef: // ldstr + case Op_LdRef: // ldref case Op_NewObj: // newobj case Op_NewArray: // newarray case Op_NewMultiArray: // newmultiarray @@ -1603,14 +1685,12 @@ { CnGNode* n = findCnGNode_in(inst->getId()); if (n != NULL) { -#ifdef _DEBUG - if (_seinfo) { + if (_seinfo || _scinfo) { Log::out() << text << " "; if (Log::isEnabled()) printCnGNode(n,Log::out() ); Log::out() << std::endl; } -#endif } break; } @@ -1660,10 +1740,10 @@ } // markNotEscInsts() -/* -* Summarizes common number of objects with the same state. -* Prints statictics if required. -*/ +/** + * Summarizes common number of objects with the same state. + * Prints statictics if required. + */ void EscAnalyzer::createdObjectInfo() { CnGNodes::iterator it; @@ -1721,13 +1801,16 @@ 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 "<push_back(minfo); - +//std::cout<< "*2****** unlock "<clear(); + scannedObjsRev->clear(); for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { if ((*it)->nodeType&NT_EXITVAL) { // returned, thrown #ifdef _DEBUG @@ -1983,10 +2069,11 @@ } #endif initNodeType = (*it)->nodeType; - scanCnGNodeRefsGE(*it); + scanCnGNodeRefsGE(*it,false); } } scannedObjs->clear(); + scannedObjsRev->clear(); for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { if ((*it)->nodeType==NT_DEFARG) { #ifdef _DEBUG @@ -1999,11 +2086,13 @@ } #endif initNodeType = NT_DEFARG; - scanCnGNodeRefsGE(*it); + 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; @@ -2017,10 +2106,13 @@ } #endif initNodeType = NT_ACTARG; - scanCnGNodeRefsAE(*it); + scanCnGNodeRefsAE(*it,false); + scannedObjs->clear(); + scannedObjsRev->clear(); } } scannedObjs->clear(); + scannedObjsRev->clear(); if (method_ea_level==0) { DominatorTree* dominatorTree = irManager.getDominatorTree(); if (!(dominatorTree && dominatorTree->isValid())) { @@ -2062,13 +2154,24 @@ } for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { uint32 nt = (*it)->nodeType; - if ((nt&NT_OBJECT || nt==NT_LDOBJ) && (getEscState(*it)==ARG_ESCAPE)) { +// 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++) { CnGNode* n=findCnGNode_id(*it1); // method argument node assert(n!=NULL); MethodDesc* mdesc = (MethodDesc*)n->refObj; Inst* callInst = n->nInst; +#ifdef _DEBUG + if (_setState) { + Log::out()<<"--setSt chk arg_esc: node " <<(*it)->cngNodeId + <<" opndId " <<(*it)->opndId<<" state "; + printState(*it); Log::out() << std::endl; + Log::out() << " "; + callInst->print(Log::out()); + Log::out() << std::endl; + } +#endif if (mdesc->isNative()) { // not scanned native methods if (strcmp(mdesc->getParentType()->getName(),"java/lang/VMMemoryManager")==0 &&strcmp(mdesc->getName(),"arrayCopy")==0) { @@ -2103,15 +2206,16 @@ break; } if (callInst->getOpcode()!=Op_DirectCall) { // not direct call - if (method_ea_level == 0) { + setVirtualCall(*it); + if (method_ea_level == 0 && do_sync_removal) { MonUnit* mu = NULL; if (monitorInstUnits!=NULL) mu = findMonUnit((*it)->opndId); if (mu != NULL) { - setVirtualCall(*it); +// setVirtualCall(*it); addMonUnitVCall(mu,callInst); #ifdef _DEBUG - if (Log::isEnabled()) { + if (_seinfo&&Log::isEnabled()) { Log::out() << "=-=-=-=- callimem for this "; Log::out() << std::endl; Log::out() << "=-=- "; @@ -2129,8 +2233,7 @@ continue; } } - - setEscState(*it,GLOBAL_ESCAPE); + // setEscState(*it,GLOBAL_ESCAPE); #ifdef _DEBUG if (_scanMtds==1) { if (Log::isEnabled()) { @@ -2173,13 +2276,13 @@ <<" state "; if (Log::isEnabled()) printState(*it); - Log::out() <<" to gl.esc." +// Log::out() <<" to gl.esc." + Log::out() <<" to v.call." << std::endl; } #endif - break; + continue; //break; } - CalledMethodInfo* mtdInfo = findMethodInfo(mdesc,callInst); if (mtdInfo == NULL) { // no info about called method setEscState(*it,GLOBAL_ESCAPE); @@ -2239,8 +2342,9 @@ } } if (getEscState(*it)==GLOBAL_ESCAPE) { // to set gl.escape for contained objects - scanCnGNodeRefsGE(*it); //??? to set initNodeType? + scanCnGNodeRefsGE(*it,false); //??? to set initNodeType? scannedObjs->clear(); + scannedObjsRev->clear(); } } } @@ -2342,6 +2446,7 @@ } scannedObjs->clear(); + scannedObjsRev->clear(); } @@ -2430,12 +2535,12 @@ } // findMethodInfo(MethodDesc* mdesc) -/* -* Finds specified parameter in specified method info. -* Returns: -* state - for existent parameter, -* 0 - for another cases. -*/ +/** + * 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; @@ -2460,7 +2565,8 @@ irManager.getMethodDesc().printFullName(os); os << std::endl; for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { - if ((*it)->nodeType & NT_OBJECT || (*it)->nodeType==NT_LDOBJ) { + 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) { @@ -2485,25 +2591,32 @@ void -EscAnalyzer::scanCnGNodeRefsGE(CnGNode* cgn) { +EscAnalyzer::scanCnGNodeRefsGE(CnGNode* cgn, bool check_var_src, bool check_field_elem) { // CnGEdges* cge = cngEdges; CnGEdges::iterator it; CnGRefs::iterator it1; + CnGNode* next_node; + ObjIds* scObjs = check_var_src ? scannedObjsRev : scannedObjs; uint32 nscan=0; - if (scannedObjs->size()!=0) { - if (checkScannedObjs(cgn->cngNodeId)) - return; - } + uint32 ni_opcode = cgn->nInst->getOpcode(); + #ifdef _DEBUG if (_setState) { Log::out() <<"--scanGE 1: node "<cngNodeId <<" opndId "<opndId<<" state "; if (Log::isEnabled()) printState(cgn); - Log::out() <<" " - << nodeTypeToString(cgn) << cgn->nodeType << std::endl; + Log::out() <<" " << nodeTypeToString(cgn) <nodeType + <<" check_var_src " << check_var_src + <<" check_field_elem " << check_field_elem << std::endl; } #endif + if (cgn->nodeType == NT_LDVAL) + return; + if (scObjs->size()!=0) { + if (checkScanned(scObjs,cgn->cngNodeId)) + return; + } if (cgn->nodeType&NT_OBJS) { if (initNodeType!=NT_EXITVAL && initNodeType!=NT_DEFARG) { // if (getEscState(cgn) > GLOBAL_ESCAPE) { @@ -2539,51 +2652,98 @@ // The objects created in the method are not global escaped through return } if (initNodeType==NT_DEFARG) { - if (getCalleeEscaped(cgn) == 0) { + if (getCalleeEscaped(cgn) == 0) { #ifdef _DEBUG - if (_setState) { - Log::out() <<"--scanGE 5: node " - <cngNodeId<<" opndId "<opndId <<" state "; - if (Log::isEnabled()) - printState(cgn); - Log::out() <<" to callee.esc."<< std::endl; - Log::out() <<"--scanGE 5: "<< nodeTypeToString(cgn) - << cgn->nodeType <<" initNode "<cngNodeId<<" opndId "<opndId <<" state "; + if (Log::isEnabled()) + printState(cgn); + Log::out() <<" to callee.esc."<< std::endl; + Log::out() <<"--scanGE 4: "<< nodeTypeToString(cgn) + << cgn->nodeType <<" initNode "<push_back(cgn->cngNodeId); +// 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++ ) { - scanCnGNodeRefsGE(findCnGNode_id((*it1)->cngNodeTo->cngNodeId)); + next_node = (*it1)->cngNodeTo; + if (next_node->nodeType == NT_LDOBJ) + if (next_node->nInst->getOpcode()==Op_LdVar && cgn->nodeType!=NT_VARVAL) + to_check_var_src = true; +#ifdef _DEBUG + if (_setState) { + Log::out() <<"--scanGE 5 next: node " + <cngNodeId<<" opndId "<opndId <<" state "; + printState(next_node); Log::out() << std::endl; + } +#endif + scanCnGNodeRefsGE(next_node,to_check_var_src,to_check_field_elem); if ((*it1)->edgeType!=ET_POINT) nscan++; } } + if (check_var_src) { + if (ni_opcode == Op_LdVar || ni_opcode == Op_StVar || ni_opcode ==Op_Phi) { + uint32 nsrc=cgn->nInst->getNumSrcOperands(); + for (uint32 i=0; inInst->getSrc(i)->getId()); #ifdef _DEBUG + if (_setState) { + Log::out() <<"--scanGE 6 next: node " + <cngNodeId<<" opndId "<opndId <<" state "; + printState(next_node); Log::out() << std::endl; + } +#endif + scanCnGNodeRefsGE(next_node,check_var_src); + } + } + } +#ifdef _DEBUG if (_setState) { - Log::out()<<"--scanGE 6: nscan "<opndId<opndId<nodeType==NT_ARRELEM && nscan==0) { - Inst* inst_ldbase= ((Opnd*)(cgn->refObj))->getInst()->getSrc(0)->getInst(); + if (cgn->nodeType==NT_ARRELEM) { + 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 arrElem: "; + Log::out() <<"--scanGE 7 arrElem: "; if (Log::isEnabled()) inst_ldbase->print(Log::out()); Log::out() << std::endl; - Log::out() <<"--scanGE next: " << cgnode->cngNodeId << " - " + Log::out() <<"--scanGE 7 next: " << cgnode->cngNodeId << " - " << cgnode->opndId << std::endl; } #endif - scanCnGNodeRefsGE(cgnode); + // 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); + } + } } - if (cgn->nodeType==NT_LDOBJ && nscan==0) { + 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(); @@ -2591,7 +2751,7 @@ CnGNode* cgnode=findCnGNode_fl(inst_fldaddr,NT_INSTFLD); #ifdef _DEBUG if (_setState) { - Log::out() << "TO FIND 1 for opnd " + Log::out() << "--scanGE 8 TO FIND 1 for opnd " << cgn->opndId << std::endl; if (Log::isEnabled()) ldinst->print(Log::out()); @@ -2605,13 +2765,14 @@ << cgnode->opndId << std::endl; } #endif - scanCnGNodeRefsGE(cgnode); + scanCnGNodeRefsGE(cgnode,check_var_src,false); } else { - if (inst_fldaddr->getOpcode()==Op_AddScaledIndex) { + 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() << "TO FIND 2 for opnd " + Log::out() << "--scanGE 8 TO FIND 2 for opnd " << cgn->opndId << std::endl; if (Log::isEnabled()) ldinst->print(Log::out()); @@ -2625,140 +2786,129 @@ << cgnode->opndId << std::endl; } #endif - scanCnGNodeRefsGE(cgnode); + scanCnGNodeRefsGE(cgnode,check_var_src,false); } } } } -} // scanCnGNodeRefsGE(CnGNode* cgn) +} // scanCnGNodeRefsGE(CnGNode* cgn, bool check_var_src, bool check_field_elem) void -EscAnalyzer::scanCnGNodeRefsEV(CnGNode* cgn) { +EscAnalyzer::scanCnGNodeRefsAE(CnGNode* cgn, bool check_var_src, bool check_field_elem) { + CnGEdges::iterator it; CnGRefs::iterator it1; - if (scannedObjs->size()!=0) { - if (checkScannedObjs(cgn->cngNodeId)) - return; - } + CnGNode* next_node; + ObjIds* scObjs = check_var_src ? scannedObjsRev : scannedObjs; + uint32 nscan=0; + uint32 ni_opcode = cgn->nInst->getOpcode(); + #ifdef _DEBUG if (_setState) { - Log::out() <<"--scanEV: node "<cngNodeId - <<" opndId "<opndId <<" state "; + Log::out() <<"--scanAE < 1: node "<cngNodeId + <<" opndId "<opndId<<" state "; if (Log::isEnabled()) - printState(cgn); - Log::out() << " " - << nodeTypeToString(cgn) << cgn->nodeType << std::endl; + printState(cgn); + Log::out() <<" " << nodeTypeToString(cgn) <nodeType + <<" check_var_src " << check_var_src + <<" check_field_elem " << check_field_elem << std::endl; } #endif - if (cgn->nodeType==NT_OBJECT) // object is escaped if it is returned - if (getEscState(cgn) > GLOBAL_ESCAPE) { - setEscState(cgn,GLOBAL_ESCAPE); + if (cgn->nodeType == NT_LDVAL) { // primitive type value #ifdef _DEBUG + if (_setState) { + Log::out() <<"--scanAE > 1: primitive type " << std::endl; + } +#endif + return; + } + if (scObjs->size()!=0) { + if (checkScanned(scObjs,cgn->cngNodeId)) { +#ifdef _DEBUG if (_setState) { - Log::out() <<"--scanEV: node "<cngNodeId - <<" opndId "<opndId<<" state "; - if (Log::isEnabled()) - printState(cgn); - Log::out() <<" to gl.esc."<< std::endl; + Log::out() <<"--scanAE > 2: was scanned earlier " << std::endl; } #endif + return; } - scannedObjs->push_back(cgn->cngNodeId); - if (cgn->outEdges != NULL) { - for (it1 = cgn->outEdges->begin( ); it1 != cgn->outEdges->end( ); it1++ ) { - scanCnGNodeRefsGE(findCnGNode_id((*it1)->cngNodeTo->cngNodeId)); - } } -} // scanCnGNodeRefsEV(CnGNode* cgn) - - -void -EscAnalyzer::scanCnGNodeRefsDA(CnGNode* cgn) { - CnGEdges* cge = cngEdges; - CnGEdges::iterator it; - CnGRefs::iterator it1; - uint32 cgntype=cgn->nodeType; - bool first=true; - if (scannedObjs->size()!=0) { - first=false; - if (checkScannedObjs(cgn->cngNodeId)) - return; - } + if (getEscState(cgn) < ARG_ESCAPE) { // not scan global escaped #ifdef _DEBUG - if (_setState) { - Log::out() <<"--scanDA: node "<cngNodeId - <<" opndId "<opndId<<" state "; - if (Log::isEnabled()) - printState(cgn); - Log::out() <<" "<nodeType<< std::endl; - } + if (_setState) { + Log::out() <<"--scanAE > 3: global escaped " << std::endl; + } #endif - if ((cgntype&NT_OBJECT && !first)||(cgntype==NT_OBJECT && first)) - scannedObjs->push_back(cgn->cngNodeId); - for (it = cge->begin( ); it != cge->end( ); it++ ) { - if ((*it)->cngNodeFrom == cgn) { - for (it1 = (*it)->refList->begin( ); it1 != (*it)->refList->end( ); it1++ ) { - scanCnGNodeRefsGE(findCnGNode_id((*it1)->cngNodeTo->cngNodeId)); - } - } - } -} // scanCnGNodeRefsDA(CnGNode* cgn) - - -void -EscAnalyzer::scanCnGNodeRefsAE(CnGNode* cgn) { - CnGEdges* cge = cngEdges; - CnGEdges::iterator it; - CnGRefs::iterator it1; - uint32 nscan=0; - if (scannedObjs->size()!=0) { - if (checkScannedObjs(cgn->cngNodeId)) - return; + return; } + if (cgn->nodeType&NT_OBJS) { +// if (cgn->nodeMDs!=NULL && check_field_elem) { + if (cgn->nodeMDs!=NULL) { + cgn->nodeMDs->push_back(curMDNode); #ifdef _DEBUG - if (_setState) { - Log::out() <<"--scanAE: node "<cngNodeId - <<" opndId "<opndId<<" state "; - if (Log::isEnabled()) - printState(cgn); - Log::out() <<" " << nodeTypeToString(cgn) <nodeType<< std::endl; - } + if (_setState) { + Log::out() <<"--scanAE 1_1: node "<cngNodeId + <<" opndId "<opndId <<" curMDNode "<nodeType&NT_OBJS) - if (getEscState(cgn) >= ARG_ESCAPE) { - setEscState(cgn,ARG_ESCAPE); + } + if (getEscState(cgn) > ARG_ESCAPE) { #ifdef _DEBUG if (_setState) { - Log::out() <<"--scanAE: node "<cngNodeId + Log::out() <<"--scanAE 2: node "<cngNodeId <<" opndId "<opndId<<" state "; if (Log::isEnabled()) printState(cgn); Log::out() <<" to arg.esc."<< std::endl; } #endif - if (cgn->nodeMDs==NULL) { - Log::out() <<"--scanAE: node "<cngNodeId - <<" opndId "<opndId<<" state "; - if (Log::isEnabled()) - printState(cgn); - Log::out() <<" " << nodeTypeToString(cgn) - << cgn->nodeType << std::endl; + 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 "; + printState(next_node); + Log::out() << " " << nodeTypeToString(next_node) + << " ref.type " << next_node->nodeRefType << std::endl; } - cgn->nodeMDs->push_back(curMDNode); +#endif + if (next_node->nodeType == NT_LDVAL) + continue; + 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); + if ((*it1)->edgeType!=ET_POINT) + nscan++; } - scannedObjs->push_back(cgn->cngNodeId); - for (it = cge->begin( ); it != cge->end( ); it++ ) { - if ((*it)->cngNodeFrom == cgn) { - for (it1 = (*it)->refList->begin( ); it1 != (*it)->refList->end( ); it1++ ) { - if ((*it1)->edgeType==ET_FIELD) // do not scan field edge - continue; - scanCnGNodeRefsAE(findCnGNode_id((*it1)->cngNodeTo->cngNodeId)); - if ((*it1)->edgeType!=ET_POINT) - nscan++; + } + if (check_var_src) { + if (ni_opcode == Op_LdVar || ni_opcode == Op_StVar || ni_opcode ==Op_Phi) { + uint32 nsrc=cgn->nInst->getNumSrcOperands(); + for (uint32 i=0; inInst->getSrc(i)->getId()); +#ifdef _DEBUG + if (_setState) { + Log::out() <<"--scanAE 4 next: node " + <cngNodeId<<" opndId "<opndId <<" state "; + printState(next_node); Log::out() << std::endl; + } +#endif + scanCnGNodeRefsAE(next_node,check_var_src); } } } - if (cgn->nodeType==NT_ARRELEM && nscan==0) { + 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) @@ -2766,92 +2916,91 @@ CnGNode* cgnode=findCnGNode_op(inst_ldbase->getSrc(0)->getId()); #ifdef _DEBUG if (_setState) { - Log::out() <<"--scanAE check1: "; + Log::out() <<"--scanAE 5 check1: "; if (Log::isEnabled()) inst_ldbase->print(Log::out()); Log::out() << std::endl; - Log::out() <<"--scanAE check2: "; + Log::out() <<"--scanAE 5 check2: "; if (cgnode==NULL) Log::out() <<"cngnode==null "<< std::endl; - Inst* inst_addindex= ((Opnd*)(cgn->refObj))->getInst(); - Log::out() <<"--scanAE arrElem: "; - if (Log::isEnabled()) - inst_addindex->print(Log::out()); - Log::out() << std::endl; - Log::out() <<"--scanAE arrElem: "; - if (Log::isEnabled()) - inst_ldbase->print(Log::out()); - Log::out() << std::endl; - Log::out() <<"--scanAE next: " << cgnode->cngNodeId << " - " + Log::out() <<"--scanAE 5 next: " << cgnode->cngNodeId << " - " << cgnode->opndId << std::endl; } #endif - scanCnGNodeRefsAE(cgnode); + if (cgnode->outEdges != NULL) { + for (it1 = cgnode->outEdges->begin( ); it1 != cgnode->outEdges->end( ); it1++ ) { + next_node = (*it1)->cngNodeTo; +#ifdef _DEBUG + if (_setState) { + Log::out() <<"--scanAE 5 next arrElem: node " + <cngNodeId<<" opndId "<opndId <<" state "; + printState(next_node); Log::out() << std::endl; + } +#endif + scanCnGNodeRefsAE(next_node,check_var_src,false); + } + } } - if (cgn->nodeType==NT_LDOBJ && nscan==0) { + if (cgn->nodeType==NT_LDOBJ && check_field_elem) { Inst* ldinst =((Opnd*)(cgn->refObj))->getInst(); if (ldinst->getOpcode()==Op_TauLdInd) { - CnGNode* cgnode=findCnGNode_op(ldinst->getSrc(0)->getId()); + 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() <<"TO FIND for opnd " - << cgn->opndId << std::endl; - if (Log::isEnabled()) - ldinst->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() <<"--scanAE 6 TO FIND 1 for opnd " + << cgn->opndId << std::endl; + if (Log::isEnabled()) + ldinst->print(Log::out()); + Log::out() << std::endl; + if (Log::isEnabled()) + inst_fldaddr->print(Log::out()); + Log::out() << std::endl; + Log::out() << cgn->cngNodeId << "-" + << cgn->opndId << " -> "; + Log::out() << cgnode->cngNodeId << "-" + << cgnode->opndId << 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()); +#ifdef _DEBUG + if (_setState) { + Log::out() << "--scanAE 6 TO FIND 2 for opnd " + << cgn->opndId << std::endl; + if (Log::isEnabled()) + ldinst->print(Log::out()); + Log::out() << std::endl; + if (Log::isEnabled()) + inst_fldaddr->print(Log::out()); + Log::out() << std::endl; + Log::out() << cgn->cngNodeId << "-" + << cgn->opndId << " -> "; + Log::out() << cgnode->cngNodeId << "-" + << cgnode->opndId << std::endl; + } +#endif + scanCnGNodeRefsAE(cgnode,check_var_src,false); + } } -#endif - scanCnGNodeRefsAE(cgnode); } } - if ((cgn->nodeType==NT_INSTFLD) && nscan==0) { //???????? - if (getEscState(cgn) > ARG_ESCAPE) - setEscState(cgn,ARG_ESCAPE); // for instance fields of method parameters & array elements +#ifdef _DEBUG + 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; } - scannedObjs->pop_back(); -} // scanCnGNodeRefsAE(CnGNode* cgn) +#endif +} // scanCnGNodeRefsAE(CnGNode* cgn, bool check_var_src, bool check_field_elem) -bool -EscAnalyzer::checkScannedObjs(uint32 id) { - ObjIds::iterator it; - for (it = scannedObjs->begin( ); it != scannedObjs->end( ); it++ ) { - if ((*it)==id) { - return true; - } - } - return false; -} // checkScannedObjs(CnGNode* cgn) - - -bool -EscAnalyzer::checkScannedInsts(uint32 id) { - ObjIds::iterator it; - for (it = scannedInsts->begin( ); it != scannedInsts->end( ); it++ ) { - if ((*it)==id) { - return true; - } - } - return false; -} // checkScannedInsts(CnGNode* cgn) - - -bool -EscAnalyzer::checkScannedSucNodes(uint32 id) { - ObjIds::iterator it; - for (it = scannedSucNodes->begin( ); it != scannedSucNodes->end( ); it++ ) { - if ((*it)==id) { - return true; - } - } - return false; -} // checkScannedSucNodes(CnGNode* cgn) - - void EscAnalyzer::printRefInfo(::std::ostream& os) { CnGNodes::iterator it; @@ -3062,7 +3211,8 @@ os << " id. " <getId(); os << " type " << type->getName() << " " << type->tag<<" "; os << " isRef " << type->isReference(); - os << " isObj " << type->isObject() << std::endl; + os << " isObj " << type->isObject(); + os << " isVal " << type->isValue() << std::endl; if (type->isReference()) ref_type_info(type,os); os << " "; @@ -3101,25 +3251,38 @@ if ((ntype==NT_STFLD)||ntype==NT_THRVAL) setFullState(cgnode,GLOBAL_ESCAPE); else { - if (ntype==NT_ACTARG) + if (ntype==NT_ACTARG) { setFullState(cgnode,ARG_ESCAPE); - else + if (inst->getOpcode()==Op_IndirectMemoryCall) + setVirtualCall(cgnode); + } else setFullState(cgnode,NO_ESCAPE); } if (ntype==NT_EXITVAL) setCalleeEscaped(cgnode); - if (type->isArray()) { - if (type->asArrayType()->isReference()) { - cgnode->nodeRefType = NR_REFARR; + 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_ARR; - } else - cgnode->nodeRefType = NR_REF; - if (ntype&(NT_OBJECT|NT_RETVAL)||ntype==NT_LDOBJ||ntype==NT_VARVAL||ntype==NT_REF||ntype==NT_ARRELEM) { - cgnode->nodeMDs = new (eaMemManager) NodeMDs(eaMemManager); // to collect methods receiving object - } else - cgnode->nodeMDs = NULL; + 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); +#ifdef _DEBUG + if (_cngnodes) { + Log::out() <<"++++ addNode "<cngNodeId + <<" opndId "<opndId; printCnGNode(cgnode,Log::out()); + Log::out() << std::endl; + } +#endif return cgnode; } // addCnGNode(MemoryManager& mm, Type* type, Inst* inst, uint32 ntype) @@ -3231,7 +3394,8 @@ insnum++; ntype=0; if (_instrInfo) { - Log::out() <<"++Node Id."<getId()<<" "<getDfNum()<getId()<<" "<getDfNum()<getId()<<" "<getDfNum()<print(Log::out()); @@ -3239,7 +3403,7 @@ } switch (inst->getOpcode()) { - case Op_LdRef: // ldstr + case Op_LdRef: // ldref case Op_NewObj: // newobj case Op_NewArray: // newarray case Op_NewMultiArray: // newmultiarray @@ -3266,6 +3430,21 @@ } break; + 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; + case Op_LdFieldAddr: // ldflda ntype=NT_INSTFLD; case Op_LdStaticAddr: // ldsflda @@ -3284,11 +3463,23 @@ if (type->isReference()) { assert(findCnGNode_op(inst->getDst()->getId())==NULL); cgnode = addCnGNode_op(inst,type,NT_REF); - if (findCnGNode_fl(inst,ntype)==NULL) { - CnGNode* n = addCnGNode_fl(inst,ntype); - cgnode->lNode=n; // stick nodes // and if fl node exists ? bug? + 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; @@ -3301,12 +3492,20 @@ debug_inst_info(inst,Log::out()); } #endif - if (inst->getDst()->getType()->isObject()) { - type=inst->getDst()->getType(); + 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; case Op_LdArrayBaseAddr: // ldbase @@ -3318,6 +3517,10 @@ debug_inst_info(inst,Log::out()); } #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); @@ -3326,6 +3529,38 @@ } break; + case Op_VMHelperCall: // callvmhelper +#ifdef _DEBUG + if (_instrInfo) { + Log::out() <<"Node Id."<getId()<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 #ifdef _DEBUG if (_instrInfo) { @@ -3334,7 +3569,7 @@ debug_inst_info(inst,Log::out()); } #endif - if (inst->getSrc(0)->getType()->isObject()) { + if ((type=inst->getSrc(0)->getType())->isObject() || type->isValue()) { addInst(cfgnode, inst); } break; @@ -3406,7 +3641,14 @@ } } method_inst=inst->getSrc(0)->getInst(); - md=method_inst->asMethodInst()->getMethodDesc(); + 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(); + } msd = md->getMethodSig(); n=msd->getNumParams(); addinst=false; @@ -3561,16 +3803,18 @@ case Op_TauMonitorEnter: // monenter case Op_TauMonitorExit: // monexit - addMonInst(inst); + if (do_sync_removal && method_ea_level == 0) { + addMonInst(inst); #ifdef _DEBUG - if (_seinfo) { - Log::out() << "iE: monX Node Id." + if (_seinfo) { + Log::out() << "iE: monX Node Id." << node->getId() << " "; - if (Log::isEnabled()) - inst->print(Log::out()); - Log::out()<print(Log::out()); + Log::out()<asFieldAccessInst())!=NULL) { - if (fainst->getFieldDesc()->getFieldType()->isReference()) { + bool isref = fainst->getFieldDesc()->getFieldType()->isReference(); + if (isref || ntype==NT_INSTFLD) { cgn_src=findCnGNode_op(inst->getDst()->getId()); // field address node - assert(cgn_src!=NULL); + if (isref) + assert(cgn_src!=NULL); cgnode=findCnGNode_fl(inst,ntype); // field node assert(cgnode!=NULL); // adding edge from fld node to address node @@ -3671,7 +3917,8 @@ break; case Op_TauLdInd: // ldind - if (inst->getDst()->getType()->isObject()) { + type=inst->getDst()->getType(); + if (type->isObject()) { cgnode=findCnGNode_op(inst->getDst()->getId()); assert(cgnode!=NULL); // ref to loaded object @@ -3679,6 +3926,14 @@ 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 @@ -3686,14 +3941,19 @@ if (inst->getDst()->getType()->isReference()) { cgnode=findCnGNode_op(inst->getDst()->getId()); assert(cgnode!=NULL); - // ref to loaded address - cgn_src=findCnGNode_op(inst->getSrc(0)->getId()); - assert(cgn_src!=NULL); + // ref to loaded address if (inst->getOpcode()==Op_LdArrayBaseAddr) { - cgnode->lNode=cgn_src; //stick array object & array base address nodes + 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) { - addEdge(cgn_src,cgnode,ET_FIELD,inst); // ref from array object to inner objects + 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; @@ -3706,7 +3966,20 @@ 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; case Op_DirectCall: // call @@ -3727,7 +4000,12 @@ case Op_IndirectMemoryCall: //callimem method_inst=inst->getSrc(0)->getInst(); - md=method_inst->asMethodInst()->getMethodDesc(); + if (method_inst->getOpcode() == Op_LdVar) { + MethodPtrType* mpt = inst->getSrc(0)->getType()->asMethodPtrType(); + md = mpt->getMethodDesc(); + } else { + md=method_inst->asMethodInst()->getMethodDesc(); + } msd = md->getMethodSig(); n=msd->getNumParams(); for (uint32 i = 0; i < n; i++) { @@ -3748,7 +4026,7 @@ assert(cgnode!=NULL); cgn_src=findCnGNode_op(inst->getSrc(0)->getId()); assert(cgn_src!=NULL); - addEdge(cgnode,cgn_src,ET_DEFER,inst); + addEdge(cgn_src,cgnode,ET_DEFER,inst); } break; @@ -3760,7 +4038,7 @@ for (uint32 i=0; igetSrc(i)->getId()); assert(cgn_src!=NULL); - addEdge(cgnode,cgn_src,ET_DEFER,inst); + addEdge(cgn_src,cgnode,ET_DEFER,inst); } } break; @@ -3827,7 +4105,7 @@ std::string t2; os << "nodeId "<cngNodeId<<" "; - if (cgn->nodeType & NT_OBJS) { //node of object created in the method + 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 @@ -3839,6 +4117,7 @@ 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; @@ -3848,7 +4127,7 @@ if (cgn->lNode) os << "( " << cgn->lNode->cngNodeId << "-" << cgn->lNode->opndId << " ) "; os << "st. "; - printState(cgn); os << " "; + printState(cgn,os); os << " "; } // printCnGNode(CnGNode* cgn,::std::ostream& os) @@ -3870,6 +4149,7 @@ 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; @@ -3901,7 +4181,7 @@ printCnGNode(*it,os); os << std::endl; os << " "; - if ((*it)->nodeType & (NT_OBJS|NT_EXITVAL)) { //node of created or exit object + 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) { @@ -3909,7 +4189,12 @@ Inst* inst = ((Opnd*)(*it)->refObj)->getInst(); inst->print(os); if (inst->getOpcode()==Op_IndirectMemoryCall) { - MethodDesc* md = inst->getSrc(0)->getInst()->asMethodInst()->getMethodDesc(); + 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); } @@ -3946,17 +4231,23 @@ os << std::endl; os << text; cgn->nInst->print(os); os << std::endl; scannedObjs->push_back(cgn->cngNodeId); - if (cgn->outEdges != NULL) + 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 = inst->getSrc(0)->getInst()->asMethodInst()->getMethodDesc(); + 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; } @@ -3990,7 +4281,12 @@ } } if (inst->getOpcode()==Op_IndirectMemoryCall) { - MethodDesc* md = inst->getSrc(0)->getInst()->asMethodInst()->getMethodDesc(); + 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; @@ -4041,7 +4337,7 @@ EscAnalyzer::findCnGNode_op(uint32 nId) { CnGNodes::iterator it; for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { - if ((*it)->opndId==nId && ((*it)->nodeType & NT_OBJS)) + if ((*it)->opndId==nId && ((*it)->nodeType & (NT_OBJS|NT_LDVAL))) return (*it); } return(NULL); @@ -4127,9 +4423,9 @@ } // findCnGNode_fl(Opnd* opnd, uint32 ntype) -/* -* Creates edge if it doesn't exist yet. -*/ +/** + * Creates edge if it doesn't exist yet. + */ void EscAnalyzer::addEdge(CnGNode* cgnfrom, CnGNode* cgnto, uint32 etype, Inst* inst) { @@ -4145,10 +4441,6 @@ assert(cgn1!=NULL); } - if (cgnto->lNode) { - cgn2=findCnGNode_id(cgnto->lNode->cngNodeId); - assert(cgn2!=NULL); - } #ifdef _DEBUG if (_cngedges) { Log::out() @@ -4185,7 +4477,7 @@ } } } else { - for ( itr = (*it)->refList->begin( ); itr != (*it)->refList->end( ); itr++ ) +/* for ( itr = (*it)->refList->begin( ); itr != (*it)->refList->end( ); itr++ ) if ((*itr)->cngNodeTo == cgn2) { // needed edge exists done = true; #ifdef _DEBUG @@ -4193,7 +4485,7 @@ Log::out() << "++++ addEdge: needed edge exists" << std::endl; } #endif - } + }--nvg */ } if (!done) { ref = new (eaMemManager) CnGRef; @@ -4229,5 +4521,2161 @@ } // addEdge(CnGNode* cgnfrom, CnGNode* cgnto, uint32 etype, Inst* inst) + +/* + Scalar replacement optimization +*/ + +void +EscAnalyzer::scanLocalObjects() { + CnGNodes::iterator it; + uint32 lo_count=0; // number of local objects + ObjIds* lnoids = NULL; // list of new opnds to optimize + ObjIds* lloids = NULL; // list of load opnds to optimize + ObjIds::iterator lo_it; + bool prTitle = true; + CnGNode* stnode = NULL; + + for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { + if ((*it)->nodeType == NT_OBJECT && getEscState(*it)==NO_ESCAPE + && getCalleeEscaped(*it) == 0 && !((*it)->nInst->getOpcode()==Op_LdRef)) { + if (prTitle) { + if (_scinfo) { + os_sc << "================ Local Object States < "; + irManager.getMethodDesc().printFullName(os_sc); + os_sc << std::endl; + } + prTitle = false; + } + lo_count++; // number of local objects + stnode = checkCnG(*it,true); + if (stnode != NULL) { + if (stnode->nodeType == NT_OBJECT) { + if (lnoids == NULL) { + lnoids = new (eaMemManager) ObjIds(eaMemManager); + } + lnoids->push_back(stnode->opndId); + } else { + if (lloids == NULL) { + lloids = new (eaMemManager) ObjIds(eaMemManager); + } + lloids->push_back(stnode->opndId); + } + } + if (_scinfo) { + os_sc << "- - - checkCnG returns "; + if (stnode == NULL) { + os_sc << " null "; + os_sc << std::endl; + } else { + printCnGNode(stnode,os_sc); os_sc << std::endl; + } + } + } + } + if (prTitle) + return; + if (_scinfo) { + os_sc << "CFGOpnds: " << irManager.getOpndManager().getNumSsaOpnds() << " CnGNodes: " + << cngNodes->size() << " Local Objects: " << lo_count << std::endl; + } + if (lnoids != NULL || lloids != NULL) { + if (_scinfo) { + if (lnoids != NULL) { + if (lnoids->size()>0) { + os_sc << "lnoids size: " << lnoids->size() << " - "; + for (lo_it=lnoids->begin(); lo_it!=lnoids->end(); lo_it++) { + os_sc << " " << (*lo_it); + } + os_sc << std::endl; + } + } + if (lloids != NULL) { + if (lloids->size()>0) { + os_sc << "lloids size: " << lloids->size() << " - "; + for (lo_it=lloids->begin(); lo_it!=lloids->end(); lo_it++) { + os_sc << " " << (*lo_it); + } + os_sc << std::endl; + } + } + } + methodEndInsts->clear(); + checkInsts->clear(); + checkOpndUsage(lnoids,lloids,true); + bool doopt = false; + if (lnoids != NULL) { + if (lnoids->size()>0) { + doopt = true; + if (_scinfo) { + os_sc << "lnoids size: " << lnoids->size() << " - "; + for (lo_it=lnoids->begin(); lo_it!=lnoids->end(); lo_it++) { + os_sc << " " << (*lo_it); + } + os_sc << std::endl; + } + } else { + if (_scinfo) { + os_sc << "lnoids size: 0" << std::endl; + } + } + } + if (lloids != NULL) { + if (lloids->size()>0) { + doopt = true; + if (_scinfo) { + os_sc << "lloids size: " << lloids->size() << " - "; + for (lo_it=lloids->begin(); lo_it!=lloids->end(); lo_it++) { + os_sc << " " << (*lo_it); + } + os_sc << std::endl; + } + } else { + if (_scinfo) { + os_sc << "lloids size: 0" << std::endl; + } + } + } + if (doopt && do_scalar_repl) { + if (lnoids != NULL) { + doLOScalarReplacement(lnoids); + } + if (lloids != NULL) { + doLOScalarReplacement(lloids); + } + } } + if (_scinfo) { + os_sc << "================ > " ; + irManager.getMethodDesc().printFullName(os_sc); + os_sc << std::endl; + } +} // scanLocalObjects() + + +void +EscAnalyzer::scanEscapedObjects() { + 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::iterator lo_it; + bool prTitle = true; + CnGNode* stnode = NULL; + + for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { +// if ((*it)->nodeType == NT_OBJECT && getEscState(*it)!=NO_ESCAPE + if ((*it)->nodeType == NT_OBJECT + && getCalleeEscaped(*it) == 0 && !((*it)->nInst->getOpcode()==Op_LdRef)) { + if ((*it)->nInst->getNode() == NULL && getEscState(*it)==NO_ESCAPE) { + continue; // already scalarized + } + ob_ref_type = (*it)->nodeRefType; // object ref type + if (ob_ref_type != NR_REF) { + continue; // vc arrays not scalarized + } + vco_count++; // number of vc objects + if (prTitle) { + if (_scinfo) { + os_sc << "================ Escaped Object States < "; + irManager.getMethodDesc().printFullName(os_sc); + os_sc << std::endl; + } + prTitle = false; + } + + stnode = checkCnG(*it,false); + if (stnode != NULL) { + if (stnode->nodeType == NT_OBJECT) { + if (lnoids == NULL) { + lnoids = new (eaMemManager) ObjIds(eaMemManager); + } + lnoids->push_back(stnode->opndId); + } else { + if (lloids == NULL) { + lloids = new (eaMemManager) ObjIds(eaMemManager); + } + lloids->push_back(stnode->opndId); + } + } + if (_scinfo) { + os_sc << "- - - checkCnG returns "; + if (stnode == NULL) { + os_sc << " null "; + os_sc << std::endl; + } else { + printCnGNode(stnode,os_sc); os_sc << std::endl; + } + } + + } + } + + if (prTitle) + return; + + if (_scinfo) { + os_sc << "CFGOpnds: " << irManager.getOpndManager().getNumSsaOpnds() << " CnGNodes: " + << cngNodes->size() << " VC Objects: " << vco_count << " lnoids size " + << (lnoids!=NULL?lnoids->size():0) << " lloids size " + << (lloids!=NULL?lloids->size():0)<< std::endl; + } + if (lnoids != NULL || lloids != NULL) { + if (_scinfo) { + if (lnoids != NULL) { + if (lnoids->size()>0) { + os_sc << "lnoids size: " << lnoids->size() << " - "; + for (lo_it=lnoids->begin(); lo_it!=lnoids->end(); lo_it++) { + os_sc << " " << (*lo_it); + } + os_sc << std::endl; + } + } + if (lloids != NULL) { + if (lloids->size()>0) { + os_sc << "lloids size: " << lloids->size() << " - "; + for (lo_it=lloids->begin(); lo_it!=lloids->end(); lo_it++) { + os_sc << " " << (*lo_it); + } + os_sc << std::endl; + } + } + } + methodEndInsts->clear(); + checkInsts->clear(); + checkOpndUsage(lnoids,lloids,false); + bool doopt = false; + if (lnoids != NULL) { + if (lnoids->size()>0) { + doopt = true; + if (_scinfo) { + os_sc << "lnoids size: " << lnoids->size() << " - "; + for (lo_it=lnoids->begin(); lo_it!=lnoids->end(); lo_it++) { + os_sc << " " << (*lo_it); + } + os_sc << std::endl; + } + } + } + if (lloids != NULL) { + if (lloids->size()>0) { + doopt = true; + if (_scinfo) { + os_sc << "lloids size: " << lloids->size() << " - "; + for (lo_it=lloids->begin(); lo_it!=lloids->end(); lo_it++) { + os_sc << " " << (*lo_it); + } + os_sc << std::endl; + } + } + } + if (doopt && do_scalar_repl) { + if (lnoids != NULL) { + doEOScalarReplacement(lnoids); + } + if (lloids != NULL) { + doEOScalarReplacement(lloids); + } + } + } + + if (_scinfo) { + os_sc << "================ > " ; + irManager.getMethodDesc().printFullName(os_sc); + os_sc << std::endl; + } +} // scanEscapedObjects() + + +void +EscAnalyzer::doLOScalarReplacement(ObjIds* loids) { + ObjIds::iterator lo_it; + CnGNode* onode; + Opnd* oopnd; + Type* otype; + Inst* inst; + Inst* st_inst; + Insts::iterator it3; + OpndManager& _opndManager = irManager.getOpndManager(); + InstFactory& _instFactory = irManager.getInstFactory(); + ScObjFlds* scObjFlds = new (eaMemManager) ScObjFlds(eaMemManager); + ScObjFld* sco = NULL; + ScObjFlds::iterator ito; + + if (loids == NULL) + return; + if (loids->size() == 0) + return; + for (lo_it=loids->begin(); lo_it!=loids->end(); lo_it++) { + onode = findCnGNode_op(*lo_it); + if (onode == NULL) { + if (_scinfo) { + os_sc << " - - no cng node for opId " << *lo_it << std::endl; + } + continue; + } + if (onode->nodeRefType == NR_PRIM) { + continue; + } + oopnd = (Opnd*)(onode->refObj); + otype = oopnd->getType(); + if (_scinfo) { + os_sc << " - - method: "; + irManager.getMethodDesc().printFullName(os_sc); + os_sc << std::endl; + if (onode->nodeRefType == NR_REF) + os_sc << " - - scalarized local instance "; + else + os_sc << " - - scalarized local array "; + os_sc << " "; printCnGNode(onode,os_sc); + ((Opnd*)onode->refObj)->printWithType(os_sc); + os_sc << std::endl; + } + + // to collect stind & ldind instructions + scObjFlds->clear(); + collectStLdInsts(onode, scObjFlds); + + if (_scinfo) { + os_sc << " found objects " << scObjFlds->size() << std::endl; + } + + if (onode->nodeType == NT_LDOBJ) { + if (_scinfo) { + os_sc << "*-*-*- not optimized " << std::endl; + } + continue; + } + + if (scObjFlds->size() > 0) { + for (ito = scObjFlds->begin( ); ito != scObjFlds->end( ); ito++ ){ + sco = (*ito); + if (sco->ls_insts->size()==0) { + continue; + } + bool do_fld_sc = false; + for (it3 = sco->ls_insts->begin(); it3 != sco->ls_insts->end( ); it3++ ) { + if ((*it3)->getOpcode() == Op_TauLdInd) { + do_fld_sc = true; + break; + } + } + if (do_fld_sc) { + Type* fl_type = NULL; + Inst* ii = sco->ls_insts->front(); + if (ii->getOpcode()==Op_TauStInd) { + fl_type = ii->getSrc(1)->getType()->asPtrType()->getPointedToType(); + } else { + fl_type = ii->getSrc(0)->getType()->asPtrType()->getPointedToType(); + } + VarOpnd* fl_var_opnd = _opndManager.createVarOpnd(fl_type, false); + SsaTmpOpnd* fl_init_opnd = _opndManager.createSsaTmpOpnd(fl_type); + Inst* ld_init_val_inst = NULL; + Inst* st_init_val_inst = NULL; + sco->fldVarOpnd = fl_var_opnd; + + if (_scinfo) { + os_sc<<" PoitedType "; fl_type->print(os_sc); os_sc <isReference()) { + ld_init_val_inst = _instFactory.makeLdNull(fl_init_opnd); + } else { + ld_init_val_inst = _instFactory.makeLdConst(fl_init_opnd, 0); + } + st_init_val_inst = _instFactory.makeStVar(fl_var_opnd, fl_init_opnd); + + scalarizeOFldUsage(sco); + if (_scinfo) { + os_sc << "++++ old newobj added fld_var: before" << std::endl; + FlowGraph::print(os_sc,onode->nInst->getNode()); + os_sc << "++++ old newobj: before end" << std::endl; + } + ld_init_val_inst->insertBefore(onode->nInst); + _instFactory.makeStVar(fl_var_opnd,fl_init_opnd)->insertBefore(onode->nInst); + if (_scinfo) { + os_sc << "++++ old newobj added fld_var: after" << std::endl; + FlowGraph::print(os_sc,onode->nInst->getNode()); + os_sc << "++++ old newobj: after end" << std::endl; + } + } else { // there was no ldind instructions + for (it3 = sco->ls_insts->begin(); it3 != sco->ls_insts->end( ); it3++ ) { + st_inst = *it3; + removeInst(st_inst); + removeInst(inst=st_inst->getSrc(1)->getInst()); + if (isBCmapRequired) { + remBCMap(st_inst); + remBCMap(inst); + } + removeInst(inst=inst->getSrc(0)->getInst()); + if (isBCmapRequired) { + remBCMap(inst); + } + if (inst->getOpcode() == Op_LdArrayBaseAddr) { + removeInst(inst->getSrc(0)->getInst()); + if (isBCmapRequired) { + remBCMap(inst->getSrc(0)->getInst()); + } + } + } + } + } + } + Node* no_node = onode->nInst->getNode(); + if (no_node != NULL) { + if (_scinfo) { + os_sc << "++++ old newobj removed: before" << std::endl; + FlowGraph::print(os_sc,no_node); + os_sc << "++++ old newobj: after end" << std::endl; + } + removeInst(onode->nInst); + if (_scinfo) { + os_sc << "++++ old newobj removed: after" << std::endl; + FlowGraph::print(os_sc,no_node); + os_sc << "++++ old newobj: after end" << std::endl; + } + if (isBCmapRequired) { + remBCMap(onode->nInst); + } + } + } +} // doLOScalarReplacement(ObjIds* loids) + + +void +EscAnalyzer::doEOScalarReplacement(ObjIds* loids) { + ObjIds::iterator lo_it; + CnGNode* onode; + Opnd* oopnd; + Type* otype; + Inst* inst; + Insts::iterator it3; + OpndManager& _opndManager = irManager.getOpndManager(); + InstFactory& _instFactory = irManager.getInstFactory(); + Insts* vc_insts = new (eaMemManager) Insts(eaMemManager); + ObjIds* vcids = new (eaMemManager) ObjIds(eaMemManager); + double entryNode_execCount = irManager.getFlowGraph().getEntryNode()->getExecCount(); + ScObjFlds* scObjFlds = new (eaMemManager) ScObjFlds(eaMemManager); + ScObjFlds* nscObjFlds = NULL; + bool lobj_opt = false; + CnGNode* lonode = NULL; + CnGNode* nonode = NULL; + + if (loids == NULL) + return; + if (loids->size() == 0) + return; + for (lo_it=loids->begin(); lo_it!=loids->end(); lo_it++) { + onode = findCnGNode_op(*lo_it); + if (onode == NULL) { + if (_scinfo) { + os_sc << " - - no cng node for opId " << *lo_it << std::endl; + } + continue; + } + if (onode->nodeRefType == NR_PRIM) { + continue; + } + if (onode->nodeType == NT_OBJECT) { + lobj_opt = false; + } else { + lobj_opt = true; + } + oopnd = (Opnd*)(onode->refObj); + otype = oopnd->getType(); + double path_prob = -1; + path_prob = checkLocalPath(onode->nInst); + os_sc<<"pp " << (path_prob )<nodeRefType == NR_REF) + os_sc << " - - scalarized escaped instance "; + else + os_sc << " - - scalarized escaped array "; + os_sc << " "; printCnGNode(onode,os_sc); + ((Opnd*)onode->refObj)->printWithType(os_sc); + os_sc << std::endl; + } + if (onode->nodeRefType != NR_REF) { + return; + } + lonode = NULL; + nonode = NULL; + if (lobj_opt) { +#ifdef _DEBUG + if (_scinfo) { + findObject1(onode->nInst); + } +#endif + if (onode->nInst->getOpcode() != Op_LdVar) { + if (_scinfo) { + os_sc << " doEO 1 "; onode->nInst->print(os_sc); + os_sc << std::endl; + } + continue; + } + Inst* phi = onode->nInst->getSrc(0)->getInst(); + if (phi->getOpcode() != Op_Phi) { + if (_scinfo) { + os_sc << " doEO 2 "; phi->print(os_sc); + os_sc << std::endl; + } + continue; + } + uint32 nsrc = phi->getNumSrcOperands(); + if (nsrc > 2) { + if (_scinfo) { + os_sc << " doEO 3" << std::endl; + } + continue; + } + for (uint32 i=0; igetSrc(i)->getInst(); + if (_scinfo) { + os_sc << " doEO phi "; inst->print(os_sc); + os_sc << std::endl; + } + if (inst->getOpcode() != Op_StVar) { + break; + } + inst = inst->getSrc(0)->getInst(); + if (_scinfo) { + os_sc << " doEO stvar "; inst->print(os_sc); + os_sc << std::endl; + } + if (inst->getOpcode() == Op_NewObj && nonode == NULL) { + nonode = findCnGNode_op(inst->getDst()->getId()); + continue; + } + if ((inst->getOpcode() == Op_LdVar || inst->getOpcode() == Op_TauLdInd) + && lonode == NULL) { + lonode = findCnGNode_op(inst->getDst()->getId()); + continue; + } + } + if (nonode == NULL || lonode == NULL) { + if (_scinfo) { + os_sc << " doEO 4" << std::endl; + if (nonode == NULL) { + os_sc << " nonode NULL" << std::endl; + } + if (lonode == NULL) { + os_sc << " lonode NULL" << std::endl; + } + } + continue; + } + if (_scinfo) { + os_sc << " no_src "; printCnGNode(nonode,os_sc); os_sc << std::endl; + os_sc << " lo_src "; printCnGNode(lonode,os_sc); os_sc << std::endl; + } + } else { + nonode = onode; + } + + // to collect stind & ldind instructions + scObjFlds->clear(); + collectStLdInsts(onode, scObjFlds); + + if (lobj_opt) { + collectCallInsts(nonode->cngNodeId, vc_insts, vcids); + if (vc_insts->size() > 0 ) { + if (_scinfo) { + os_sc << "--- no opt: newobj escaped " << std::endl; + for (it3=vc_insts->begin(); it3!=vc_insts->end(); it3++) { + (*it3)->print(os_sc); os_sc << std::endl; + } + } + continue; + } + // to collect stind & ldind instructions for newobj + if (nscObjFlds == NULL) { + nscObjFlds = new (eaMemManager) ScObjFlds(eaMemManager); + } else { + nscObjFlds->clear(); + } + collectStLdInsts(nonode, nscObjFlds); + if (_scinfo) { + os_sc << " found objects for newobj " << nscObjFlds->size() << std::endl; + } + if (!checkObjFlds(nscObjFlds, scObjFlds)) { + if (_scinfo) { + os_sc << " checkObjFlds failed " << std::endl; + } + continue; + } + if (_scinfo) { + os_sc << " checkObjFlds passed " << std::endl; + } + } + + // to collect call & callimem instructions + collectCallInsts(onode->cngNodeId, vc_insts, vcids); + + if (_scinfo) { + os_sc << " found objects " << scObjFlds->size() << " vc_inst " << vc_insts->size() + << std::endl; + } + if (_scinfo) { + if (lobj_opt) { + for (it3=vc_insts->begin(); it3!=vc_insts->end(); it3++) { + (*it3)->print(os_sc); os_sc << std::endl; + } + } + } + + if (lobj_opt) { + if (checkInsts != NULL) { + fixCheckInsts(onode->opndId); + } + } + TypeManager& _typeManager = irManager.getTypeManager(); + Type* typeInt32 = _typeManager.getInt32Type(); + Inst* nobj_inst = nonode->nInst; // optimized newobj inst for ldvar opnd + Inst* lobj_inst = NULL; // load opnd inst for ldvar opnd + Edge* excedge = NULL; + VarOpnd* ob_flag_opnd = _opndManager.createVarOpnd(typeInt32, false); + VarOpnd* ob_var_opnd = _opndManager.createVarOpnd(nobj_inst->getDst()->getType(), false); + SsaTmpOpnd* ob_init_opnd = NULL; + uint32 ob_id = onode->opndId; + Node* ob_exc_tnode = NULL; + Insts::iterator itvc; + ScObjFlds::iterator ito; + Node* node_no = NULL; + ScObjFld* sco = NULL; + + insertLdConst(1); + insertLdConst(0); + + if (nobj_inst->getOperation().canThrow()==true) { + excedge = (Edge*)nobj_inst->getNode()->getExceptionEdge(); + assert(excedge != NULL); + ob_exc_tnode = excedge->getTargetNode(); + } + if (lobj_opt) { + lobj_inst = lonode->nInst; + } + if (scObjFlds->size() > 0) { + ob_init_opnd = _opndManager.createSsaTmpOpnd(ob_var_opnd->getType()); + node_no = nobj_inst->getNode(); + for (ito = scObjFlds->begin( ); ito != scObjFlds->end( ); ito++ ){ + sco = (*ito); + if (sco->ls_insts->size()==0) + continue; + Type* fl_type = NULL; + Inst* ii = sco->ls_insts->front(); + Inst* iadr = NULL; + if (ii->getOpcode()==Op_TauStInd) { + iadr=ii->getSrc(1)->getInst(); + fl_type = ii->getSrc(1)->getType()->asPtrType()->getPointedToType(); + } else { + iadr=ii->getSrc(0)->getInst(); + fl_type = ii->getSrc(0)->getType()->asPtrType()->getPointedToType(); + } + VarOpnd* fl_var_opnd = _opndManager.createVarOpnd(fl_type, false); + SsaTmpOpnd* fl_init_opnd = _opndManager.createSsaTmpOpnd(fl_type); + Inst* ld_init_val_inst = NULL; + Inst* st_init_val_inst = NULL; + sco->fldVarOpnd = fl_var_opnd; + + if (_scinfo) { + os_sc<<" PoitedType "; fl_type->print(os_sc); os_sc <isReference()) { + ld_init_val_inst = _instFactory.makeLdNull(fl_init_opnd); + } else { + ld_init_val_inst = _instFactory.makeLdConst(fl_init_opnd, 0); + } + st_init_val_inst = _instFactory.makeStVar(fl_var_opnd, fl_init_opnd); + scalarizeOFldUsage(sco); + if (_scinfo) { + os_sc << "++++ old newobj added fld_var: before" << std::endl; + FlowGraph::print(os_sc,node_no); + os_sc << "++++ old newobj: before end" << std::endl; + } + ld_init_val_inst->insertBefore(nobj_inst); + _instFactory.makeStVar(fl_var_opnd,fl_init_opnd)->insertBefore(nobj_inst); + if (_scinfo) { + os_sc << "++++ old newobj added fld_var: after" << std::endl; + FlowGraph::print(os_sc,node_no); + os_sc << "++++ old newobj: after end" << std::endl; + } + if (lobj_opt) { + // + Modifier mod = ii->getModifier(); + Opnd* ld_tau_op = _opndManager.createSsaTmpOpnd(_typeManager.getTauType()); + Inst* itau = _instFactory.makeTauUnsafe(ld_tau_op); + itau->insertAfter(lobj_inst); + FieldDesc* fd = iadr->asFieldAccessInst()->getFieldDesc(); + Opnd* dst_ld = _opndManager.createSsaTmpOpnd(iadr->getDst()->getType()); + Opnd* ob_opnd = (Opnd*)(lonode->refObj); + Inst* lda = _instFactory.makeLdFieldAddr(dst_ld,ob_opnd,fd); + lda->insertAfter(itau); + SsaTmpOpnd* fl_tmp_opnd_ld = _opndManager.createSsaTmpOpnd(fl_type); + Inst* ldf = _instFactory.makeTauLdInd(mod,fl_var_opnd->getType()->tag, + fl_tmp_opnd_ld,dst_ld,ld_tau_op,ld_tau_op); + ldf->insertAfter(lda); + Inst* stv = _instFactory.makeStVar(fl_var_opnd,fl_tmp_opnd_ld); + stv->insertAfter(ldf); + } + } + } + if ((nscObjFlds != NULL) && (nscObjFlds->size() > 0)) { + for (ito = nscObjFlds->begin( ); ito != nscObjFlds->end( ); ito++ ) { + sco = (*ito); + if (sco->ls_insts->size()==0) { + continue; + } + ScObjFlds::iterator it2; + for (it2=scObjFlds->begin(); it2!=scObjFlds->end(); it2++) { + if (sco->fd == (*it2)->fd) { + sco->fldVarOpnd = (*it2)->fldVarOpnd; + break; + } + } + assert(sco->fldVarOpnd!=NULL); + scalarizeOFldUsage(sco); + } + } + restoreEOCreation(vc_insts, scObjFlds, ob_var_opnd, ob_flag_opnd, + ob_exc_tnode, ob_id); + if (_scinfo) { + os_sc << "++++ old newobj: before" << std::endl; + FlowGraph::print(os_sc,node_no); + os_sc << "++++ old newobj: before end" << std::endl; + if (lobj_opt) { + os_sc << "++++ old ldobj: before" << std::endl; + FlowGraph::print(os_sc,lonode->nInst->getNode()); + os_sc << "++++ old ldobj: before end" << std::endl; + } + } + _instFactory.makeStVar(ob_flag_opnd, i32_0)->insertBefore(nobj_inst); + _instFactory.makeLdNull(ob_init_opnd)->insertBefore(nobj_inst); + _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) + fixMethodEndInsts(ob_id); + removeInst(nobj_inst); + if (isBCmapRequired) { + remBCMap(nobj_inst); + } + if (_scinfo) { + os_sc << "++++ old newobj: after" << std::endl; + FlowGraph::print(os_sc,node_no); + os_sc << "++++ old newobj: after end" << std::endl; + if (lobj_opt) { + os_sc << "++++ old ldobj:after" << std::endl; + FlowGraph::print(os_sc,lonode->nInst->getNode()); + os_sc << "++++ old ldobj: after end" << std::endl; + } + } + + if (lobj_opt) { // remove ldvar, phi, stvar + Inst* phi = onode->nInst->getSrc(0)->getInst(); + if (phi->getOpcode() != Op_Phi) { + assert(0); + } + uint32 nsrc = phi->getNumSrcOperands(); + + for (uint32 i=0; igetSrc(i)->getInst(); + removeInst(inst); + } + removeInst(phi); + removeInst(onode->nInst); + } + + scObjFlds->clear(); + if (nscObjFlds != NULL) { + nscObjFlds->clear(); + } + } + +} // doEOScalarReplacement(ObjIds* loids) + + +void +EscAnalyzer::collectStLdInsts(CnGNode* onode, ScObjFlds* scObjFlds) { + ScObjFld* scObjFld = NULL; + CnGRefs::iterator it1; + CnGRefs::iterator it2; + Inst* inst; + CnGNode* fnode; + + if (onode->outEdges != NULL) { + for (it1 = onode->outEdges->begin(); it1 != onode->outEdges->end(); it1++) { + if ((*it1)->edgeType == ET_FIELD) { + scObjFld = new (eaMemManager) ScObjFld; + scObjFld->fldVarOpnd=NULL; + scObjFld->isFinalFld=false; + Insts* fl_insts = new (eaMemManager) Insts(eaMemManager); + fnode =(*it1)->cngNodeTo; + if (fnode->outEdges == NULL) { + if (_scinfo) { + os_sc << "collectStLdInsts: no ref from fld" << std::endl; + printCnGNode(onode, os_sc); os_sc << std::endl; + printCnGNode(fnode, os_sc); os_sc << std::endl; + } + continue; + } + for (it2 = fnode->outEdges->begin(); it2 != fnode->outEdges->end(); it2++) { + inst = (*it2)->edgeInst; + if (_scinfo) { + os_sc << "- - - to remove: "; + FlowGraph::printLabel(os_sc,inst->getNode()); os_sc<<" "; + inst->print(os_sc); os_sc<< std::endl; + } + fl_insts->push_back(inst); + if (_scinfo) { + if (inst->getOpcode() == Op_TauStInd) { + inst=inst->getSrc(1)->getInst(); + } + if (inst->getOpcode() == Op_TauLdInd) { + inst=inst->getSrc(0)->getInst(); + } + os_sc << " "; + FlowGraph::printLabel(os_sc,inst->getNode()); os_sc<<" "; + inst->print(os_sc); os_sc << std::endl; + os_sc << " "; + FlowGraph::printLabel(os_sc,inst->getSrc(0)->getInst()->getNode()); os_sc<<" "; + (inst->getSrc(0)->getInst())->print(os_sc); os_sc << std::endl; + } + } + if (fnode->nInst->getOpcode()==Op_LdFieldAddr) { + FieldDesc* fdesc = fnode->nInst->asFieldAccessInst()->getFieldDesc(); + scObjFld->fd = fdesc; + if (fdesc->isInitOnly()) { + scObjFld->isFinalFld=true; + } + } + scObjFld->ls_insts = fl_insts; + scObjFlds->push_back(scObjFld); + } else { + os_sc << " --- col error: not a field "; (*it1)->edgeInst->print(os_sc); + os_sc << std::endl; + } + } + } else { + if (_scinfo) { + os_sc << "- - - to remove 2: "; + onode->nInst->print(os_sc); + os_sc << std::endl; + } + } +} // collectStLdInsts(CnGNode* onode, ScObjFld* scObjFlds) + + +void +EscAnalyzer::collectCallInsts(uint32 n, Insts* vc_insts, ObjIds* vcids) { + CnGEdges::iterator ite; + CnGRefs::iterator it2; + + vc_insts->clear(); + vcids->clear(); + for (ite = cngEdges->begin( ); ite != cngEdges->end( ); ite++ ) { + for (it2 = (*ite)->refList->begin( ); it2 != (*ite)->refList->end( ); it2++ ) { + if ((*it2)->cngNodeTo->cngNodeId == n) { + Inst* ii=(*ite)->cngNodeFrom->nInst; + uint32 opc = ii->getOpcode(); + if (opc == Op_IndirectMemoryCall || opc == Op_DirectCall) { + if (!checkScanned(vcids,ii->getId())) { + vc_insts->push_back(ii); + vcids->push_back(ii->getId()); + } + } + } + } + } +} // collectCallInsts(CnGNode* onode, ScObjFld* scObjFlds) + + +void +EscAnalyzer::scalarizeOFldUsage(ScObjFld* scfld) { + Insts* sl_insts = scfld->ls_insts; + VarOpnd* fl_var_opnd = scfld->fldVarOpnd; + uint32 nsrco = 0; + Inst* inst_ad; + Inst* st_ld_var_inst; + Inst* st_ld_inst; + InstFactory& _instFactory = irManager.getInstFactory(); + Node* node_before = NULL; + Insts::const_iterator it; + + for (it = sl_insts->begin( ); it != sl_insts->end( ); it++ ) { + st_ld_inst = *it; + node_before = st_ld_inst->getNode(); + if (node_before==NULL) { + os_sc << "node_before NULL "; st_ld_inst->print(os_sc); os_sc << std::endl; + } + if (_scinfo) { + os_sc << "++++ scalarizeOFldUsage: before" << std::endl; + FlowGraph::print(os_sc,node_before); + os_sc << "++++ scalarizeOFldUsage: before end" << std::endl; + } + if (st_ld_inst->getOpcode() == Op_TauStInd) + nsrco = 1; + else + nsrco = 0; + inst_ad = st_ld_inst->getSrc(nsrco)->getInst(); // receives address to load/store + if (nsrco == 0) { + st_ld_var_inst = _instFactory.makeLdVar(st_ld_inst->getDst(), fl_var_opnd); + } else { + st_ld_var_inst = _instFactory.makeStVar(fl_var_opnd, st_ld_inst->getSrc(0)); + } + st_ld_var_inst->insertAfter(st_ld_inst); + removeInst(st_ld_inst); + if (isBCmapRequired) { + setNewBCMap(st_ld_var_inst,st_ld_inst); + } + removeInst(inst_ad); + if (isBCmapRequired) { + remBCMap(inst_ad); + } + if (inst_ad->getOpcode()==Op_AddScaledIndex) { + removeInst(inst_ad->getSrc(0)->getInst()); + if (isBCmapRequired) { + remBCMap(inst_ad->getSrc(0)->getInst()); + } + } + if (_scinfo) { + os_sc << "++++ scalarizeOFldUsage: after" << std::endl; + FlowGraph::print(os_sc,node_before); + + os_sc << "++++ scalarizeOFldUsage: after end" << std::endl; + } + } +} // scalarizeOFldUsage(ScObjFld* scfld) + + +void +EscAnalyzer::checkOpndUsage(ObjIds* lnoids, ObjIds* lloids, bool check_loc) { + const Nodes& nodes = irManager.getFlowGraph().getNodes(); + Nodes::const_iterator niter; + bool maydo = true; + bool do_break = false; + + if (_scinfo) { + os_sc << " -------- Objects used in: check_loc " << check_loc << 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()) { + uint32 nsrc = inst->getNumSrcOperands(); + for (uint32 i=0; igetSrc(i))->isSsaOpnd()) { // check ssa operands + if (_scinfo) { + os_sc << " not ssa opnd " << i << " "; + inst->print(os_sc); os_sc << std::endl; + } + continue; + } + uint32 opcode=inst->getOpcode(); + if (checkScanned(lnoids,opnd->getId())) { + if (_scinfo) { + os_sc << " no "; FlowGraph::printLabel(os_sc,inst->getNode()); + os_sc << " "; inst->print(os_sc); os_sc << std::endl; + } + if (opcode == Op_MethodEnd) { + methodEndInsts->push_back(inst); + continue; + } + if (opcode == Op_LdFieldAddr || opcode == Op_LdArrayBaseAddr) + continue; + if (!check_loc) + if (opcode == Op_IndirectMemoryCall || opcode == Op_DirectCall) + continue; + + maydo = false; + if (_scinfo) { + os_sc << " no remove " << opnd->getId() << std::endl; + } + lnoids->remove(opnd->getId()); + } + if (checkScanned(lloids,opnd->getId())) { + if (_scinfo) { + 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) { + checkInsts->push_back(inst); + continue; + } + if (opcode == Op_MethodEnd) { + methodEndInsts->push_back(inst); + continue; + } + if (opcode == Op_LdFieldAddr || opcode == Op_LdArrayBaseAddr) + continue; + if (!check_loc) { + if (opcode == Op_IndirectMemoryCall || opcode == Op_DirectCall) { + continue; + } + } + maydo = false; + if (_scinfo) { + os_sc << " lo remove " << opnd->getId() << std::endl; + } + lloids->remove(opnd->getId()); + } + if ((lnoids == NULL || lnoids->size() == 0) + && (lloids == NULL || lloids->size() == 0)) { + do_break = true; + break; + } + } + if (do_break) { + break; + } + } + } + if (_scinfo) { + os_sc << " -------- " << std::endl; + } + return; +} // checkOpndUsage(ObjIds* loids,bool check_loc,::std::ostream& os_sc) + + +bool +EscAnalyzer::checkOpndUsage(uint32 lobjid) { + const Nodes& nodes = irManager.getFlowGraph().getNodes(); + Nodes::const_iterator niter; + bool maydo = true; + uint32 n_used = 0; + + if (_scinfo) { + os_sc << " -------- Used in " << 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()==lobjid) { + n_used++; + 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_LdFieldAddr && opcode != Op_LdArrayBaseAddr && + opcode != Op_IndirectMemoryCall && opcode != Op_DirectCall && + opcode != Op_MethodEnd && opcode != Op_StVar) { + maydo = false; + } + } + } + } + } + if (_scinfo) { + os_sc << " -------- opnd used: " << n_used << " maydo " << maydo << std::endl; + } + return maydo; +} // checkOpndUsage(uint32 lobjid) + + +EscAnalyzer::CnGNode* +EscAnalyzer::checkCnG(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 + uint32 ob_nfld_count=0; // number of object references to not a field + uint32 ref_to_obj_count=0; // number references to object + uint32 vcall_count=0; // number of virtual calls + uint32 call_count=0; // number of calls + uint32 ob_fld_stind_count=0; // number of stores in object field + uint32 ob_fld_ldind_count=0; // number of loads from object field + uint32 ob_fld_field_count=0; // number of fields of object field + uint32 ob_fld_unkn_count=0; // number of unknown references of object field + uint32 ob_fld_usage_count=0; // number of object field usage + uint32 ob_stvar_count=0; // number of object stvar + bool storeId = false; + CnGRefs::iterator it1; + CnGRefs::iterator it2; + CnGEdges::iterator ite; + CnGNode* nf = NULL; + CnGNode* vnode = NULL; + CnGNode* rnode = scnode; + uint32 scnode_type = scnode->nodeType; + + ob_ref_type = scnode->nodeRefType; // object ref type + if (!check_loc && (ob_ref_type != NR_REF)) + return NULL; // vc arrays not scalarized + if (_scinfo) { + os_sc << "=="; printCnGNode(scnode,os_sc); + ((Opnd*)scnode->refObj)->printWithType(os_sc); + os_sc << std::endl; + os_sc << " =="; ((Opnd*)scnode->refObj)->getInst()->print(os_sc); + os_sc << std::endl; + checkOpndUsage(scnode->opndId); + } + + if (_scinfo) { + os_sc << " -------- begin - Ref from node " << scnode->cngNodeId << " - " + << scnode->opndId << std::endl; + } + if (scnode->outEdges != NULL) { + for (it1 = scnode->outEdges->begin(); it1 != scnode->outEdges->end(); it1++) { + if ((*it1)->edgeType == ET_FIELD) { + ob_fld_count++; // number of object fields + if (_scinfo) { + os_sc<<"++ "<cngNodeId<< " -> " << + (*it1)->cngNodeTo->cngNodeId << " - "<< + (*it1)->cngNodeTo->opndId << std::endl; + } + nf = (*it1)->cngNodeTo; // object field cng node + if (nf->nInst->getOpcode()==Op_LdFieldAddr) { // ??? + FieldDesc* fdesc = nf->nInst-> + asFieldAccessInst()->getFieldDesc(); + if (fdesc->isInitOnly()) + ob_fin_fld_count++; + } + if (nf->outEdges != NULL || + (*it1)->cngNodeTo->nInst->getOpcode() != Op_LdArrayBaseAddr) { + ob_fld_usage_count++; + if (_scinfo) { + os_sc << " fld-" << std::endl << " "; + printCnGNode(nf,os_sc); os_sc << std::endl << " "; + (*it1)->cngNodeTo->nInst->print(os_sc); os_sc << std::endl; + } + } + if (nf->outEdges != NULL) { + for (it2 = nf->outEdges->begin( ); it2 != nf->outEdges->end( ); it2++ ) { + if (_scinfo) { + os_sc << " " << edgeTypeToString(*it2) << std::endl; + } + switch ((*it2)->edgeType) { + case ET_POINT: ob_fld_ldind_count++; break; + case ET_DEFER: ob_fld_stind_count++; break; + case ET_FIELD: ob_fld_field_count++; break; + default: ob_fld_unkn_count++; + } + if (_scinfo) { + CnGNode* node = NULL; + if ((node=findCnGNode_id((*it2)->cngNodeTo->cngNodeId))!=NULL) { + os_sc << " "; + printCnGNode(node,os_sc); os_sc << std::endl << " "; + node->nInst->print(os_sc); os_sc << std::endl; + os_sc << " "; + (*it2)->edgeInst->print(os_sc); + os_sc << std::endl; + } + } + } + } + } else { + if ((*it1)->cngNodeTo->nInst->getOpcode() == Op_StVar) { + ob_stvar_count++; + if (ob_stvar_count == 1) { + vnode =(*it1)->cngNodeTo; + } + } else { + ob_nfld_count++; + } + if (_scinfo) { + os_sc << " not_fld " << edgeTypeToString(*it1) << " "; + (*it1)->cngNodeTo->nInst->print(os_sc); os_sc << std::endl; + } + } + } + } + if (_scinfo) { + os_sc << " -------- end - Ref from node " << std::endl; + } + uint32 n=scnode->cngNodeId; + + if (_scinfo) { + os_sc << " -------- begin - Ref to node " << scnode->cngNodeId << " - " + << scnode->opndId << std::endl; + } + for (ite = cngEdges->begin( ); ite != cngEdges->end( ); ite++ ) { + for (it2 = (*ite)->refList->begin( ); it2 != (*ite)->refList->end( ); it2++ ) { + if ((*it2)->cngNodeTo->cngNodeId == n) { + Inst* ii=(*ite)->cngNodeFrom->nInst; + uint32 opc = ii->getOpcode(); + if (opc == Op_IndirectMemoryCall || opc == Op_DirectCall) { + if (opc == Op_IndirectMemoryCall) + vcall_count++; + else + call_count++; + } else + ref_to_obj_count++; // number of ref to object + if (_scinfo) { + os_sc << " Ref to object. Edge: " << (*ite)->cngNodeFrom->cngNodeId + << " - " << (*ite)->cngNodeFrom->opndId << " -> " + << (*it2)->cngNodeTo->cngNodeId + << " - " << (*it2)->cngNodeTo->opndId << std::endl << " "; + printCnGNode((*ite)->cngNodeFrom,os_sc); + os_sc << std::endl << " "; + ii->print(os_sc); os_sc << std::endl; + if (ii->getOpcode()==Op_IndirectMemoryCall) { + MethodDesc* md = getMD(ii); + os_sc<<" ";md->printFullName(os_sc);os_sc << std::endl; + } + } + } + } + } + if (_scinfo) { + os_sc << " -------- end - Ref to node " << std::endl; + } + + if (ob_nfld_count == 0 && + ( (scnode_type == NT_OBJECT && ref_to_obj_count == 0) + || (scnode_type == NT_LDOBJ && ref_to_obj_count == 1 && ob_stvar_count == 0) ) ) { + if (scnode_type == NT_LDOBJ) { + if (ob_fin_fld_count==ob_fld_usage_count) { + if ( (check_loc && (getEscState(scnode)==NO_ESCAPE)) || + (!check_loc && (getEscState(scnode)!=NO_ESCAPE)) ) { + storeId = true; + } else { + if (_scinfo) { + os_sc << "----scalar no opt: check_loc " << check_loc + << " state " << getEscState(scnode) << std::endl; + } + } + } else { + if (_scinfo) { + os_sc << "----scalar no opt: LOBJ final fields " << ob_fin_fld_count + << " used field " << ob_fld_usage_count << std::endl; + } + } + goto MM; + } + if (ob_ref_type == NR_REF) { // NT_OBJECT - object + if (ob_stvar_count == 1) { // find ldvar target operand + if (ob_fin_fld_count!=ob_fld_usage_count) { + if (_scinfo) { + os_sc << "----scalar no opt: stvar=1 final fields " << ob_fin_fld_count + << " used field " << ob_fld_usage_count << std::endl; + } + goto MM; + } + + if (_scinfo) { + os_sc << "************* " << ((Opnd*)scnode->refObj)->getType()->getName() + << std::endl; + } + assert(vnode==0); + CnGNode* lobj = getLObj(vnode); // scalarizable load object + if (lobj != NULL) { + if (_scinfo) { + findObject1(lobj->nInst," "); + } + bool notnullsrcs = checkVVarSrcs(lobj->nInst); + if (_scinfo) { + os_sc << "----checkCnG: stvar=1 checkVVSrcs " << notnullsrcs << std::endl; + } + if (!notnullsrcs) { + goto MM; + } + if (_scinfo) { + os_sc << "----check srcs opernds for optimized load object (cng node): " + << lobj->cngNodeId << std::endl; + } + rnode = checkCnG(lobj,check_loc); + if (rnode!=NULL) { + storeId =true; + } + } + goto MM; + } + // to optimize newobj target operand + if (check_loc) { //local object + assert(vcall_count==0 && call_count==0); + storeId = true; + goto MM; + } + // to optimize escaped object + if (do_scalar_repl_only_final_fields) { + if (ob_fin_fld_count==ob_fld_usage_count) { + storeId = true; + } else { + if (_scinfo) { + os_sc << "----scalar no opt: onlyFF final fields " << ob_fin_fld_count + << " used field " << ob_fld_usage_count << std::endl; + } + } + } else { + if (ob_fin_fld_count==ob_fld_usage_count) { // objects with only final fields + storeId = true; + } else { + // not global escaped objects may be scalarized + if (getEscState(scnode)!=GLOBAL_ESCAPE && getVirtualCall(scnode)==0) { + storeId = true; + } else { + if (_scinfo) { + os_sc << "----scalar no opt: GLOBAL, fin.flds " << ob_fin_fld_count + << " used flds " << ob_fld_usage_count << std::endl; + } + } + } + } + goto MM; + } + // NT_OBJECT - array + if (ob_fld_usage_count <= 1 && check_loc && ob_stvar_count == 0) { + storeId = true; + } else { + if (_scinfo) { + os_sc << "----scalar no opt: arr: fld " << ob_fld_count + << " used flds " << ob_fld_usage_count << std::endl; + } + } + } else { + if (_scinfo) { + os_sc << "----scalar no opt: ref to " << ref_to_obj_count << " not field " + << ob_nfld_count << " obj stvar " << ob_stvar_count << std::endl; + } + } +MM: + if (_scinfo) { + os_sc << "----checkCnG: ntype " << scnode->nodeType + << " flds " << ob_fld_count + << " not flds " << ob_nfld_count + << " final flds " << ob_fin_fld_count + << " used flds " << ob_fld_usage_count + << " vcalls " << vcall_count + << " calls " << call_count + << " stored " << ob_fld_stind_count + << " loaded " << ob_fld_ldind_count + << " others " << ob_fld_field_count + << " ref to " << ref_to_obj_count + << " stvar " << ob_stvar_count + << " unkn.refs " << ob_fld_unkn_count << std::endl; + } + if (storeId) { + if (_scinfo) { + os_sc << "----scalar may be opt: "; printCnGNode(scnode,os_sc); + os_sc << std::endl; + } + return rnode; + } + if (_scinfo) { + os_sc << "----scalar no opt: "; printCnGNode(scnode,os_sc); + os_sc << std::endl; + } + return NULL; + +} // checkCnG(CnGNode* scnode, bool check_loc) + + +double +EscAnalyzer::checkLocalPath(Inst* nob_inst) { + double prob = 0; + Node* node = nob_inst->getNode(); + Opnd* objOpnd = nob_inst->getDst(); + uint32 objId = objOpnd ->getId(); + + if (_scinfo) { + os_sc << " -------- Find local path for "; FlowGraph::printLabel(os_sc,node); + os_sc << " id." << node->getId() << " "; + nob_inst->print(os_sc); os_sc << std::endl; + } + + scannedObjs->clear(); + scannedObjsRev->clear(); // to store ids of unsuccessful nodes + scannedSucNodes->clear(); // to store ids of unsuccessful nodes + if (node->getKind() != Node::Kind_Exit) + prob = checkNextNodes(node,objId,0); + + if (_scinfo) { + double enc = irManager.getFlowGraph().getEntryNode()->getExecCount(); + os_sc << " Path count " << prob << " ENTRY node count " << enc + << " exec_count_mult " << ec_mult << std::endl; + if (prob!=0 && prob>=enc*ec_mult) + os_sc << " -------- Local path found " << std::endl; + else + os_sc << " -------- Local path not found " << std::endl; + } + return prob; +} // checkLocalPath(Inst* nob_inst) + + +double +EscAnalyzer::checkNextNodes(Node* n, uint32 obId, double cprob, std::string text) { + Node* node = n; + Inst *headInst = (Inst*)node->getFirstInst(); + Opnd* opnd; + Edges::const_iterator eit; + double cnprob = node->getExecCount(); + double r = cnprob>cprob?cnprob:cprob; + double no = -4; + + if (node->getKind()==Node::Kind_Exit) { + if (_scinfo) { + os_sc << " **** Node EXIT : "; FlowGraph::printLabel(os_sc,node); + os_sc << " id." << node->getId() << " execCount " << node->getExecCount() + << " in prob " << cprob << std::endl; + } + 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; + } + if (scannedObjsRev->size()!=0) { + if (checkScannedObjsRev(node->getId())) + return no; + } + 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(); + for (uint32 i=0; igetSrc(i); + if (opnd->getId()==obId) { + if (_scinfo) { + inst->print(os_sc); os_sc << std::endl; + } + return no; + } + } + } + } + + scannedObjs->push_back(node->getId()); + Node* tn1; + Node* tn2; + double r0=-1; + double r1=-1; + 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 + } 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 + } + 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 + } + if (r1==-1 && r2==-1) + r0=no; + else + r0=r1>r2?r1:r2; + } + if (r0==no) { + scannedObjsRev->push_back(node->getId()); + return r0; + } else { + scannedSucNodes->push_back(node->getId()); + } + if (r0>r) + return r0; + return r; + +} // checkNextNodes(Node* n, uint32 obId, double cprob, std::string text)) + + +void +EscAnalyzer::restoreEOCreation(Insts* vc_insts, ScObjFlds* scObjFlds, VarOpnd* ob_var_opnd, + VarOpnd* ob_flag_var_opnd, Node* tnode, uint32 oid) { + Insts::iterator itvc; + InstFactory& _instFactory = irManager.getInstFactory(); + ControlFlowGraph& fg = irManager.getFlowGraph(); + OpndManager& _opndManager = irManager.getOpndManager(); + TypeManager& _typeManager = irManager.getTypeManager(); + 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_after1 = NULL; // node with field var opnds updating after call + ScObjFlds::iterator ito; + const bool splitAfter = true; + SsaTmpOpnd* ob_opnd = NULL; + Opnd* ld_tau_op = NULL; + + for (itvc = vc_insts->begin( ); itvc != vc_insts->end( ); itvc++ ) { + Inst* vc = *itvc; + uint32 i; + uint32 nsrc = vc->getNumSrcOperands(); + + for (i=0; igetSrc(i); + if (opnd->getId()==oid) { + break; + } + } + if (i>=nsrc) { + continue; + } + + node_before=vc->getNode(); + node_obj1 = NULL; + node_after1 = NULL; + ld_tau_op = NULL; + if (_scinfo) { + os_sc << "++++ objectCreate: before" << std::endl; + FlowGraph::print(os_sc,node_before); + os_sc << "++++ objectCreate: before end" << std::endl; + } + // loading object var opnd + ob_opnd = _opndManager.createSsaTmpOpnd(ob_var_opnd->getType()); + Inst* ldobj=_instFactory.makeLdVar(ob_opnd,ob_var_opnd); + 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 ); + } + } + // adding newobj inst + SsaTmpOpnd* nob_opnd = _opndManager.createSsaTmpOpnd(ob_var_opnd->getType()); + Inst* newobj=_instFactory.makeNewObj(nob_opnd,ob_var_opnd->getType()); + newobj->insertBefore(ldobj); + if (isBCmapRequired) { + setNewBCMap(newobj,old_newobj); + } + // storing created newobj result in object var opnd + Inst* stvobj=_instFactory.makeStVar(ob_var_opnd,nob_opnd); + stvobj->insertBefore(ldobj); + // resetting ob_flag_var_opnd to 1 (object created) + Inst* stvflag=_instFactory.makeStVar(ob_flag_var_opnd, i32_1); + stvflag->insertBefore(ldobj); + // node with call inst after opt + node_var=fg.splitNodeAtInstruction(stvflag,splitAfter,false,_instFactory.makeLabel()); + // checkinf flag: if object created goto node_var node + SsaTmpOpnd* ob_flag_opnd = _opndManager.createSsaTmpOpnd(ob_flag_var_opnd->getType()); + _instFactory.makeLdVar(ob_flag_opnd,ob_flag_var_opnd)->insertBefore(newobj); + Inst* branch_inst = _instFactory.makeBranch(Cmp_EQ, Type::Int32, + ob_flag_opnd, i32_1, (LabelInst*)(node_var->getFirstInst())); + branch_inst->insertBefore(newobj); + // node with newobj instruction after opt + node_obj=fg.splitNodeAtInstruction(branch_inst,splitAfter,false,_instFactory.makeLabel()); + fg.addEdge(node_before, node_var); + // created oject field initialization + ScObjFld* sco = NULL; + if (scObjFlds->size() > 0) { + Opnd* st_tau_op = _opndManager.createSsaTmpOpnd(_typeManager.getTauType()); + _instFactory.makeTauUnsafe(st_tau_op)->insertBefore(stvobj); + for (ito = scObjFlds->begin( ); ito != scObjFlds->end( ); ito++ ){ + sco = (*ito); + if (sco->ls_insts->size()==0) { + continue; + } + Type* fl_type = NULL; + Inst* ii = sco->ls_insts->front(); + Inst* iadr = NULL; + if (ii->getOpcode()==Op_TauStInd) { + iadr=ii->getSrc(1)->getInst(); + fl_type = ii->getSrc(1)->getType()->asPtrType()->getPointedToType(); + } else { + iadr=ii->getSrc(0)->getInst(); + fl_type = ii->getSrc(0)->getType()->asPtrType()->getPointedToType(); + } + assert(iadr->getOpcode()==Op_LdFieldAddr); // only esc.objects may be optimized + Type* type = sco->fldVarOpnd->getType(); + bool compress = (fl_type->isCompressedReference() && + !type->isCompressedReference()); + Modifier compressMod = Modifier(compress ? AutoCompress_Yes + : AutoCompress_No); + Modifier mod = Modifier(Store_NoWriteBarrier)|compressMod; + + SsaTmpOpnd* fl_tmp_opnd_st = _opndManager.createSsaTmpOpnd(fl_type); + _instFactory.makeLdVar(fl_tmp_opnd_st, sco->fldVarOpnd)->insertBefore(stvobj); + Opnd* dst = _opndManager.createSsaTmpOpnd(iadr->getDst()->getType()); + FieldDesc* fd = iadr->asFieldAccessInst()->getFieldDesc(); + _instFactory.makeLdFieldAddr(dst,nob_opnd,fd)->insertBefore(stvobj); + Inst* nstind=_instFactory.makeTauStInd(mod,type->tag, + fl_tmp_opnd_st,dst,st_tau_op,st_tau_op,st_tau_op); + nstind->insertBefore(stvobj); + if (sco->isFinalFld) { + continue; + } + // updating non-final fields after call + if (node_after1 == NULL) { + ld_tau_op = _opndManager.createSsaTmpOpnd(_typeManager.getTauType()); + Inst* itau = _instFactory.makeTauUnsafe(ld_tau_op); + node_after1=fg.createBlockNode(_instFactory.makeLabel()); + node_after1->appendInst(itau); + } + // loading field address + Opnd* dst_ld = _opndManager.createSsaTmpOpnd(iadr->getDst()->getType()); + Inst* lda = _instFactory.makeLdFieldAddr(dst_ld,ob_opnd,fd); + node_after1->appendInst(lda); + // loading field value + SsaTmpOpnd* fl_tmp_opnd_ld = _opndManager.createSsaTmpOpnd(fl_type); + Inst* ldf = _instFactory.makeTauLdInd(mod,type->tag,fl_tmp_opnd_ld,dst_ld, + ld_tau_op,ld_tau_op); + node_after1->appendInst(ldf); + // storing field value in field var opnd + Inst* stv = _instFactory.makeStVar(sco->fldVarOpnd,fl_tmp_opnd_ld); + node_after1->appendInst(stv); + } + if (tnode!=NULL) { + node_obj1=fg.splitNodeAtInstruction(newobj,splitAfter,false, + _instFactory.makeLabel()); + fg.addEdge(node_obj,tnode); + } + if (node_after1 != NULL) { + if (_scinfo) { + os_sc << "!!!! to restore not final fields " << std::endl; + } + // next node after node with call inst + Node* node_after = node_var->getUnconditionalEdgeTarget(); + // inserting node with updating field var opnds + fg.removeEdge(node_var->getUnconditionalEdge()); + fg.addEdge(node_var,node_after1); + fg.addEdge(node_after1,node_after); + } + if (_scinfo) { + os_sc << "++++ objectCreate: after" << std::endl; + FlowGraph::print(os_sc,node_before); + FlowGraph::print(os_sc,node_obj); + if (node_obj1 != NULL) { + FlowGraph::print(os_sc,node_obj1); + } + FlowGraph::print(os_sc,node_var); + if (node_after1 != NULL) { + FlowGraph::print(os_sc,node_after1); + } + os_sc << "++++ objectCreate: after end" << std::endl; + } + } + } +} // restoreEOCreation(Insts* vc_insts, ScObjFlds* objs, VarOpnd* ob_var_opnd,...) + + +void +EscAnalyzer::removeInst(Inst* reminst) { + ControlFlowGraph& fg = irManager.getFlowGraph(); + Edge* excedge = NULL; + + if (reminst->getNode()!=NULL) { + if (_scinfo) { + os_sc <<"--rmInst done: CFGnode " << reminst->getNode()->getId() <<" "; + ((Inst*)(reminst->getNode()->getLabelInst()))->print(os_sc); os_sc << " "; + reminst->print(os_sc); + os_sc << std::endl; + } + if (reminst->getOperation().canThrow()==true) { + excedge = (Edge*)reminst->getNode()->getExceptionEdge(); + assert(excedge != NULL); + if (_scinfo) { + os_sc <<"--rmEdge done: to "; ((Inst*)(excedge->getTargetNode()->getLabelInst()))->print(os_sc); + os_sc << std::endl; + } + fg.removeEdge(excedge); + } + reminst->unlink(); + return; + } + if (_scinfo) { + os_sc <<"--rmInst null: CFGnode NULL "; + reminst->print(os_sc); + os_sc << std::endl; + } +} // removeInst(Inst* reminst) + + +MethodDesc* +EscAnalyzer::getMD(Inst* inst) { + MethodDesc* md; + if (inst->getOpcode()==Op_DirectCall) + return inst->asMethodCallInst()->getMethodDesc(); + if (inst->getOpcode()!=Op_IndirectMemoryCall) + return NULL; + if (inst->getSrc(0)->getInst()->getOpcode()== Op_LdVar) { + md = inst->getSrc(0)->getType()->asMethodPtrType()->getMethodDesc(); + } else { + md = inst->getSrc(0)->getInst()->asMethodInst()->getMethodDesc(); + } + return md; +} + + +void +EscAnalyzer::fixMethodEndInsts(uint32 ob_id) { + Insts::iterator itmei; + InstFactory& _instFactory = irManager.getInstFactory(); + OpndManager& _opndManager = irManager.getOpndManager(); + for (itmei = methodEndInsts->begin( ); itmei != methodEndInsts->end( ); itmei++ ) { + Inst* mei = *itmei; + uint32 i = 0; + uint32 nsrc = mei->getNumSrcOperands(); + + if (nsrc == 0) + continue; + Opnd* o = mei->getSrc(i); + if (o->getId() != ob_id) + continue; + + if (_scinfo) { + os_sc << "++++ Op_MethodEnd " << std::endl; + mei->print(os_sc); os_sc << std::endl; + os_sc << " -- replaced by " << std::endl; + } + + SsaTmpOpnd* null_opnd = _opndManager.createSsaTmpOpnd(o->getType()); + _instFactory.makeLdNull(null_opnd)->insertBefore(mei); + mei->setSrc(i,null_opnd); + + if (_scinfo) { + mei->getPrevInst()->print(os_sc); os_sc << std::endl; + mei->print(os_sc); os_sc << std::endl; + os_sc << "++++ " << std::endl; + } + } +} // fixMethodEndInsts(uint32 ob_id) + + +EscAnalyzer::CnGNode* +EscAnalyzer::getLObj(CnGNode* vval) { + CnGNode* n = vval; + while (n->nodeType != NT_LDOBJ) { + if (n->nodeType!=NT_VARVAL) + return NULL; + if (n->outEdges == NULL) + return NULL; + if ((n->outEdges)->size()!=1) + return NULL; + n=(n->outEdges)->front()->cngNodeTo; + } + return n; +} //getLObj(CnGNode* vval) + + +bool +EscAnalyzer::checkVVarSrcs(Inst* inst) { + Inst* inst1; + uint32 nsrc=inst->getNumSrcOperands(); + std::string text = " checkVVS "; + bool res = true; + + if (scannedObjs->size()!=0) { + if (checkScannedObjs(inst->getId())) { +#ifdef _DEBUG + if (_scinfo) { + os_sc << "instId " << inst->getId() + << " . . . returns false" << std::endl; + } +#endif + return false; + } + } +#ifdef _DEBUG + if (_scinfo) { + os_sc << text; + inst->print(os_sc); + os_sc << 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) { + os_sc<< text << " "; + printCnGNode(n,os_sc); + os_sc<< 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) { + os_sc << text << " "; + printCnGNode(n,os_sc); + os_sc << std::endl; + } + break; + } + default: + break; + } + } +#endif + + if (inst->getOpcode()==Op_DirectCall || inst->getOpcode()==Op_IndirectMemoryCall) { +#ifdef _DEBUG + if (_scinfo) { + os_sc << " 6 returns false " << std::endl; + } +#endif + return false; + } + if (nsrc == 0) { + if (inst->getOpcode() == Op_LdStaticAddr) { + FieldDesc* fd = inst->asFieldAccessInst()->getFieldDesc(); + const char* ptn = fd->getParentType()->getName(); + if (checkObjectType(ptn) && strcmp(fd->getName(),"CACHE")==0 ) { +#ifdef _DEBUG + if (_scinfo) { + os_sc << " 5 returns true " << std::endl; + } +#endif + return true; + } else { +#ifdef _DEBUG + if (_scinfo) { + os_sc << " 4 returns false " << std::endl; + } +#endif + return false; + } + } + if (inst->getOpcode() == Op_NewObj || inst->getOpcode() == Op_NewArray + || inst->getOpcode() == Op_NewMultiArray) { +#ifdef _DEBUG + if (_scinfo) { + os_sc << " 3 returns true " << std::endl; + } +#endif + return true; + } + if (inst->getOpcode() == Op_LdRef || inst->getOpcode() == Op_DefArg ) { +#ifdef _DEBUG + if (_scinfo) { + os_sc << " 2 returns false " << std::endl; + } +#endif + return false; + } + } + scannedObjs->push_back(inst->getId()); + switch (inst->getOpcode()) { + case Op_TauLdInd: // ldind + case Op_AddScaledIndex: // addindex + inst1 = inst->getSrc(0)->getInst(); + res = checkVVarSrcs(inst1); + break; + case Op_TauStInd: // stind + for (uint32 i=0; i<2; i++) { + inst1 = inst->getSrc(i)->getInst(); + res = checkVVarSrcs(inst1); + } + break; + default: + for (uint32 i=0; igetSrc(i)->getInst(); + bool res1 = checkVVarSrcs(inst1); + res = res && res1; + } + } + scannedObjs->pop_back(); +#ifdef _DEBUG + if (_scinfo) { + os_sc << " 1 returns " << res << std::endl; + } +#endif + return res; +} // checkVVarSrcs(Inst* inst) + + +bool +EscAnalyzer::checkObjectType(const char* otn) { + if ((strcmp(otn,"java/lang/Integer") == 0) || (strcmp(otn,"java/lang/Short") == 0) + || (strcmp(otn,"java/lang/Long") == 0) || (strcmp(otn,"java/lang/Character") == 0) + || (strcmp(otn,"java/lang/Integer$valueOfCache") == 0) + || (strcmp(otn,"java/lang/Short$valueOfCache") == 0) + || (strcmp(otn,"java/lang/Long$valueOfCache") == 0) + || (strcmp(otn,"java/lang/Character$valueOfCache") == 0) ) { + return true; + } + return false; +} + + +bool +EscAnalyzer::checkObjFlds(ScObjFlds* nscObjFlds, ScObjFlds* lscObjFlds) { + ScObjFlds::iterator it1; + ScObjFlds::iterator it2; + + if (nscObjFlds->size() == 0) { + return true; + } + if (lscObjFlds->size() == 0) { + return false; + } + for (it1=lscObjFlds->begin(); it1!=lscObjFlds->end(); it1++) { + for (it2=nscObjFlds->begin(); it2!=nscObjFlds->end(); it2++) { + if ((*it1)->fd == (*it2)->fd) { + break; + } + return false; + } + } + return true; +} // checkObjFlds(ScObjFlds* nscObjFlds, ScObjFlds* scObjFlds) + + +void +EscAnalyzer::fixCheckInsts(uint32 opId) { + Insts::iterator iit; + Edge* excedge; + + if (checkInsts == NULL) { + return; + } + os_sc << " checkInsts " << checkInsts->size() << std::endl; + for (iit=checkInsts->begin(); iit!=checkInsts->end(); iit++) { + if ((*iit)->getSrc(0)->getId()!=opId) { + continue; + } + if (_scinfo) { + os_sc << " ** "; (*iit)->print(os_sc); os_sc << std::endl; + } + Inst* inst = (*iit); + uint32 opcode = inst->getOpcode(); + if (opcode == Op_TauCheckNull) { + removeInst(inst); + } + if (opcode == Op_Branch) { + excedge = NULL; + if (inst->getComparisonModifier()==Cmp_Zero) { + excedge = inst->getNode()->getTrueEdge(); + } + if (inst->getComparisonModifier()==Cmp_NonZero) { + excedge = inst->getNode()->getFalseEdge(); + } + if (_scinfo) { + os_sc <<"-- to remove edge: to "; + ((Inst*)( excedge->getTargetNode()->getLabelInst() ))->print(os_sc); + os_sc << std::endl; + } + if (excedge != NULL) { + irManager.getFlowGraph().removeEdge(excedge); + removeInst(inst); + } + } + if (opcode == Op_TauIsNonNull) { + 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); + } + 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) + + +void +EscAnalyzer::checkToScalarizeFinalFiels(CnGNode* onode, ScObjFlds* scObjFlds) { + ScObjFlds::iterator ito; + ScObjFld* sco = NULL; + bool do_fsc = false; + OpndManager& _opndManager = irManager.getOpndManager(); + InstFactory& _instFactory = irManager.getInstFactory(); + TypeManager& _typeManager = irManager.getTypeManager(); + + if (_scinfo) { + os_sc << "########################" << std::endl; + printCnGNode(onode,os_sc); os_sc << std::endl; + checkOpndUsage(onode->opndId); + // to collect stind & ldind instructions + scObjFlds->clear(); + collectStLdInsts(onode, scObjFlds); + if (scObjFlds->size() != 0) { + os_sc << " used fields: " << scObjFlds->size() << " final fields exist: "; + for (ito = scObjFlds->begin( ); ito != scObjFlds->end( ); ito++ ){ + sco = (*ito); + os_sc << sco->isFinalFld << " "; + if (sco->isFinalFld) { + do_fsc = true; + } + os_sc << " field usage : " << sco->ls_insts->size(); + } + os_sc << std::endl; + } + if (scObjFlds->size() != 0 && do_fsc) { + printCnGNode(onode,os_sc); os_sc << std::endl; + os_sc << " ############# try to do" << std::endl; + } else { + os_sc << " ############# do_fsc " << do_fsc << std::endl; + } + os_sc << "# #######################" << std::endl; + } + if (onode->nodeType == NT_LDOBJ) { + + for (ito = scObjFlds->begin( ); ito != scObjFlds->end( ); ito++ ){ + sco = (*ito); + if (!sco->isFinalFld || sco->ls_insts->size() < 2) { + continue; + } + Type* fl_type = NULL; + Inst* ii = sco->ls_insts->front(); + Inst* iadr = NULL; + if (ii->getOpcode()==Op_TauStInd) { + iadr=ii->getSrc(1)->getInst(); + fl_type = ii->getSrc(1)->getType()->asPtrType()->getPointedToType(); + } else { + iadr=ii->getSrc(0)->getInst(); + fl_type = ii->getSrc(0)->getType()->asPtrType()->getPointedToType(); + } + VarOpnd* fl_var_opnd = _opndManager.createVarOpnd(fl_type, false); + sco->fldVarOpnd = fl_var_opnd; + scalarizeOFldUsage(sco); + if (_scinfo) { + os_sc << "++++ old newobj added fld_var: before" << std::endl; + FlowGraph::print(os_sc,onode->nInst->getNode()); + os_sc << "++++ old newobj: before end" << std::endl; + } + Modifier mod = ii->getModifier(); + Opnd* ld_tau_op = _opndManager.createSsaTmpOpnd(_typeManager.getTauType()); + Inst* itau = _instFactory.makeTauUnsafe(ld_tau_op); + itau->insertAfter(onode->nInst); + FieldDesc* fd = iadr->asFieldAccessInst()->getFieldDesc(); + Opnd* dst_ld = _opndManager.createSsaTmpOpnd(iadr->getDst()->getType()); + Opnd* ob_opnd = (Opnd*)(onode->refObj); + Inst* lda = _instFactory.makeLdFieldAddr(dst_ld,ob_opnd,fd); + lda->insertAfter(itau); + SsaTmpOpnd* fl_tmp_opnd_ld = _opndManager.createSsaTmpOpnd(fl_type); + Inst* ldf = _instFactory.makeTauLdInd(mod,fl_var_opnd->getType()->tag, + fl_tmp_opnd_ld,dst_ld,ld_tau_op,ld_tau_op); + ldf->insertAfter(lda); + Inst* stv = _instFactory.makeStVar(fl_var_opnd,fl_tmp_opnd_ld); + stv->insertAfter(ldf); + if (_scinfo) { + os_sc << "++++ old newobj added fld_var: after" << std::endl; + FlowGraph::print(os_sc,onode->nInst->getNode()); + os_sc << "++++ old newobj: after end" << std::endl; + } + } + } +} // checkToScalarizeFinalFiels(CnGNode* onode, ScObjFlds* scObjFlds) + + +/** + * 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 + */ +void +EscAnalyzer::setNewBCMap(Inst* new_i, Inst* old_i) { + if (isBCmapRequired) { + uint64 bcOffset = ILLEGAL_VALUE; + uint64 instID = old_i->getId(); + bcOffset = bc2HIRMapHandler->getVectorEntry(instID); + if (bcOffset != ILLEGAL_VALUE) { + bc2HIRMapHandler->setVectorEntry(new_i->getId(), bcOffset); + } + } +} // setNewBCMap(Inst* new_i, Inst* old_i) + + +/** + * Removes bcmap offset in bc2HIRMapHandler. + * @param inst - instruction to remove offset + */ +void +EscAnalyzer::remBCMap(Inst* inst) { + if (isBCmapRequired) { + uint64 bcOffset = ILLEGAL_VALUE; + uint64 instID = inst->getId(); + bcOffset = bc2HIRMapHandler->getVectorEntry(instID); + if (bcOffset != ILLEGAL_VALUE) { + bc2HIRMapHandler->setVectorEntry(instID, ILLEGAL_VALUE); + } + } +} // remBCMap(Inst* inst) + + + } //namespace Jitrino Index: vm/jitrino/src/optimizer/escanalyzer.h =================================================================== --- vm/jitrino/src/optimizer/escanalyzer.h (revision 517749) +++ vm/jitrino/src/optimizer/escanalyzer.h (working copy) @@ -59,8 +59,10 @@ static const uint32 NT_ACTARG = 128; // Op_DirectCall,Op_IndirectMemoryCall static const uint32 NT_EXITVAL = 256; // returned value - Op_Return static const uint32 NT_THRVAL = NT_EXITVAL+1; // thrown value - Op_Throw - static const uint32 NT_OBJS = NT_OBJECT|NT_RETVAL|NT_LDOBJ; //for findCnGNode_op + static const uint32 NT_LDVAL = 512; // Op_TauLdInd, Op_TauStInd + static const uint32 NT_OBJS = NT_OBJECT|NT_RETVAL|NT_LDOBJ; //for findCnGNode_op // CnG node reference types + static const uint32 NR_PRIM = 0; static const uint32 NR_REF = 1; static const uint32 NR_ARR = 2; static const uint32 NR_REFARR = 3; @@ -153,9 +155,16 @@ uint32 allProps; const char* debug_method; + bool do_sync_removal; + 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; private: - static const int maxMethodExamLevel_default = 5; + static const int maxMethodExamLevel_default = 0; struct CnGEdge { CnGNode* cngNodeFrom; @@ -187,6 +196,7 @@ int defArgNumber; uint32 method_ea_level; ObjIds *scannedObjs; + ObjIds *scannedObjsRev; ObjIds *scannedInsts; ObjIds *scannedSucNodes; uint32 initNodeType; // type of initial scanned node @@ -194,8 +204,21 @@ SsaTmpOpnd* i32_0; SsaTmpOpnd* i32_1; TranslatorAction* translatorAction; + Insts* methodEndInsts; + Insts* checkInsts; + std::ostream& os_sc; + bool print_scinfo; + 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()<<"--------------------"<begin( ); it != ids->end( ); it++ ) { + if ((*it)==id) { + return true; + } + } + return false; + } + bool checkScannedObjs(uint32 id) {return checkScanned(scannedObjs, id);} + bool checkScannedObjsRev(uint32 id) {return checkScanned(scannedObjsRev, id);} + bool checkScannedInsts(uint32 id) {return checkScanned(scannedInsts, id);} + bool checkScannedSucNodes(uint32 id) {return checkScanned(scannedSucNodes, id);} + uint32 getEscState(CnGNode* n) { return (n->state)&ESC_MASK; } @@ -331,6 +372,201 @@ } void runTranslatorSession(CompilationContext& inlineCC); + + // Scalar replacement optimization +/** + * Performs scalar replacement optimization for local objects + * (class instances and arrays). + */ + void scanLocalObjects(); + +/** + * Performs scalar replacement optimization for method escaped class instances. + */ + void scanEscapedObjects(); + +/** + * Performs scalar replacement optimization for local objects from the specified list. + * @param loids - list of local objects CnG nodes Ids + * @param os - output stream + */ + 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 + */ + 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 + */ + 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 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 + */ + 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 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 an object can be removed and its fields/elements scalarized. + * @param lobjid - object CnG nodes Ids + * @return true if an object is used only in ldflda or ldbase instructions; + * false otherwise. + */ + bool checkOpndUsage(uint32 lobjid); + +/** + * 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, + * 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); + +/** + * 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 nob_inst - object creation instruction. + * @return execCount of this path execution; + * 0 otherwise. + */ + double checkLocalPath(Inst* nob_inst); + +/** + * 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 + * @return execCount the most value of execCount and + * checkNextNodes execution for next after n node; + */ + double checkNextNodes(Node* n, uint32 obId, double cExecCount, std::string text=""); + +/** + * 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 + */ + void restoreEOCreation(Insts* vc_insts, ScObjFlds* objs, VarOpnd* ob_var_opnd, + VarOpnd* ob_flag_var_opnd, Node* tnode, uint32 oid); + +/** + * Removes specified instruction from ControlFlowGraph. + * If instruction can throw exception removes corresponding CFGEdge. + * @param reminst - removed instruction + */ + void removeInst(Inst* reminst); + +/** + * Returns MethodDesc* for Op_IndirectMemoryCall and Op_DirectCall instructions. + * @param inst - call instruction. + * @return MethodDesc for Op_IndirectMemoryCall and Op_DirectCall; + * NULL otherwise. + */ + MethodDesc* getMD(Inst* inst); + +/** + * Replaces first source operand of Op_MethodEnd instruction by NULL + * for scalar replacement optimized object. + * @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 + * @return CnGNode* - found optimized load varOpnd CnG node + * NULL otherwise. + */ + CnGNode* getLObj(CnGNode* vval); + +/** + * Checks that all sources of optimized load varOpnd aren't null and + * satisfy to specified conditions. + * @param inst - ldvar instruction created optimized load varOpnd. + * @return true if satisfied; + * false otherwise. + */ + bool checkVVarSrcs(Inst* inst); + +/** + * Checks that optimized object type satisfied to specified types. + * @param otn - object type name. + * @return true if satisfied; + * false otherwise. + */ + bool checkObjectType(const char* otn); + +/** + * 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 + * @return true if list of new object used field contains all + * load varOpnd used field; + * false otherwise. + */ + bool checkObjFlds(ScObjFlds* nscObjFlds, ScObjFlds* lscObjFlds); + +/** + * Removes check instructions for optimized load varOpnd. + * @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 + */ + void checkToScalarizeFinalFiels(CnGNode* onode, ScObjFlds* scObjFlds); + + + // BCMap support +/** + * 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 + */ + void setNewBCMap(Inst* new_i, Inst* old_i); + +/** + * Removes bcmap offset in bc2HIRMapHandler. + * @param inst - instruction to remove offset + */ + void remBCMap(Inst* inst); + + int _cfgirun; int _instrInfo; int _instrInfo2; @@ -341,8 +577,14 @@ 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