| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /** |
| * @author Intel, Natalya V. Golovleva |
| * |
| */ |
| |
| #include "escanalyzer.h" |
| #include "FlowGraph.h" |
| #include "Inst.h" |
| #include "Stl.h" |
| #include "BitSet.h" |
| #include "Dominator.h" |
| #include "Loop.h" |
| #include "Log.h" |
| #include "Type.h" |
| #include "ssa/SSA.h" |
| #include "optpass.h" |
| #include "devirtualizer.h" |
| #include "VMInterface.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 synchronization removal optimization\n" |
| " escape.do_sync_removal_vc[={ON,off}] - do synchronization removal optimization\n" |
| " for virtual call escaped operands\n" |
| " escape.do_sync_removal_sm[={ON,off}] - do synchronization removal optimization\n" |
| " for synchronized methods\n" |
| " escape.do_scalar_repl[={ON,off}] - do scalar replacement optimization for\n" |
| " local and escaped objects\n" |
| " escape.do_esc_scalar_repl[={ON,off}] - scalar replacement for escaped objects\n" |
| " escape.do_scalar_repl_only_final_fields_in_use[={on,OFF}] \n" |
| " escape.do_scalar_repl_final_fields[={on,OFF}] \n" |
| " - 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) {}; |
| U_32 _n0; |
| U_32 _n_ge; |
| U_32 _n_ae; |
| U_32 _n_ne; |
| U_32 _n_lo; |
| }; |
| static ComObjStat comObjStat; |
| EscAnalyzer::CalleeMethodInfos* EscAnalyzer::calleeMethodInfos=NULL; |
| Mutex EscAnalyzer::calleeMethodInfosLock; |
| |
| static void logMethod(MethodPtrType* mpt); |
| static void logMethod(MethodDesc* md); |
| static bool isVMHelperCall(Inst* inst, VM_RT_SUPPORT id); |
| |
| void |
| EscapeAnalysisPass::_run(IRManager& irm) { |
| |
| MemoryManager escMemManager("EscapeAnalyzer:tmp_mm"); |
| EscAnalyzer ea(escMemManager, this, irm); |
| |
| if (Log::isEnabled() && (ea.allProps!=0)) { |
| Log::out() << "E s c a p e A n a l y s i s " << std::endl; |
| } |
| |
| ea.doAnalysis(); |
| |
| irm.getFlowGraph().purgeUnreachableNodes(); //needed to get valid log after this pass |
| |
| } // run(IRManager& irm) |
| |
| |
| EscAnalyzer::EscAnalyzer(MemoryManager& mm, SessionAction* argSource, IRManager& irm) |
| : eaMemManager(mm), irManager(irm), mh(irm.getMethodDesc()), |
| compInterface(irm.getCompilationInterface()),os_sc(Log::out()) |
| { |
| maxMethodExamLevel = (U_32)argSource->getIntArg("max_level",maxMethodExamLevel_default); |
| allProps = (U_32)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",true); |
| do_sync_removal_vc = argSource->getBoolArg("do_sync_removal_vc",true); |
| do_sync_removal_sm = argSource->getBoolArg("do_sync_removal_sm",true); |
| do_scalar_repl = argSource->getBoolArg("do_scalar_repl",true); |
| do_esc_scalar_repl = argSource->getBoolArg("do_esc_scalar_repl",true); |
| execCountMultiplier_string = argSource->getStringArg("exec_count_mult", NULL); |
| ec_mult = ( execCountMultiplier_string==NULL ? 0 : atof(execCountMultiplier_string) ); |
| do_scalar_repl_only_final_fields_in_use = argSource->getBoolArg("do_scalar_repl_only_final_fields_in_use",false); |
| do_scalar_repl_final_fields = argSource->getBoolArg("do_scalar_repl_final_fields",false); |
| compressedReferencesArg = argSource->getBoolArg("compressedReferences", false); |
| |
| const char* translatorName = argSource->getStringArg("translatorActionName", "translator"); |
| translatorAction = (TranslatorAction*)PMF::getAction(argSource->getPipeline(), translatorName); |
| assert(translatorAction); |
| |
| shortLog = argSource->log(LogStream::CT).isEnabled(); |
| verboseLog = shortLog && argSource->isLogEnabled("escape_verbose"); |
| |
| init(); |
| } |
| |
| EscAnalyzer::EscAnalyzer(EscAnalyzer* parent, IRManager& irm) |
| : eaMemManager(parent->eaMemManager), irManager(irm), mh(irm.getMethodDesc()), |
| compInterface(irm.getCompilationInterface()), os_sc(Log::out()) |
| { |
| maxMethodExamLevel = parent->maxMethodExamLevel; |
| allProps = parent->allProps; |
| debug_method = parent->debug_method; |
| translatorAction = parent->translatorAction; |
| method_ea_level = parent->method_ea_level + 1; |
| shortLog = parent->shortLog; |
| verboseLog = parent->verboseLog; |
| |
| init(); |
| } |
| |
| void EscAnalyzer::init() { |
| i32_0 = NULL; |
| i32_1 = NULL; |
| |
| 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); |
| exam2Insts = new (eaMemManager) Insts(eaMemManager); |
| methodEndInsts = new (eaMemManager) Insts(eaMemManager); |
| checkInsts = new (eaMemManager) Insts(eaMemManager); |
| } |
| |
| void |
| EscAnalyzer::showFlags(std::ostream& os) { |
| os << " escape flags:"<<std::endl; |
| os << " escape.max_level[=0] - max level callee method analysis" << std::endl; |
| os << " escape.do_sync_removal[={ON,off}] - do synchronization removal optimization" << std::endl; |
| os << " escape.do_sync_removal_vc[={ON,off}] - do synchronization removal optimization" << std::endl; |
| os << " for virtual call escaped operands" << std::endl; |
| os << " escape.do_sync_removal_sm[={ON,off}] - do synchronization removal optimization" << std::endl; |
| os << " for synchronized methods" << std::endl; |
| os << " escape.do_scalar_repl[={ON,off}] - do scalar replacement optimization for" << std::endl; |
| os << " local and escaped objects" << std::endl; |
| os << " escape.do_esc_scalar_repl[={ON,off}] - scalar replacement for escaped objects" << std::endl; |
| os << " escape.do_scalar_repl_only_final_fields_in_use[={on,OFF}] " << std::endl; |
| os << " escape.do_scalar_repl_final_fields[={on,OFF}] " << std::endl; |
| os << " - scalarize final field usage when" << std::endl; |
| os << " escaped object wasn't optimized" << std::endl; |
| os << " escape.exec_count_mult[=0] - entry node execCount multiplier" << std::endl; |
| } |
| |
| void |
| EscAnalyzer::doAnalysis() { |
| const char* mn = mh.getName(); |
| const Nodes& nodes = irManager.getFlowGraph().getNodes(); |
| ControlFlowGraph& fg = irManager.getFlowGraph(); |
| U_32 nodeNum = (U_32)nodes.size(); |
| U_32 num2 = fg.getNodeCount(); |
| U_32 num3 = fg.getMaxNodeId(); |
| Nodes::const_iterator niter; |
| |
| lastCnGNodeId = 0; // initialization of private field |
| defArgNumber = -1; // initialization of private field |
| |
| |
| if (verboseLog) { |
| Log::out()<<"====== doAnalysis ====== "<<mn<<" level: "; |
| Log::out()<<method_ea_level<<" "; |
| if (mh.isSynchronized()) |
| Log::out()<<"sync "; |
| if (mh.isStatic()) |
| Log::out()<<"stat "; |
| Log::out()<<nodeNum<<" "<<num2<<" "<<num3<< " "; |
| mh.printFullName(Log::out()); |
| Log::out()<< std::endl; |
| } |
| int maxInd = 0; |
| int cur = -1; |
| Node* node; |
| cngNodes=new (eaMemManager) CnGNodes(eaMemManager); // Common part of connection graph (nodes) |
| |
| for(niter = nodes.begin(); niter != nodes.end(); ++niter) { |
| node = *niter; |
| cur = maxInd++; |
| |
| // exam instructions |
| |
| if (verboseLog) { |
| Log::out() <<std::endl; |
| Log::out() <<"Scan "<< cur <<" Node "; |
| FlowGraph::printLabel(Log::out(),node); |
| Log::out() <<" Id. "<<node->getId() <<std::endl; |
| } |
| |
| |
| instrExam(node); |
| |
| }; |
| |
| if (verboseLog) { |
| Log::out() <<"printCnGNodes: "; |
| mh.printFullName(Log::out()); |
| Log::out() << std::endl; |
| printCnGNodes("First run result: nodes",Log::out()); |
| } |
| |
| cngEdges=new (eaMemManager) CnGEdges(eaMemManager); // Common part of connection graph (edges) |
| instrExam2(); |
| |
| if (verboseLog) { |
| Log::out() <<"printCnGEdges: "; |
| mh.printFullName(Log::out()); |
| Log::out() << std::endl; |
| printCnGEdges("resulting OUT CnGEdges",Log::out()); |
| } |
| |
| setCreatedObjectStates(); |
| |
| if (verboseLog) { |
| printCreatedObjectsInfo(Log::out()); |
| } |
| |
| saveScannedMethodInfo(); // to save states of contained obj, if needed |
| |
| if (verboseLog) { |
| Log::out() << "++++++++++++++ printRefInfo() "; |
| mh.printFullName(Log::out()); |
| Log::out() << std::endl; |
| printRefInfo(Log::out()); |
| Log::out() << "++++++++++++++ end "; |
| mh.printFullName(Log::out()); |
| Log::out() << std::endl; |
| } |
| |
| if (verboseLog) { |
| Log::out() <<"printCnGNodes: "; |
| mh.printFullName(Log::out()); |
| Log::out() << std::endl; |
| printCnGNodes("Marked nodes",Log::out()); |
| } |
| |
| if (method_ea_level == 0) { |
| createdObjectInfo(); // prints if verboseLog |
| } |
| |
| if (method_ea_level == 0) { |
| if (do_sync_removal) { |
| scanSyncInsts(); |
| } |
| if (do_scalar_repl) { |
| scanLocalObjects(); |
| eaFixupVars(irManager); |
| if (do_esc_scalar_repl) { |
| scanEscapedObjects(); |
| eaFixupVars(irManager); |
| } |
| } |
| if (verboseLog && Log::isEnabled()) { |
| printCreatedObjectsInfo(Log::out()); |
| } |
| } |
| |
| if (verboseLog) { |
| Log::out()<<"====== doAnalysis ====== "<<mn<<" level: "; |
| Log::out()<<method_ea_level<<" end "; |
| if (mh.isSynchronized()) |
| Log::out()<<"sync "; |
| if (mh.isStatic()) |
| Log::out()<<"stat "; |
| mh.printFullName(Log::out()); |
| Log::out()<< std::endl; |
| } |
| |
| return; |
| } // doAnalysis() |
| |
| void |
| EscAnalyzer::instrExam(Node* node) { |
| TypeManager& typeManager = irManager.getTypeManager(); |
| int insnum = 0; |
| |
| if (shortLog) { |
| Log::out() <<"instrExam: Checking node: "; FlowGraph::printLabel(Log::out(), node); |
| Log::out()<<" dfNum="<<node->getDfNum()<<std::endl; |
| } |
| |
| for (Inst* inst=(Inst*)node->getSecondInst();inst!=NULL;inst=inst->getNextInst()) { |
| insnum++; |
| |
| Type* type = NULL; |
| CnGNode* cgnode = NULL; |
| U_32 ntype=0; |
| MethodPtrType* methType = NULL; |
| U_32 n = 0; |
| bool addinst = false; |
| Inst* method_inst = NULL; |
| if (shortLog) { |
| Log::out() <<"Checking inst:"; debug_inst_info(inst,Log::out()); |
| } |
| |
| switch (inst->getOpcode()) { |
| case Op_NewObj: // newobj |
| case Op_NewArray: // newarray |
| case Op_NewMultiArray: // newmultiarray |
| ntype=NT_OBJECT; // for 3 cases above |
| case Op_LdRef: // ldref |
| case Op_LdConstant: // ldc |
| case Op_GetClassObj: // getclassobj |
| if (ntype==0) |
| ntype=NT_LDOBJ; // loads refs |
| case Op_DefArg: // defarg |
| if (ntype==0) { |
| ntype=NT_DEFARG; // for Op_DefArg |
| defArgNumber++; |
| } |
| if (inst->getDst()->getType()->isObject()) { |
| type=inst->getDst()->getType(); |
| assert(findCnGNode_op(inst->getDst()->getId())==NULL); |
| cgnode = addCnGNode_op(inst,type,ntype); |
| } |
| break; |
| |
| case Op_Conv: // conv |
| case Op_ConvUnmanaged: |
| if (inst->getDst()->getType()->isObject()) { |
| type=inst->getDst()->getType(); |
| assert(findCnGNode_op(inst->getDst()->getId())==NULL); |
| cgnode = addCnGNode_op(inst,type,NT_OBJECT); |
| } |
| break; |
| |
| case Op_AddOffset: // used to get non-static field addr in lazy resolution mode. |
| case Op_LdFieldAddr: // ldflda |
| case Op_LdStaticAddr: // ldsflda |
| instrExam_processLdFieldAddr(inst); |
| break; |
| case Op_TauLdInd: // ldind |
| { |
| Opnd* src = inst->getSrc(0); |
| if(src->getType()->isUnmanagedPtr()) |
| break; // skip load from unmanaged source |
| type = inst->getDst()->getType(); |
| if (type->isReference()) { //isObject()) { |
| assert(findCnGNode_op(inst->getDst()->getId())==NULL); |
| cgnode = addCnGNode_op(inst,type,NT_LDOBJ); |
| exam2Insts->push_back(inst); |
| } |
| if (src->getInst()->getOpcode()==Op_LdStaticAddr) |
| break; |
| if (type->isValue()) { |
| assert(findCnGNode_op(inst->getDst()->getId())==NULL); |
| cgnode = addCnGNode_op(inst,type,NT_LDVAL); |
| exam2Insts->push_back(inst); |
| } |
| } |
| break; |
| |
| case Op_LdArrayBaseAddr: // ldbase |
| case Op_AddScaledIndex: // addindex |
| if (inst->getDst()->getType()->isReference()) { |
| type=inst->getDst()->getType(); |
| assert(findCnGNode_op(inst->getDst()->getId())==NULL); |
| cgnode = addCnGNode_op(inst,type,NT_ARRELEM); |
| exam2Insts->push_back(inst); |
| } |
| break; |
| |
| case Op_VMHelperCall: // callvmhelper |
| { |
| VM_RT_SUPPORT callId = inst->asVMHelperCallInst()->getVMHelperId(); |
| switch(callId) { |
| case VM_RT_GET_STATIC_FIELD_ADDR_WITHRESOLVE: |
| instrExam_processLdFieldAddr(inst); |
| break; |
| case VM_RT_CHECKCAST_WITHRESOLVE: |
| assert(findCnGNode_op(inst->getDst()->getId())==NULL); |
| addCnGNode_op(inst,inst->getDst()->getType(), NT_REF); |
| exam2Insts->push_back(inst); |
| break; |
| case VM_RT_NEWOBJ_WITHRESOLVE: |
| case VM_RT_NEWARRAY_WITHRESOLVE: |
| case VM_RT_MULTIANEWARRAY_RESOLVED: |
| assert(findCnGNode_op(inst->getDst()->getId())==NULL); |
| addCnGNode_op(inst,inst->getDst()->getType(), NT_OBJECT); |
| break; |
| default: |
| break; |
| } |
| } |
| break; |
| case Op_JitHelperCall: // calljithelper |
| if (method_ea_level == 0) { |
| switch(inst->asJitHelperCallInst()->getJitHelperId()) { |
| case Prefetch: |
| case Memset0: |
| case InitializeArray: |
| case FillArrayWithConst: |
| case SaveThisState: |
| case ReadThisState: |
| case LockedCompareAndExchange: |
| case AddValueProfileValue: |
| case ArrayCopyDirect: |
| case ArrayCopyReverse: |
| case StringCompareTo: |
| case StringIndexOf: |
| case StringRegionMatches: |
| case ClassIsArray: |
| case ClassGetAllocationHandle: |
| case ClassGetTypeSize: |
| case ClassGetArrayElemSize: |
| case ClassIsInterface: |
| case ClassIsFinal: |
| case ClassGetArrayClass: |
| case ClassIsFinalizable: |
| case ClassGetFastCheckDepth: |
| break; |
| default: |
| assert(0); |
| } |
| } |
| break; |
| |
| case Op_TauStInd: // stind |
| { |
| type=inst->getSrc(0)->getType(); |
| if (type->isObject() || type->isValue()) { |
| exam2Insts->push_back(inst); |
| } |
| } |
| break; |
| |
| case Op_DirectCall: // call |
| if (!inst->getDst()->isNull()) { |
| if (inst->getDst()->getType()->isObject()) { |
| type=inst->getDst()->getType(); |
| assert(findCnGNode_op(inst->getDst()->getId())==NULL); |
| cgnode = addCnGNode_op(inst,type,NT_RETVAL); |
| } |
| } |
| methType = typeManager.getMethodPtrType(inst->asMethodInst()->getMethodDesc()); |
| assert(methType!=NULL); |
| n=methType->getNumParams(); |
| addinst=false; |
| for (U_32 i = 0; i < n; i++) { |
| Type* tt = methType->getParamType(i); |
| if (!tt->isReference()) { |
| continue; |
| } |
| addinst=true; |
| assert(findCnGNode_mp(inst->getId(),i)==NULL); |
| cgnode = addCnGNode_mp(inst, methType, NT_ACTARG, i); |
| } |
| if (addinst) { |
| exam2Insts->push_back(inst); |
| } |
| if (verboseLog) { |
| if (method_ea_level == 0) { |
| Log::out() <<"iE: call "; |
| logMethod(methType); |
| } |
| } |
| break; |
| |
| case Op_IndirectMemoryCall: //callimem |
| if (!inst->getDst()->isNull()) { |
| if (inst->getDst()->getType()->isObject()) { |
| type=inst->getDst()->getType(); |
| assert(findCnGNode_op(inst->getDst()->getId())==NULL); |
| cgnode = addCnGNode_op(inst,type,NT_RETVAL); |
| } |
| } |
| method_inst=inst->getSrc(0)->getInst(); |
| if (method_inst->getOpcode() == Op_LdVar) { |
| methType = inst->getSrc(0)->getType()->asMethodPtrType(); |
| } else if (method_inst->asMethodInst()!=NULL) { |
| methType = typeManager.getMethodPtrType(method_inst->asMethodInst()->getMethodDesc()); |
| } else { |
| assert(method_inst->isVMHelperCallInst()); //lazy resolution helper |
| methType = inst->getSrc(0)->getType()->asMethodPtrType(); |
| } |
| assert(methType!=NULL); |
| |
| n=methType->getNumParams(); |
| addinst=false; |
| for (U_32 i = 0; i < n; i++) { |
| Type* tt = methType->getParamType(i); |
| if (!tt->isReference()) { |
| continue; |
| } |
| addinst=true; |
| assert(findCnGNode_mp(inst->getId(),i)==NULL); |
| cgnode = addCnGNode_mp(inst, methType, NT_ACTARG, i); |
| } |
| if (addinst) { |
| exam2Insts->push_back(inst); |
| } |
| |
| if (verboseLog) { |
| if (method_ea_level == 0) { |
| logMethod(methType); |
| } |
| } |
| break; |
| |
| case Op_Catch: // catch |
| type = inst->getDst()->getType(); |
| if (type->isObject()) { |
| assert(!type->isUnresolvedType()); |
| assert(findCnGNode_op(inst->getDst()->getId())==NULL); |
| cgnode = addCnGNode_op(inst,type,NT_CATCHVAL); |
| } |
| break; |
| |
| case Op_StVar: // stvar |
| type = inst->getDst()->getType(); |
| if (type->isObject()) { |
| assert(findCnGNode_op(inst->getDst()->getId())==NULL); |
| cgnode = addCnGNode_op(inst,type,NT_VARVAL); |
| exam2Insts->push_back(inst); |
| } |
| break; |
| |
| case Op_Phi: // phi |
| type = inst->getDst()->getType(); |
| if (type->isReference()) { |
| assert(findCnGNode_op(inst->getDst()->getId())==NULL); |
| cgnode = addCnGNode_op(inst,type,NT_VARVAL); |
| exam2Insts->push_back(inst); |
| } |
| break; |
| |
| case Op_LdVar: // ldvar |
| type = inst->getDst()->getType(); |
| if (type->isReference()) { |
| assert(findCnGNode_op(inst->getDst()->getId())==NULL); |
| cgnode = addCnGNode_op(inst,type,NT_LDOBJ); |
| exam2Insts->push_back(inst); |
| } |
| break; |
| |
| case Op_Return: // return |
| ntype=NT_EXITVAL; |
| case Op_Throw: // throw |
| if (ntype==0) |
| ntype=NT_THRVAL; |
| if (inst->getNumSrcOperands()>0) { |
| type = inst->getSrc(0)->getType(); |
| if (type->isObject()) { |
| assert(findCnGNode_in(inst->getId())==NULL); |
| cgnode = addCnGNode_ex(inst,ntype); |
| exam2Insts->push_back(inst); |
| } |
| } |
| break; |
| |
| case Op_TauStaticCast: // staticcast |
| case Op_TauCast: // cast |
| type = inst->getDst()->getType(); |
| if (type->isObject()) { |
| assert(findCnGNode_op(inst->getDst()->getId())==NULL); |
| cgnode = addCnGNode_op(inst,type,NT_REF); |
| exam2Insts->push_back(inst); |
| } |
| break; |
| |
| case Op_SaveRet: // saveret |
| type = inst->getDst()->getType(); |
| if (type->isIntPtr()) { |
| cgnode = findCnGNode_op(inst->getDst()->getId()); |
| if (cgnode == NULL) |
| cgnode = addCnGNode_op(inst,type,NT_INTPTR); |
| } |
| break; |
| |
| case Op_TauMonitorEnter: // monenter |
| case Op_TauMonitorExit: // monexit |
| if (do_sync_removal && method_ea_level == 0) { |
| addMonInst(inst); |
| } |
| break; |
| |
| case Op_TypeMonitorEnter:// tmonenter |
| case Op_TypeMonitorExit: // tmonexit |
| break; |
| |
| case Op_TauVirtualCall: // callvirt |
| case Op_IndirectCall: // calli |
| |
| case Op_TauStRef: |
| case Op_TauStField: |
| case Op_TauStElem: |
| case Op_Prefetch: |
| case Op_TauStStatic: |
| case Op_Copy: |
| break; |
| |
| default: |
| break; |
| } |
| } |
| return; |
| } // instrExam(Node* node) |
| |
| |
| void EscAnalyzer::getLdFieldAddrInfo(Inst* inst, Type*& type, U_32& nType) { |
| type = NULL; |
| nType = 0; |
| if (inst->getOpcode() == Op_LdFieldAddr || inst->getOpcode() == Op_LdStaticAddr) { |
| FieldAccessInst* fainst = inst->asFieldAccessInst(); |
| type = fainst->getFieldDesc()->getFieldType(); |
| nType = inst->getOpcode() == Op_LdFieldAddr ? NT_INSTFLD : NT_STFLD; |
| } else { |
| if (inst->getOpcode() == Op_AddOffset) { |
| nType = NT_INSTFLD; |
| } else { |
| assert(isVMHelperCall(inst, VM_RT_GET_STATIC_FIELD_ADDR_WITHRESOLVE)); |
| nType = NT_STFLD; |
| } |
| assert(inst->getDst()->getType()->isManagedPtr()); |
| type = inst->getDst()->getType()->asPtrType()->getPointedToType(); |
| } |
| assert(type!=NULL && nType!=0); |
| } |
| |
| void EscAnalyzer::instrExam_processLdFieldAddr(Inst* inst) { |
| Type* type = NULL; |
| U_32 nType = 0; |
| getLdFieldAddrInfo(inst, type, nType); |
| if (type->isReference() || nType==NT_INSTFLD) { |
| assert(findCnGNode_op(inst->getDst()->getId())==NULL); |
| CnGNode* cgnode = addCnGNode_op(inst,type,NT_REF); |
| CnGNode* n = findCnGNode_fl(inst,nType); |
| if (n==NULL) { |
| n = addCnGNode_fl(inst,nType); |
| } |
| cgnode->lNode=n; // stick nodes |
| exam2Insts->push_back(inst); |
| } |
| } |
| |
| void |
| EscAnalyzer::instrExam2_processLdFieldAddr(Inst* inst) { |
| Type* type = NULL; |
| U_32 nType = 0; |
| getLdFieldAddrInfo(inst, type, nType); |
| |
| bool isref = type->isReference(); |
| if (isref || nType==NT_INSTFLD) { |
| assert(!isref || findCnGNode_op(inst->getDst()->getId())); |
| if (nType == NT_INSTFLD) { |
| CnGNode* cgnode=findCnGNode_fl(inst,nType); // field node |
| assert(cgnode!=NULL); |
| CnGNode* cgn_src=findCnGNode_op(inst->getSrc(0)->getId()); // instance node |
| assert(cgn_src!=NULL); |
| // adding fld edge for ldflda |
| addEdge(cgn_src,cgnode,ET_FIELD,inst); |
| |
| // special for java/lang/String::value |
| if (inst->asFieldAccessInst()!=NULL) { |
| FieldDesc* fd=inst->asFieldAccessInst()->getFieldDesc(); |
| if (fd->getParentType()->isSystemString()&&strcmp(fd->getName(),"value")==0) { |
| addEdge(cgnode,cgn_src,ET_DEFER,inst); |
| } |
| if (method_ea_level == 0 && cgn_src->nInst->getOpcode()==Op_NewObj) { |
| //fail if instance type is not compatible with |
| //store/load type. Incompatibility can be the result of not cleaned dead code. |
| //see HARMONY-4115 for details. |
| Inst* instantceInst = cgn_src->nInst; |
| ObjectType* instanceType = instantceInst->asTypeInst()->getTypeInfo()->asObjectType(); |
| assert(instanceType!=NULL); |
| ObjectType* fieldObjectType = fd->getParentType()->asObjectType(); |
| assert(fieldObjectType!=NULL); |
| if (!instanceType->isSubClassOf(fieldObjectType)) { |
| if (shortLog) { |
| Log::out()<<"FAILURE: instance type: "<<instanceType->getName(); |
| Log::out()<<" is not compatible with field object type: "<<fieldObjectType->getName()<<std::endl; |
| Log::out()<<"Instance inst: ";instantceInst->print(Log::out()); |
| Log::out()<<" field inst: ";inst->print(Log::out()); Log::out()<<std::endl; |
| } |
| assert(0); |
| Jitrino::crash("Jitrino failure:escape: illegal HIR sequence"); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| void |
| EscAnalyzer::instrExam2() { |
| TypeManager& typeManager = irManager.getTypeManager(); |
| Insts *instrs = exam2Insts; |
| int insnum=0; |
| Inst* inst; |
| Insts::iterator it; |
| |
| for (it = instrs->begin( ); it != instrs->end( ); it++ ) { |
| inst=*it; |
| insnum++; |
| |
| Type* type = NULL; |
| CnGNode* cgnode = NULL; |
| CnGNode* cgn_src = NULL; |
| U_32 ntype=0; |
| MethodPtrType* methType = NULL; |
| U_32 n = 0; |
| Inst* method_inst = NULL; |
| bool not_exam = false; |
| |
| |
| if (shortLog) { |
| Node * node = inst->getNode(); |
| Log::out() <<"instrExam2: node: "; FlowGraph::printLabel(Log::out(), node); |
| Log::out()<<" dfNum="<<node->getDfNum()<<std::endl; |
| Log::out() <<"inst :"; inst->print(Log::out()); Log::out() << std::endl; |
| } |
| |
| switch (inst->getOpcode()) { |
| case Op_AddOffset: |
| case Op_LdFieldAddr: |
| case Op_LdStaticAddr: |
| instrExam2_processLdFieldAddr(inst); |
| break; |
| case Op_VMHelperCall: |
| { |
| VM_RT_SUPPORT helperId = inst->asVMHelperCallInst()->getVMHelperId(); |
| switch(helperId) { |
| case VM_RT_GET_STATIC_FIELD_ADDR_WITHRESOLVE: |
| instrExam2_processLdFieldAddr(inst); |
| break; |
| case VM_RT_CHECKCAST_WITHRESOLVE: |
| { //handling is equal to taucheckcast |
| cgnode = findCnGNode_op(inst->getDst()->getId()); |
| assert(cgnode!=NULL); |
| if (cgnode->lNode == NULL) { |
| cgn_src=findCnGNode_op(inst->getSrc(2)->getId()); |
| assert(cgn_src!=NULL); |
| cgnode->lNode = cgn_src; |
| } |
| } |
| default: break; |
| } |
| } |
| break; |
| case Op_TauLdInd: // ldind |
| { |
| type=inst->getDst()->getType(); |
| if (type->isObject()) { |
| cgnode=findCnGNode_op(inst->getDst()->getId()); |
| assert(cgnode!=NULL); |
| // ref to loaded object |
| cgn_src=findCnGNode_op(inst->getSrc(0)->getId()); |
| assert(cgn_src!=NULL); |
| addEdge(cgn_src,cgnode,ET_POINT,inst); |
| } |
| if (type->isValue()) { |
| Inst* srcInst = inst->getSrc(0)->getInst(); |
| U_32 src_opcode = srcInst->getOpcode(); |
| if (src_opcode==Op_LdStaticAddr || isVMHelperCall(srcInst, VM_RT_GET_STATIC_FIELD_ADDR_WITHRESOLVE)) { |
| break; |
| } |
| |
| cgnode=findCnGNode_op(inst->getDst()->getId()); |
| assert(cgnode!=NULL); |
| // ref to loaded object |
| cgn_src=findCnGNode_op(inst->getSrc(0)->getId()); |
| assert(cgn_src!=NULL); |
| addEdge(cgn_src,cgnode,ET_POINT,inst); |
| } |
| } |
| break; |
| |
| case Op_LdArrayBaseAddr: // ldbase |
| case Op_AddScaledIndex: // addindex |
| if (inst->getDst()->getType()->isReference()) { |
| cgnode=findCnGNode_op(inst->getDst()->getId()); |
| assert(cgnode!=NULL); |
| // ref to loaded address |
| if (inst->getOpcode()==Op_LdArrayBaseAddr) { |
| cgn_src=findCnGNode_op(inst->getSrc(0)->getId()); |
| assert(cgn_src!=NULL); |
| addEdge(cgn_src,cgnode,ET_FIELD,inst); // ref to base element |
| } |
| if (inst->getOpcode()==Op_AddScaledIndex) { |
| if (inst->getSrc(0)->getInst()->getOpcode()==Op_LdArrayBaseAddr) { |
| cgn_src=findCnGNode_op( |
| inst->getSrc(0)->getInst()->getSrc(0)->getId()); |
| assert(cgn_src!=NULL); |
| addEdge(cgn_src,cgnode,ET_FIELD,inst); // ref from array object to inner objects |
| } |
| } |
| } |
| break; |
| |
| case Op_TauStInd: // stind |
| { |
| type = inst->getSrc(0)->getType(); |
| if (type->isObject()) { |
| // ref to loaded address |
| cgn_src=findCnGNode_op(inst->getSrc(0)->getId()); |
| assert(cgn_src!=NULL); |
| cgnode=findCnGNode_op(inst->getSrc(1)->getId()); |
| assert(cgnode!=NULL); |
| addEdge(cgnode,cgn_src,ET_DEFER,inst); |
| break; |
| } |
| if (type->isValue()) { |
| Inst* srcInst = inst->getSrc(1)->getInst(); |
| U_32 src_opcode = srcInst->getOpcode(); |
| if (src_opcode==Op_LdStaticAddr || isVMHelperCall(srcInst, VM_RT_GET_STATIC_FIELD_ADDR_WITHRESOLVE)) { |
| 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 |
| methType = typeManager.getMethodPtrType(inst->asMethodInst()->getMethodDesc()); |
| n = methType->getNumParams(); |
| for (U_32 i = 0; i < n; i++) { |
| Type* tt = methType->getParamType(i); |
| if (!tt->isReference()) { |
| continue; |
| } |
| cgnode=findCnGNode_mp(inst->getId(),i); |
| assert(cgnode!=NULL); |
| Opnd* param = inst->getSrc(2+i); |
| cgn_src=findCnGNode_op(param->getId()); |
| assert(cgn_src!=NULL); |
| addEdge(cgnode,cgn_src,ET_DEFER,inst); |
| } |
| break; |
| |
| case Op_IndirectMemoryCall: //callimem |
| method_inst=inst->getSrc(0)->getInst(); |
| if (method_inst->getOpcode() == Op_LdVar) { |
| methType = inst->getSrc(0)->getType()->asMethodPtrType(); |
| } else if (method_inst->asMethodInst()!=NULL) { |
| methType = typeManager.getMethodPtrType(method_inst->asMethodInst()->getMethodDesc()); |
| } else { |
| assert(method_inst->isVMHelperCallInst()); //lazy resolution helper |
| methType = inst->getSrc(0)->getType()->asMethodPtrType(); |
| } |
| assert(methType!=NULL); |
| n = methType->getNumParams(); |
| for (U_32 i = 0; i < n; i++) { |
| Type* tt = methType->getParamType(i); |
| if (!tt->isReference()) { |
| continue; |
| } |
| cgnode = findCnGNode_mp(inst->getId(),i); |
| assert(cgnode!=NULL); |
| Opnd* param = inst->getSrc(3+i); |
| cgn_src=findCnGNode_op(param->getId()); |
| assert(cgn_src!=NULL); |
| addEdge(cgnode,cgn_src,ET_DEFER,inst); |
| } |
| break; |
| |
| case Op_StVar: // stvar |
| type = inst->getDst()->getType(); |
| if (type->isObject()) { |
| cgnode = findCnGNode_op(inst->getDst()->getId()); |
| assert(cgnode!=NULL); |
| cgn_src=findCnGNode_op(inst->getSrc(0)->getId()); |
| assert(cgn_src!=NULL); |
| addEdge(cgn_src,cgnode,ET_DEFER,inst); |
| } |
| break; |
| |
| case Op_Phi: // phi |
| type = inst->getDst()->getType(); |
| if (type->isObject()) { |
| U_32 nsrc=inst->getNumSrcOperands(); |
| cgnode = findCnGNode_op(inst->getDst()->getId()); |
| assert(cgnode!=NULL); |
| for (U_32 i=0; i<nsrc; i++) { |
| Opnd* srcOpnd = inst->getSrc(i); |
| cgn_src=findCnGNode_op(srcOpnd->getId()); |
| assert(cgn_src!=NULL); |
| addEdge(cgn_src,cgnode,ET_DEFER,inst); |
| } |
| } |
| break; |
| |
| case Op_LdVar: // ldvar |
| type = inst->getDst()->getType(); |
| if (type->isReference()&&(!type->isUnmanagedPtr())) { |
| cgnode = findCnGNode_op(inst->getDst()->getId()); |
| assert(cgnode!=NULL); |
| cgn_src=findCnGNode_op(inst->getSrc(0)->getId()); |
| assert(cgn_src!=NULL); |
| addEdge(cgn_src,cgnode,ET_DEFER,inst); // load ldobj |
| } |
| break; |
| |
| case Op_Return: // return |
| ntype=NT_EXITVAL; |
| case Op_Throw: // throw |
| if (ntype==0) |
| ntype=NT_THRVAL; |
| if (inst->getNumSrcOperands()>0) { |
| cgnode = findCnGNode_in(inst->getId()); |
| assert(cgnode!=NULL); |
| cgn_src=findCnGNode_op(inst->getSrc(0)->getId()); |
| assert(cgn_src!=NULL); |
| addEdge(cgnode,cgn_src,ET_DEFER,inst); |
| } |
| break; |
| |
| case Op_TauStaticCast: // staticcast |
| case Op_TauCast: // cast |
| cgnode = findCnGNode_op(inst->getDst()->getId()); |
| assert(cgnode!=NULL); |
| if (cgnode->lNode == NULL) { |
| cgn_src=findCnGNode_op(inst->getSrc(0)->getId()); |
| assert(cgn_src!=NULL); |
| cgnode->lNode = cgn_src; |
| } |
| break; |
| |
| case Op_TauMonitorEnter: // monenter |
| case Op_TauMonitorExit: // monexit |
| case Op_TypeMonitorEnter:// tmonenter |
| case Op_TypeMonitorExit: // tmonexit |
| break; |
| |
| default: |
| if (verboseLog) { |
| not_exam = true; |
| } |
| } |
| if (verboseLog) { |
| if (not_exam) { |
| Log::out() <<"!!! Not examined. "; |
| inst->print(Log::out()); Log::out() << std::endl; |
| not_exam = false; |
| } |
| } |
| } |
| return; |
| } // instrExam2() |
| |
| |
| EscAnalyzer::CnGNode* |
| EscAnalyzer::addCnGNode(Inst* inst, Type* type, U_32 ntype) { |
| CnGNode* cgnode = new (eaMemManager) CnGNode; // new CG node |
| |
| cgnode->cngNodeId = ++lastCnGNodeId; |
| cgnode->instrId = inst->getId(); |
| cgnode->nodeType = ntype; |
| cgnode->lNode = NULL; |
| cgnode->nInst = inst; |
| cgnode->outEdges = NULL; |
| if (cgnode->nodeType==NT_DEFARG) |
| cgnode->argNumber = defArgNumber; // number of formal parameter |
| else |
| cgnode->argNumber = 0; |
| if ((ntype==NT_STFLD)||ntype==NT_THRVAL) |
| setFullState(cgnode,GLOBAL_ESCAPE); |
| else { |
| if (ntype==NT_ACTARG) { |
| setFullState(cgnode,ARG_ESCAPE); |
| if (inst->getOpcode()==Op_IndirectMemoryCall) |
| setVirtualCall(cgnode); |
| } else |
| setFullState(cgnode,NO_ESCAPE); |
| } |
| if (ntype==NT_EXITVAL) |
| setOutEscaped(cgnode); |
| cgnode->nodeMDs = NULL; |
| if (type->isReference()) { |
| if (type->isArray()) { |
| if (type->asArrayType()->getElementType()->isReference()) { |
| cgnode->nodeRefType = NR_REFARR; |
| } else |
| cgnode->nodeRefType = NR_ARR; |
| } else |
| cgnode->nodeRefType = NR_REF; |
| if (ntype&(NT_OBJECT|NT_RETVAL)||ntype==NT_LDOBJ) { |
| cgnode->nodeMDs = new (eaMemManager) NodeMDs(eaMemManager); // to collect methods receiving object |
| } |
| } else { |
| cgnode->nodeRefType = NR_PRIM; |
| } |
| if (cgnode->nodeType==NT_OBJECT && cgnode->nodeRefType == NR_REF) { |
| NamedType* nt = (NamedType*)(inst->getDst())->getType(); |
| if (nt->isUnresolvedType() || nt->isFinalizable()) { |
| // finalized objects cannot be removed |
| // unresolved objects too |
| setOutEscaped(cgnode); |
| } |
| } |
| cngNodes->push_back(cgnode); |
| return cgnode; |
| } // addCnGNode(Inst* inst, Type* type, U_32 ntype) |
| |
| |
| EscAnalyzer::CnGNode* |
| EscAnalyzer::addCnGNode_op(Inst* inst, Type* type, U_32 ntype) { |
| CnGNode* cgnode = addCnGNode(inst, type, ntype); // new CG node |
| Opnd* opnd = inst->getDst(); |
| |
| cgnode->opndId = opnd->getId(); |
| cgnode->refObj = opnd; |
| if (shortLog) { |
| Log::out() <<"++++ addNode "; printCnGNode(cgnode,Log::out()); |
| Log::out() << std::endl; |
| } |
| return cgnode; |
| } // addCnGNode_op(Inst* inst, Type* type, U_32 ntype) |
| |
| |
| EscAnalyzer::CnGNode* |
| EscAnalyzer::addCnGNode_mp(Inst* inst, MethodPtrType* mpt, U_32 ntype, U_32 narg) { |
| Type* type = mpt->getParamType(narg); |
| CnGNode* cgnode = addCnGNode(inst, type, ntype); // new CG node |
| |
| cgnode->opndId = 0; |
| cgnode->argNumber = narg; |
| cgnode->refObj = mpt; |
| if (shortLog) { |
| Log::out() <<"++++ addNode "; printCnGNode(cgnode,Log::out()); |
| Log::out() << std::endl; |
| } |
| return cgnode; |
| } // addCnGNode_mp(Inst* inst, MethodDesc* md, U_32 ntype, U_32 narg) |
| |
| |
| EscAnalyzer::CnGNode* |
| EscAnalyzer::addCnGNode_ex(Inst* inst, U_32 ntype) { |
| Type* type = inst->getSrc(0)->getType(); |
| CnGNode* cgnode = addCnGNode(inst, type, ntype); // new CG node |
| |
| cgnode->opndId = 0; |
| cgnode->refObj = inst->getSrc(0); // returned or thrown operand |
| if (shortLog) { |
| Log::out() <<"++++ addNode "; printCnGNode(cgnode,Log::out()); |
| Log::out() << std::endl; |
| } |
| return cgnode; |
| } // addCnGNode_ex(Inst* inst, U_32 ntype) |
| |
| |
| EscAnalyzer::CnGNode* |
| EscAnalyzer::addCnGNode_fl(Inst* inst, U_32 ntype) { |
| Type* type = inst->getDst()->getType(); |
| CnGNode* cgnode = addCnGNode(inst, type, ntype); // new CG node |
| |
| cgnode->opndId = 0; |
| cgnode->refObj = inst; // returned or thrown operand |
| if (shortLog) { |
| Log::out() <<"++++ addNode "; printCnGNode(cgnode,Log::out()); |
| Log::out() << std::endl; |
| } |
| return cgnode; |
| } // addCnGNode_fl(Inst* inst, U_32 ntype) |
| |
| |
| EscAnalyzer::CnGNode* |
| EscAnalyzer::findCnGNode_op(U_32 nId) { |
| CnGNodes::iterator it; |
| for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { |
| if ((*it)->opndId==nId && ((*it)->nodeType & (NT_OBJS|NT_LDVAL))) |
| return (*it); |
| } |
| return(NULL); |
| } // findCnGNode_op(U_32 nId) |
| |
| |
| EscAnalyzer::CnGNode* |
| EscAnalyzer::findCnGNode_id(U_32 nId) { |
| CnGNodes::iterator it; |
| for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { |
| if ((*it)->cngNodeId==nId) |
| return (*it); |
| } |
| return(NULL); |
| } // findCnGNode_id(U_32 nId) |
| |
| |
| EscAnalyzer::CnGNode* |
| EscAnalyzer::findCnGNode_in(U_32 nId) { |
| CnGNodes::iterator it; |
| for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { |
| if ((*it)->instrId==nId) |
| return (*it); |
| } |
| return(NULL); |
| } // findCnGNode_in(U_32 nId) |
| |
| |
| EscAnalyzer::CnGNode* |
| EscAnalyzer::findCnGNode_mp(U_32 iId, U_32 aId) { |
| CnGNodes::iterator it; |
| for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { |
| if ((*it)->instrId==iId && (*it)->argNumber==aId && |
| (*it)->nodeType == NT_ACTARG) |
| return (*it); |
| } |
| return(NULL); |
| } // findCnGNode_mp(U_32 iId, U_32 aId) |
| |
| |
| EscAnalyzer::CnGNode* |
| EscAnalyzer::findCnGNode_fl(Inst* inst, U_32 ntype) { |
| FieldDesc* fd1 = NULL; |
| if (inst->asFieldAccessInst()==NULL) {// unresolved field access |
| assert(inst->getOpcode() == Op_AddOffset || isVMHelperCall(inst, VM_RT_GET_STATIC_FIELD_ADDR_WITHRESOLVE)); |
| } else { |
| fd1 = inst->asFieldAccessInst()->getFieldDesc(); |
| } |
| |
| U_32 idr = 0; //object field used to reference this field |
| if (ntype==NT_INSTFLD) { |
| idr=inst->getSrc(0)->getId(); |
| } |
| for (CnGNodes::iterator it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { |
| CnGNode* cgNode = *it; |
| if (cgNode->nodeType==ntype) { |
| Inst* inst2 = (Inst*)cgNode->refObj; |
| FieldDesc* fd2 = NULL; |
| if (inst2->asFieldAccessInst()==NULL) { |
| assert(inst2->getOpcode() == Op_AddOffset || isVMHelperCall(inst2, VM_RT_GET_STATIC_FIELD_ADDR_WITHRESOLVE)); |
| } else { |
| fd2 = inst2->asFieldAccessInst()->getFieldDesc(); |
| } |
| if ((fd1==NULL) != (fd2==NULL)) { |
| continue; // nodes for resolved & unresolved fields |
| } |
| if ( (fd1!=NULL && fd1->getFieldHandle() == fd2->getFieldHandle()) || inst == inst2/*don't optimize*/ ) { |
| if (ntype==NT_INSTFLD) { |
| U_32 idf = inst2->getSrc(0)->getId(); |
| if (idr!=idf) { |
| continue; |
| } |
| } |
| return (*it); |
| } |
| } |
| } |
| return(NULL); |
| } // findCnGNode_fl(Opnd* opnd, U_32 ntype) |
| |
| |
| void |
| EscAnalyzer::addEdge(CnGNode* cgnfrom, CnGNode* cgnto, |
| U_32 etype, Inst* inst) { |
| CnGEdges::iterator it; |
| CnGRefs* el = NULL; |
| CnGRef* ref; |
| CnGNode* cgn1=cgnfrom; |
| CnGNode* cgn2=cgnto; |
| |
| if (cgnfrom->lNode) { |
| cgn1 = findCnGNode_id(cgnfrom->lNode->cngNodeId); // to find CnG node using CnG node Id |
| assert(cgn1!=NULL); |
| } |
| if (cgnfrom->nodeType == NT_REF && cgnfrom->lNode == NULL) { |
| bool helperCall = isVMHelperCall(cgnfrom->nInst, VM_RT_CHECKCAST_WITHRESOLVE); |
| assert(cgnfrom->nInst->getOpcode()==Op_TauCast || cgnfrom->nInst->getOpcode()==Op_TauStaticCast || helperCall); |
| cgn1 = findCnGNode_op(cgnfrom->nInst->getSrc(helperCall ? 2 : 0)->getId()); |
| assert(cgn1!=NULL); |
| cgnfrom->lNode = cgn1; |
| } |
| |
| if (verboseLog) { |
| Log::out() |
| << "++++ addEdge: " << cgnfrom->cngNodeId << "-" << cgnfrom->opndId |
| << " ( "<<cgn1->cngNodeId << "-" << cgn1->opndId << " ) to " |
| << cgnto->cngNodeId << "-" << cgnto->opndId << " ( " |
| << cgn2->cngNodeId << "-" << cgn2->opndId << " )" << std::endl; |
| } |
| if (cgn1==cgn2) { |
| if (verboseLog) { |
| Log::out() << "+++++++ equal " |
| << cgnfrom->cngNodeId<< "-" << cgnfrom->opndId |
| << " ( "<<cgn1->cngNodeId << "-" << cgn1->opndId << " ) to " |
| << cgnto->cngNodeId << "-" << cgnto->opndId << " ( " |
| << cgn2->cngNodeId << "-" << cgn2->opndId << " )" << std::endl; |
| } |
| return; |
| } |
| for ( it = cngEdges->begin( ); it != cngEdges->end( ); it++ ) { |
| if ((*it)->cngNodeFrom == cgn1) { |
| CnGRefs::iterator itr; |
| for ( itr = (*it)->refList->begin( ); itr != (*it)->refList->end( ); itr++ ) { |
| if ((*itr)->cngNodeTo == cgn2 && (*itr)->edgeType == etype && cgn1->nodeType != NT_INSTFLD) { |
| if (etype==ET_FIELD || cgn1->nodeType==NT_ACTARG) { |
| if (verboseLog) { |
| Log::out() << "++++ addEdge: ET_FIELD || cgn1==NT_ACTARG && *->cngNodeTo == cgn2" << std::endl; |
| } |
| return; |
| } |
| if (inst->getOpcode() == Op_LdFieldAddr) { |
| FieldDesc* fd=inst->asFieldAccessInst()->getFieldDesc(); |
| if (fd->getParentType()->isSystemString()&&strcmp(fd->getName(),"value")==0) { |
| if (verboseLog) { |
| Log::out() << "++++ addEdge: ldflda String.value" << std::endl; |
| } |
| return; |
| } |
| } |
| if (verboseLog) { |
| Log::out() << "++++ addEdge: edge already exists and new is added" << std::endl; |
| } |
| } |
| } |
| ref = new (eaMemManager) CnGRef; |
| ref->cngNodeTo=cgn2; |
| ref->edgeType=etype; |
| ref->edgeInst=inst; |
| (*it)->refList->push_back(ref); |
| if (verboseLog) { |
| Log::out() << "++++ addEdge: added CnGRef" << std::endl; |
| } |
| return; |
| } |
| } |
| ref = new (eaMemManager) CnGRef; |
| ref->cngNodeTo=cgn2; |
| ref->edgeType=etype; |
| ref->edgeInst=inst; |
| CnGEdge* cgedge=new (eaMemManager) CnGEdge; |
| el=new CnGRefs(eaMemManager); |
| cgedge->cngNodeFrom=cgn1; |
| el->push_back(ref); |
| cgedge->refList=el; |
| cngEdges->push_back(cgedge); |
| cgn1->outEdges=el; |
| if (verboseLog) { |
| Log::out() << "++++ addEdge: added edge" << std::endl; |
| } |
| |
| } // addEdge(CnGNode* cgnfrom, CnGNode* cgnto, U_32 etype, Inst* inst) |
| |
| |
| void |
| EscAnalyzer::setCreatedObjectStates() { |
| CnGNodes::iterator it; |
| NodeMDs::iterator it1; |
| |
| for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { |
| U_32 nt = (*it)->nodeType; |
| if (nt==NT_STFLD || nt==NT_CATCHVAL |
| || (nt==NT_RETVAL && (*it)->nInst->getOpcode()==Op_IndirectMemoryCall) |
| || (nt==NT_RETVAL && (*it)->nInst->asMethodInst()->getMethodDesc()->isNative())) { |
| initNodeType = NT_STFLD; |
| if (verboseLog) { |
| Log::out() <<"-- before scanGE: nodeId " |
| <<(*it)->cngNodeId<<" opId "<<(*it)->opndId<<" state "; |
| printState(*it); Log::out() << std::endl; |
| } |
| scanCnGNodeRefsGE(*it,false); |
| } |
| } |
| scannedObjs->clear(); |
| scannedObjsRev->clear(); |
| for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { |
| if ((*it)->nodeType&NT_EXITVAL || (*it)->nodeType==NT_DEFARG) { // returned, thrown , defarg |
| if (verboseLog) { |
| Log::out() <<"-- before scanEVDA: nodeId " <<(*it)->cngNodeId<<" opId "<<(*it)->opndId<<" state "; |
| printState(*it); Log::out() << std::endl; |
| } |
| initNodeType = (*it)->nodeType; |
| scanCnGNodeRefsGE(*it,false); |
| scannedObjs->clear(); |
| scannedObjsRev->clear(); |
| } |
| } |
| scannedObjs->clear(); |
| scannedObjsRev->clear(); |
| for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { |
| if ((*it)->nodeType==NT_ACTARG) { |
| curMDNode=(*it)->cngNodeId; |
| if (verboseLog) { |
| Log::out() <<"-- before scanAE: nodeId " <<(*it)->cngNodeId<<" opId "<<(*it)->opndId<<" state "; |
| printState(*it); Log::out() << std::endl; |
| } |
| initNodeType = NT_ACTARG; |
| scanCnGNodeRefsAE(*it,false); |
| scannedObjs->clear(); |
| scannedObjsRev->clear(); |
| } |
| } |
| scannedObjs->clear(); |
| scannedObjsRev->clear(); |
| if (method_ea_level==0) { |
| DominatorTree* dominatorTree = irManager.getDominatorTree(); |
| if (!(dominatorTree && dominatorTree->isValid())) { |
| OptPass::computeDominators(irManager); |
| dominatorTree = irManager.getDominatorTree(); |
| } |
| if (dominatorTree && dominatorTree->isValid()) { |
| OptPass::computeLoops(irManager,false); |
| LoopTree* ltree = irManager.getLoopTree(); |
| if (ltree->isValid()) |
| for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { |
| if ( (*it)->nodeType==NT_OBJECT) { |
| if (ltree->getLoopHeader((*it)->nInst->getNode(),false)) { |
| if (verboseLog) { |
| Log::out() |
| <<"--setSt loop: nodeId " |
| <<(*it)->cngNodeId<<" opId " |
| <<(*it)->opndId<<" state "; |
| printState(*it); |
| Log::out() <<" to set loop" << std::endl; |
| } |
| setLoopCreated(*it); |
| comObjStat._n_lo++; |
| } |
| } |
| } |
| } else { |
| if (verboseLog) { |
| mh.printFullName(Log::out()); Log::out() << std::endl; |
| Log::out() << "DominatorTree isn't valid " << std::endl; |
| } |
| } |
| } |
| for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { |
| U_32 nt = (*it)->nodeType; |
| 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); |
| MethodPtrType* mpt = (MethodPtrType*)n->refObj; |
| Inst* callInst = n->nInst; |
| if (verboseLog) { |
| Log::out()<<"--setSt chk arg_esc: nodeId " <<(*it)->cngNodeId |
| <<" opId " <<(*it)->opndId<<" state "; |
| printState(*it); Log::out() << std::endl; |
| Log::out() << " "; callInst->print(Log::out()); |
| Log::out() << std::endl; |
| } |
| if (mpt->isUnresolvedMethodPtrType() || mpt->getMethodDesc()->isNative()) { // not scanned native methods |
| setEscState(*it,GLOBAL_ESCAPE); |
| if (verboseLog) { |
| mpt->print(Log::out()); |
| Log::out() << std::endl; |
| if (mpt->isUnresolvedMethodPtrType()) { |
| Log::out() << " isUnresolved: true" << std::endl; |
| } else { |
| Log::out() << " isNative: true" << std::endl; |
| } |
| } |
| if (verboseLog) { |
| Log::out() <<"--setSt 1: nodeId " <<(*it)->cngNodeId<<" opId "<<(*it)->opndId <<" state "; |
| printState(*it); |
| Log::out()<<" to gl.esc."<< std::endl; |
| } |
| break; |
| } |
| if (callInst->getOpcode()!=Op_DirectCall) { // not direct call |
| setVirtualCall(*it); |
| if (method_ea_level == 0 && do_sync_removal) { |
| MonUnit* mu = NULL; |
| if (monitorInstUnits!=NULL) |
| mu = findMonUnit((*it)->opndId); |
| if (mu != NULL) { |
| addMonUnitVCall(mu,callInst); |
| if (verboseLog) { |
| Log::out() << "=-=-=-=- callimem for this "; |
| Log::out() << std::endl; |
| Log::out() << "=-=- "; |
| printCnGNode(*it,Log::out()); |
| Log::out() << std::endl; |
| printCnGNode(n,Log::out()); |
| Log::out() << std::endl; |
| callInst->print(Log::out()); |
| Log::out() << std::endl; |
| mpt->print(Log::out()); |
| Log::out() << std::endl; |
| Log::out() << "=-=-=-=- end " << std::endl; |
| } |
| continue; |
| } |
| } |
| if (verboseLog) { |
| callInst->print(Log::out()); Log::out() << std::endl; |
| logMethod(mpt); |
| |
| Log::out() <<"--setSt 2: nodeId " <<(*it)->cngNodeId<<" opId "<<(*it)->opndId <<" state "; |
| printState(*it); |
| Log::out() <<" to v.call." << std::endl; |
| } |
| continue; //break; |
| } |
| CalleeMethodInfo* mtdInfo = mpt->isUnresolvedMethodPtrType() ? NULL : findMethodInfo(mpt->getMethodDesc(), callInst); |
| if (mtdInfo == NULL) { // no info about called method |
| setEscState(*it,GLOBAL_ESCAPE); |
| if (verboseLog) { |
| Log::out() <<"--setSt 3: nodeId " <<(*it)->cngNodeId<<" opId "<<(*it)->opndId <<" state "; |
| printState(*it);Log::out() <<" to gl.esc." << std::endl; |
| } |
| break; |
| } else { // to use info about scanned method |
| U_32 narg = n->argNumber; |
| ParamInfos::iterator it2; |
| U_32 state = 0; |
| if (verboseLog) { |
| Log::out() << "--setSt cmi: method " |
| << mtdInfo->methodIdent->parentName << "::" |
| << mtdInfo->methodIdent->name << " " |
| << mtdInfo->methodIdent->signature << std::endl; |
| } |
| for (it2 = mtdInfo->paramInfos->begin( ); it2 != mtdInfo->paramInfos->end( ); it2++) { |
| if (verboseLog) { |
| Log::out() |
| <<(*it2)->paramNumber<<" == "<<narg<<" state " |
| <<(*it2)->state <<" < "<< getEscState(*it)<<" "; |
| printState(*it); Log::out() << std::endl; |
| } |
| if ((*it2)->paramNumber == narg) { //???to add scanning of contained obj |
| if ((state=(*it2)->state&ESC_MASK) < getEscState(*it)) { |
| if (verboseLog) { |
| Log::out()<<"--setSt cmi1: nodeId " <<(*it)->cngNodeId<<" opId "<<(*it)->opndId <<" state "; |
| printState(*it); Log::out() <<" to state " <<state<< std::endl; |
| } |
| setEscState(*it,state); |
| } |
| } |
| } |
| } |
| } |
| if (getEscState(*it)==GLOBAL_ESCAPE) { // to set gl.escape for contained objects |
| initNodeType = NT_STFLD; |
| CnGNode* cn = *it; |
| CnGNode* nn = NULL; |
| CnGRefs::iterator it2; |
| if (cn->nodeType == NT_LDOBJ) { |
| scanCnGNodeRefsGE(cn,true); |
| } else { |
| if (cn->outEdges != NULL) { |
| for (it2 = cn->outEdges->begin( ); it2 != cn->outEdges->end( ); it2++ ) { |
| nn = (*it2)->cngNodeTo; |
| if (getEscState(nn)==GLOBAL_ESCAPE) { |
| continue; |
| } |
| scanCnGNodeRefsGE(nn,false); |
| } |
| } |
| } |
| scannedObjs->clear(); |
| scannedObjsRev->clear(); |
| } |
| } |
| } |
| for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { |
| U_32 nt = (*it)->nodeType; |
| if ((nt==NT_RETVAL) && getEscState(*it)>GLOBAL_ESCAPE) { |
| MethodDesc* mdesc = (*it)->nInst->asMethodInst()->getMethodDesc(); |
| if (((*it)->nInst->getOpcode())!=Op_DirectCall) { // only direct call may be here |
| assert(0); |
| continue; |
| } |
| CalleeMethodInfo* mthInfo = findMethodInfo(mdesc,(*it)->nInst); |
| if (mthInfo == NULL) { |
| if (verboseLog) { |
| Log::out() <<"--setCOS 4: nodeId " <<(*it)->cngNodeId<<" opId "<<(*it)->opndId <<" state "; |
| printState(*it); Log::out() <<" to gl.esc."<< std::endl; |
| } |
| initNodeType = NT_STFLD; |
| scanCnGNodeRefsGE(*it,false); |
| } else { |
| if (getEscState(*it)>((mthInfo->retValueState)&ESC_MASK) || getOutEscaped(*it)==0) { |
| if (verboseLog) { |
| Log::out() <<"--setCOS 5: nodeId " <<(*it)->cngNodeId<<" opId "<<(*it)->opndId <<" state "; |
| printState(*it); |
| Log::out() <<" to "<< mthInfo->retValueState<< std::endl; |
| } |
| if (((mthInfo->retValueState)&ESC_MASK) == GLOBAL_ESCAPE) { |
| initNodeType = NT_STFLD; // global_escape propagate |
| } else { |
| initNodeType = NT_EXITVAL; // out_escaped propagate |
| } |
| scanCnGNodeRefsGE(*it,false); |
| } |
| } |
| } |
| } |
| scannedObjs->clear(); |
| scannedObjsRev->clear(); |
| scannedSucNodes->clear(); |
| // check states of array elements' and fields' values |
| for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { |
| U_32 nt = (*it)->nodeType; |
| if ((nt&(NT_OBJECT|NT_RETVAL) || nt==NT_LDOBJ) && (getEscState(*it)!=GLOBAL_ESCAPE)) { |
| if ((*it)->outEdges == NULL) |
| continue; |
| if (verboseLog) { |
| Log::out() <<"--setCOS 6: to check subobj nodes "; |
| printCnGNode(*it,Log::out()); Log::out() << std::endl; |
| } |
| checkSubobjectStates(*it); |
| } |
| scannedObjs->clear(); |
| scannedObjsRev->clear(); |
| scannedSucNodes->clear(); |
| } |
| |
| } // setCreatedObjectStates() |
| |
| |
| void |
| EscAnalyzer::scanCnGNodeRefsGE(CnGNode* cgn, bool check_var_src) { |
| CnGEdges::iterator it; |
| CnGRefs::iterator it1; |
| CnGNode* next_node; |
| ObjIds* scObjs = check_var_src ? scannedObjsRev : scannedObjs; |
| U_32 ni_opcode = cgn->nInst->getOpcode(); |
| bool needFix = isStateNeedGEFix(getFullState(cgn),cgn->nodeType); |
| |
| if (cgn->nodeType != NT_STFLD && cgn->nodeType != NT_THRVAL && cgn->nodeType != NT_EXITVAL |
| && cgn->nodeType != NT_DEFARG && cgn->nodeType != NT_RETVAL && cgn->nodeType != NT_LDOBJ) |
| assert(needFix); |
| if (verboseLog) { |
| Log::out() <<"--scanGE 1: nodeId "<<cgn->cngNodeId <<" opId "<<cgn->opndId<<" state "; |
| printState(cgn); |
| Log::out() <<" " << nodeTypeToString(cgn) <<cgn->nodeType <<" check_var_src " << check_var_src << std::endl; |
| } |
| if (cgn->nodeType == NT_LDVAL) { |
| if (verboseLog) { |
| Log::out() <<"--scanGE > 1: primitive type " << std::endl; |
| } |
| return; |
| } |
| if (scObjs->size()!=0) { |
| if (checkScanned(scObjs,cgn->cngNodeId)) { |
| if (verboseLog) { |
| Log::out() <<"--scanGE > 1: was scanned earlier " << std::endl; |
| } |
| return; |
| } |
| } |
| |
| if (initNodeType!=NT_EXITVAL && initNodeType!=NT_DEFARG) { // |
| if (getEscState(cgn) > GLOBAL_ESCAPE) { |
| if (verboseLog) { |
| Log::out() <<"--scanGE 2: nodeId " |
| <<cgn->cngNodeId<<" opId "<<cgn->opndId <<" state "; |
| printState(cgn); |
| Log::out() <<" to gl.esc."<< std::endl; |
| Log::out() <<"--scanGE 2: "<< nodeTypeToString(cgn) |
| << cgn->nodeType <<" initNode "<<initNodeType<< std::endl; |
| } |
| setEscState(cgn,GLOBAL_ESCAPE); |
| } |
| } |
| if (initNodeType==NT_EXITVAL) { |
| if (getOutEscaped(cgn) == 0) { |
| if (verboseLog) { |
| Log::out() <<"--scanGE 3: nodeId " |
| <<cgn->cngNodeId<<" opId "<<cgn->opndId <<" state "; |
| printState(cgn); |
| Log::out() <<" to out.esc."<< std::endl; |
| Log::out() <<"--scanGE 3: "<< nodeTypeToString(cgn) |
| << cgn->nodeType <<" initNode "<<initNodeType<< std::endl; |
| } |
| setOutEscaped(cgn); |
| } |
| // The objects created in the method are not global escaped through return |
| } |
| if (initNodeType==NT_DEFARG) { |
| if (needFix) { |
| if (verboseLog) { |
| Log::out() <<"--scanGE 4: nodeId " <<cgn->cngNodeId<<" opId "<<cgn->opndId <<" state "; |
| printState(cgn); |
| if (cgn->nodeType == NT_OBJECT || cgn->nodeType == NT_LDOBJ || cgn->nodeType == NT_RETVAL) { |
| Log::out() <<" to gl.esc."<< std::endl; |
| } else { |
| Log::out() <<" to out.esc."<< std::endl; |
| } |
| Log::out() <<"--scanGE 4: "<< nodeTypeToString(cgn) |
| << cgn->nodeType <<" initNode "<<initNodeType<< std::endl; |
| } |
| if (cgn->nodeType == NT_OBJECT || cgn->nodeType == NT_LDOBJ || cgn->nodeType == NT_RETVAL) { |
| setEscState(cgn,GLOBAL_ESCAPE); //objects escaped through defarg - global escape |
| } else { |
| setOutEscaped(cgn); |
| } |
| } |
| } |
| |
| scObjs->push_back(cgn->cngNodeId); |
| if (cgn->outEdges != NULL) { |
| bool to_check_var_src = false; |
| for (it1 = cgn->outEdges->begin( ); it1 != cgn->outEdges->end( ); it1++ ) { |
| next_node = (*it1)->cngNodeTo; |
| needFix = isStateNeedGEFix(getFullState(next_node),next_node->nodeType); |
| if (!needFix) { |
| if (verboseLog) { |
| Log::out() <<"--scanGE 5.0 next: already set "; |
| printState(next_node); Log::out() << std::endl; |
| } |
| continue; |
| } |
| if (next_node->nodeType == NT_LDOBJ && next_node->nInst->getOpcode()==Op_LdVar |
| && cgn->nodeType!=NT_VARVAL) { |
| to_check_var_src = true; |
| } |
| if (verboseLog) { |
| Log::out() <<"--scanGE 5 next: nodeId " |
| <<next_node->cngNodeId<<" opId "<<next_node->opndId <<" state "; |
| printState(next_node); Log::out() << std::endl; |
| } |
| scanCnGNodeRefsGE(next_node,to_check_var_src); |
| if (verboseLog) { |
| Log::out() <<"--scanGE ret 1 for node: " << next_node->cngNodeId |
| <<" opId " << next_node->opndId << std::endl; |
| } |
| } |
| } |
| if (check_var_src) { |
| if (ni_opcode == Op_LdVar || ni_opcode == Op_StVar || ni_opcode ==Op_Phi) { |
| U_32 nsrc=cgn->nInst->getNumSrcOperands(); |
| for (U_32 i=0; i<nsrc; i++) { |
| next_node = findCnGNode_op(cgn->nInst->getSrc(i)->getId()); |
| needFix = isStateNeedGEFix(getFullState(next_node),next_node->nodeType); |
| if (!needFix) { |
| if (verboseLog) { |
| Log::out() <<"--scanGE 6.0 next: already set "; |
| printState(next_node); Log::out() << std::endl; |
| } |
| continue; |
| } |
| if (verboseLog) { |
| Log::out() <<"--scanGE 6 next: nodeId " |
| <<next_node->cngNodeId<<" opId "<<next_node->opndId <<" state "; |
| printState(next_node); Log::out() << std::endl; |
| } |
| scanCnGNodeRefsGE(next_node,check_var_src); |
| if (verboseLog) { |
| Log::out() <<"--scanGE ret 2 for node: " << next_node->cngNodeId |
| <<" opId " << next_node->opndId << std::endl; |
| } |
| } |
| } |
| } |
| |
| } // scanCnGNodeRefsGE(CnGNode* cgn, bool check_var_src) |
| |
| |
| void |
| EscAnalyzer::scanCnGNodeRefsAE(CnGNode* cgn, bool check_var_src) { |
| CnGEdges::iterator it; |
| CnGRefs::iterator it1; |
| CnGNode* next_node; |
| ObjIds* scObjs = check_var_src ? scannedObjsRev : scannedObjs; |
| U_32 ni_opcode = cgn->nInst->getOpcode(); |
| U_32 curMDNode_saved = 0; |
| |
| if (curMDNode == 0) { |
| assert(getEscState(cgn)!=ARG_ESCAPE); |
| } |
| assert(getEscState(cgn)!=GLOBAL_ESCAPE); |
| if (verboseLog) { |
| Log::out() <<"--scanAE < 1: nodeId "<<cgn->cngNodeId |
| <<" opId "<<cgn->opndId<<" state "; |
| printState(cgn); |
| Log::out() <<" " << nodeTypeToString(cgn) <<cgn->nodeType |
| <<" check_var_src " << check_var_src << std::endl; |
| } |
| if (cgn->nodeType == NT_LDVAL) { // primitive type value |
| if (verboseLog) { |
| Log::out() <<"--scanAE > 1: primitive type " << std::endl; |
| } |
| return; |
| } |
| if (scObjs->size()!=0) { |
| if (checkScanned(scObjs,cgn->cngNodeId)) { |
| if (verboseLog) { |
| Log::out() <<"--scanAE > 2: was scanned earlier " << std::endl; |
| } |
| return; |
| } |
| } |
| |
| if (cgn->nodeType == NT_ACTARG) { |
| curMDNode_saved = curMDNode; |
| } |
| |
| if (cgn->nodeMDs!=NULL && curMDNode!=0) { |
| cgn->nodeMDs->push_back(curMDNode); |
| if (verboseLog) { |
| Log::out() <<"--scanAE 1_1: nodeId "<<cgn->cngNodeId |
| <<" opId "<<cgn->opndId <<" curMDNode "<<curMDNode<< std::endl; |
| } |
| } |
| if (getEscState(cgn) > ARG_ESCAPE) { |
| if (verboseLog) { |
| Log::out() <<"--scanAE 2: nodeId "<<cgn->cngNodeId <<" opId "<<cgn->opndId<<" state "; |
| printState(cgn); |
| Log::out() <<" to arg.esc."<< std::endl; |
| } |
| setEscState(cgn,ARG_ESCAPE); |
| } |
| |
| scObjs->push_back(cgn->cngNodeId); |
| if (cgn->outEdges != NULL) { |
| bool to_check_var_src = check_var_src; |
| for (it1 = cgn->outEdges->begin( ); it1 != cgn->outEdges->end( ); it1++ ) { |
| next_node = (*it1)->cngNodeTo; |
| if (getEscState(next_node) < ARG_ESCAPE) |
| continue; |
| if (getEscState(next_node) == ARG_ESCAPE && cgn->nodeType != NT_ACTARG) |
| continue; |
| if (verboseLog) { |
| Log::out() <<"--scanAE 3 next: nodeId " <<next_node->cngNodeId<<" opId "<<next_node->opndId <<" state "; |
| printState(next_node); |
| Log::out() << " " << nodeTypeToString(next_node) << " ref.type " << next_node->nodeRefType << std::endl; |
| } |
| 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); |
| curMDNode = curMDNode_saved; |
| } |
| } |
| if (check_var_src) { |
| if (ni_opcode == Op_LdVar || ni_opcode == Op_StVar || ni_opcode ==Op_Phi) { |
| U_32 nsrc=cgn->nInst->getNumSrcOperands(); |
| for (U_32 i=0; i<nsrc; i++) { |
| next_node = findCnGNode_op(cgn->nInst->getSrc(i)->getId()); |
| if (getEscState(next_node) <= ARG_ESCAPE) |
| continue; |
| if (verboseLog) { |
| Log::out() <<"--scanAE 4 next: nodeId " |
| <<next_node->cngNodeId<<" opId "<<next_node->opndId <<" state "; |
| printState(next_node); Log::out() << std::endl; |
| } |
| scanCnGNodeRefsAE(next_node,check_var_src); |
| curMDNode = curMDNode_saved; |
| } |
| } |
| } |
| |
| if (verboseLog) { |
| Log::out() <<"--scanAE > 4: exit: nodeId "<<cgn->cngNodeId |
| <<" opId "<<cgn->opndId<<" state "; printState(cgn); |
| Log::out() <<" " << nodeTypeToString(cgn) <<cgn->nodeType |
| <<" check_var_src " << check_var_src << std::endl; |
| } |
| } // scanCnGNodeRefsAE(CnGNode* cgn, bool check_var_src) |
| |
| |
| void |
| EscAnalyzer::checkSubobjectStates(CnGNode* node) { |
| CnGRefs::iterator it; |
| CnGRefs::iterator it1; |
| CnGNode* cgn; |
| CnGNode* cgn1; |
| CnGNode* node_fld; |
| bool arge = false; |
| bool calle = false; |
| bool gle = false; |
| bool no_mod = false; |
| Inst* n_inst = node->nInst; |
| CnGNode* nt = NULL; |
| |
| if (verboseLog) { |
| Log::out() <<"--checkSOS 0: "; |
| printCnGNode(node,Log::out());Log::out() << std::endl; |
| } |
| if (node->outEdges==NULL) { |
| if (verboseLog) { |
| Log::out() <<"--checkSOS 1: return " << std::endl; |
| } |
| return; |
| } |
| |
| for (it1 = node->outEdges->begin( ); it1 != node->outEdges->end( ); it1++ ) { |
| node_fld = (*it1)->cngNodeTo; |
| if ((*it1)->edgeType != ET_FIELD) { |
| continue; |
| } |
| if (node_fld->outEdges==NULL) { |
| continue; |
| } |
| arge = false; |
| calle = false; |
| gle = false; |
| no_mod = false; |
| nt = node_fld; |
| n_inst = node_fld->nInst; |
| for (it = node_fld->outEdges->begin( ); it != node_fld->outEdges->end( ); it++ ) { |
| cgn = (*it)->cngNodeTo; |
| if (verboseLog) { |
| Log::out() <<"--checkSOS 2: "; |
| printCnGNode(cgn,Log::out());Log::out() << std::endl; |
| } |
| if (getEscState(cgn) < getEscState(node_fld)) { |
| if (getEscState(cgn)==GLOBAL_ESCAPE) { |
| gle = true; |
| break; |
| } |
| if (getEscState(cgn)==ARG_ESCAPE) { |
| arge = true; |
| continue; |
| } |
| } |
| if (getOutEscaped(node_fld) == 0 && getOutEscaped(cgn) != 0) { |
| calle = true; |
| continue; |
| } |
| no_mod = true; |
| } |
| if (verboseLog) { |
| Log::out() <<"--checkSOS 2: " << no_mod << " " << gle << " " << calle << " " << arge |
| << std::endl; |
| } |
| if (gle || calle || arge) { |
| if (node_fld->nodeType==NT_ARRELEM) { |
| if (n_inst->getOpcode() == Op_AddScaledIndex) { |
| n_inst = n_inst->getSrc(0)->getInst(); |
| nt = findCnGNode_op(n_inst->getSrc(0)->getId()); |
| if (verboseLog) { |
| Log::out() <<"--checkSOS 3: "; printCnGNode(nt,Log::out()); Log::out() << std::endl; |
| } |
| if (nt->lNode != NULL) { |
| nt = nt->lNode; |
| } |
| } |
| } |
| if (verboseLog) { |
| Log::out() <<"--checkSOS 4: found "; |
| printCnGNode(nt,Log::out());Log::out() << std::endl; |
| } |
| if (gle) { |
| initNodeType = NT_STFLD; |
| } else { |
| if (calle) { |
| initNodeType = NT_DEFARG; |
| } else { |
| initNodeType = NT_ACTARG; |
| } |
| } |
| if (node_fld->nodeType==NT_INSTFLD) { // set new state beginning with instance field |
| if (gle || calle) { |
| scanCnGNodeRefsGE(node_fld,false); |
| } else { |
| curMDNode = 0; |
| scanCnGNodeRefsAE(node_fld,false); |
| } |
| } else { // set new state beginning with array elements |
| for (it = nt->outEdges->begin( ); it != nt->outEdges->end( ); it++ ) { |
| cgn1 = (*it)->cngNodeTo; |
| if (cgn1->nodeType != NT_ARRELEM) |
| continue; |
| if (gle || calle) { |
| if (isStateNeedGEFix(getFullState(cgn1),cgn1->nodeType)) |
| scanCnGNodeRefsGE(cgn1,false); |
| } else { |
| curMDNode = 0; |
| if (getEscState(cgn1) > ARG_ESCAPE) |
| scanCnGNodeRefsAE((*it)->cngNodeTo,false); |
| } |
| } |
| } |
| } |
| } |
| } // checkSubobjectStates(CnGNode* node) |
| |
| |
| EscAnalyzer::CalleeMethodInfo* |
| EscAnalyzer::findMethodInfo(MethodDesc* mdesc,Inst* callInst) { |
| const char* ch1 = mdesc->getParentType()->getName(); |
| const char* ch2 = mdesc->getName(); |
| const char* ch3 = mdesc->getSignatureString(); |
| CalleeMethodInfo* mtdInfo = getMethodInfo(ch1,ch2,ch3); |
| if (mtdInfo == NULL) { |
| if (verboseLog) { |
| Log::out() << " = = = = = = = = To scan method " << std::endl; |
| mdesc->printFullName(Log::out()); |
| Log::out() << std::endl; |
| callInst->print(Log::out()); |
| Log::out() << std::endl; |
| } |
| if (method_ea_level < maxMethodExamLevel) { |
| scanCalleeMethod(callInst); |
| mtdInfo=getMethodInfo(ch1,ch2,ch3); |
| } |
| } |
| return mtdInfo; |
| } // findMethodInfo(MethodDesc* mdesc) |
| |
| |
| EscAnalyzer::CalleeMethodInfo* |
| EscAnalyzer::getMethodInfo(const char* ch1,const char* ch2,const char* ch3) { |
| CalleeMethodInfos::iterator it; |
| if (calleeMethodInfos==NULL) |
| return NULL; |
| for (it = calleeMethodInfos->begin( ); it != calleeMethodInfos->end( ); it++ ) { |
| const char* c1 = (*it)->methodIdent->parentName; |
| const char* c2 = (*it)->methodIdent->name; |
| const char* c3 = (*it)->methodIdent->signature; |
| if (strcmp(c1,ch1)==0 && strcmp(c2,ch2)==0 && strcmp(c3,ch3)==0) |
| return (*it); |
| } |
| return NULL; |
| } // getMethodInfo(const char* ch1,const char* ch2,const char* ch3) |
| |
| |
| void |
| EscAnalyzer::scanCalleeMethod(Inst* call) { |
| if (verboseLog) { |
| Log::out() << "=="; |
| call->print(Log::out()); |
| Log::out() << std::endl; |
| } |
| if (call == NULL) { // scanned Op_DirectCall, not scanned Op_IndirectMemoryCall |
| Log::out() << "scanMethod: NULL" << std::endl; |
| return; |
| } |
| |
| MethodDesc* methodDesc = call->asMethodCallInst()->getMethodDesc(); |
| |
| if (verboseLog) { |
| Log::out() << std::endl; Log::out() << "scanMethod: "; logMethod(methodDesc); |
| } |
| |
| OpndManager& _opndManager(irManager.getOpndManager()); |
| Opnd *returnOpnd = 0; |
| if(call->getDst()->isNull()) |
| returnOpnd = _opndManager.getNullOpnd(); |
| else |
| returnOpnd = _opndManager.createSsaTmpOpnd(call->getDst()->getType()); |
| |
| IRManager* inlinedIRM = new (eaMemManager) IRManager(irManager.getMemoryManager(), irManager, *methodDesc, returnOpnd); |
| CompilationInterface& ci= inlinedIRM->getCompilationInterface(); |
| bool cibcmap = ci.isBCMapInfoRequired(); |
| if (cibcmap) { |
| ci.setBCMapInfoRequired(false); |
| } |
| |
| { |
| CompilationContext inlineCC(irManager.getMemoryManager(), &ci, irManager.getCurrentJITContext()); |
| inlineCC.setPipeline(irManager.getCompilationContext()->getPipeline()); |
| inlineCC.setHIRManager(inlinedIRM); |
| runTranslatorSession(inlineCC); |
| } |
| |
| optimizeTranslatedCode(*inlinedIRM); |
| |
| EscAnalyzer ea1(this, *inlinedIRM); |
| ea1.doAnalysis(); |
| |
| if (cibcmap) { |
| ci.setBCMapInfoRequired(true); |
| } |
| } // scanCalleeMethod(Inst* call) |
| |
| |
| void EscAnalyzer::runTranslatorSession(CompilationContext& inlineCC) { |
| TranslatorSession* traSession = (TranslatorSession*)translatorAction->createSession(inlineCC.getCompilationLevelMemoryManager()); |
| traSession->setCompilationContext(&inlineCC); |
| inlineCC.setCurrentSessionAction(traSession); |
| traSession->run(); |
| inlineCC.setCurrentSessionAction(NULL); |
| } |
| |
| |
| void |
| EscAnalyzer::optimizeTranslatedCode(IRManager& irm) { |
| // run ssa pass |
| OptPass::computeDominators(irm); |
| DominatorTree* dominatorTree = irm.getDominatorTree(); |
| ControlFlowGraph& flowGraph = irm.getFlowGraph(); |
| |
| DomFrontier frontier(irm.getNestedMemoryManager(),*dominatorTree,&flowGraph); |
| SSABuilder ssaBuilder(irm.getOpndManager(),irm.getInstFactory(),frontier,&flowGraph, |
| irm.getOptimizerFlags()); |
| ssaBuilder.convertSSA(irm.getMethodDesc()); |
| irm.setInSsa(true); |
| irm.setSsaUpdated(); |
| |
| // run devirt pass |
| // Devirtualizer pass(irm); |
| // pass.guardCallsInRegion(irm, dominatorTree); |
| |
| } // optimizeTranslatedCode(IRManager& irManager) |
| |
| |
| void |
| EscAnalyzer::saveScannedMethodInfo() { |
| CnGNodes::iterator it; |
| MethodDesc* mdesc = &irManager.getMethodDesc(); |
| MemoryManager& globalMM = irManager.getCurrentJITContext()->getGlobalMemoryManager(); |
| const char* ch1 = mdesc->getParentType()->getName(); |
| const char* ch2 = mdesc->getName(); |
| const char* ch3 = mdesc->getSignatureString(); |
| if (calleeMethodInfos==NULL) { |
| calleeMethodInfosLock.lock(); |
| if (calleeMethodInfos==NULL) |
| calleeMethodInfos = new (globalMM) CalleeMethodInfos(globalMM); |
| calleeMethodInfosLock.unlock(); |
| } else { |
| CalleeMethodInfo* mtdInfo = getMethodInfo(ch1,ch2,ch3); |
| if (mtdInfo!=NULL) |
| return; // already saved for global analyzed method |
| } |
| if (getMethodInfo(ch1,ch2,ch3)!=NULL) // info was saved by another jit |
| return; |
| calleeMethodInfosLock.lock(); // Lock to save method info in common memory |
| |
| if (getMethodInfo(ch1,ch2,ch3)!=NULL) { // already saved by another jit |
| calleeMethodInfosLock.unlock(); // Unlock |
| return; |
| } |
| |
| CalleeMethodInfo* minfo = new (globalMM) CalleeMethodInfo; |
| char* mpname=new (globalMM) char[strlen(ch1)+1]; |
| strcpy(mpname,ch1); |
| char* mname=new (globalMM) char[strlen(ch2)+1]; |
| strcpy(mname,ch2); |
| char* msig=new (globalMM) char[strlen(ch3)+1]; |
| strcpy(msig,ch3); |
| MemberIdent* mident = new (globalMM) MemberIdent; |
| mident->parentName=mpname; |
| mident->name=mname; |
| mident->signature=msig; |
| minfo->methodIdent=mident; |
| U_32 numpar = mdesc->getNumParams(); |
| minfo->numberOfArgs=numpar; |
| ParamInfos* prminfos = new (globalMM) ParamInfos(globalMM); |
| minfo->paramInfos=prminfos; |
| minfo->retValueState=0; |
| if (mdesc->getReturnType()->isReference()) { |
| U_32 escstate = 0; |
| for (it = cngNodes->begin( ); it != cngNodes->end( ); it++) { |
| if ((*it)->nodeType==NT_EXITVAL) { |
| if (isGlobalState(getFullState((*it)->outEdges->front()->cngNodeTo))) { |
| escstate = GLOBAL_ESCAPE; |
| break; |
| } |
| } |
| } |
| if (escstate == 0) { |
| escstate = OUT_ESCAPED|NO_ESCAPE; |
| } |
| minfo->retValueState=escstate; |
| } |
| bool pmt = checkMonitorsOnThis(); |
| minfo->mon_on_this = pmt; |
| for (it = cngNodes->begin( ); it != cngNodes->end( ); it++) { |
| if ((*it)->nodeType==NT_DEFARG) { |
| ParamInfo* prminfo = new (globalMM) ParamInfo; |
| prminfo->state=getFullState(*it); |
| prminfo->paramNumber=(*it)->argNumber; |
| prminfos->push_back(prminfo); |
| } |
| } |
| calleeMethodInfos->push_back(minfo); |
| calleeMethodInfosLock.unlock(); // Unlock |
| |
| if (verboseLog) { |
| ParamInfos::iterator it2; |
| Log::out() << "==== ===== calleeMethodInfo " << std::endl; |
| Log::out() << minfo->methodIdent->parentName << " "; |
| Log::out() << minfo->methodIdent->name << " "; |
| Log::out() << minfo->methodIdent->signature << " "; |
| Log::out() << minfo->numberOfArgs<< " " << std::endl; |
| for (it2 = minfo->paramInfos->begin( ); it2 != minfo->paramInfos->end( ); it2++) { |
| Log::out() << (*it2)->paramNumber << " st." |
| << (*it2)->state << std::endl; |
| } |
| Log::out() << "==== end ===== calleeMethodInfo " << std::endl; |
| } |
| } // saveScannedMethodInfo(MemoryManager& mm) |
| |
| |
| U_32 |
| EscAnalyzer::getMethodParamState(CalleeMethodInfo* mi, U_32 np) { |
| ParamInfos::iterator it; |
| U_32 st = 0; |
| if (mi==NULL) |
| return 0; |
| for (it = mi->paramInfos->begin( ); it != mi->paramInfos->end( ); it++) { |
| if ((*it)->paramNumber == np) { |
| st = (*it)->state; |
| return st; |
| } |
| } |
| return st; |
| } // getMethodParamState(CalleeMethodInfo* mi, U_32 np) |
| |
| |
| void |
| EscAnalyzer::markNotEscInsts() { |
| CnGNodes::iterator it; |
| bool p2 = false; |
| StlMap<U_32, U_32> nonEscInsts(eaMemManager); |
| typedef ::std::pair <U_32,U_32> intPair; |
| |
| for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { |
| if ((*it)->nodeType == NT_OBJECT && getEscState(*it) > GLOBAL_ESCAPE && getVirtualCall(*it) == 0 |
| && getOutEscaped(*it) == 0) { |
| nonEscInsts.insert(intPair((*it)->instrId,getFullState(*it))); |
| } |
| } |
| if (p2 && Log::isEnabled()) { |
| Log::out() << "================ > "; |
| irManager.getMethodDesc().printFullName(Log::out()); |
| Log::out() << std::endl; |
| } |
| } // markNotEscInsts() |
| |
| |
| void |
| EscAnalyzer::eaFixupVars(IRManager& irm) { |
| OptPass::computeDominators(irm); |
| DominatorTree* dominatorTree = irm.getDominatorTree(); |
| ControlFlowGraph& flowGraph = irm.getFlowGraph(); |
| |
| DomFrontier frontier(irm.getNestedMemoryManager(),*dominatorTree,&flowGraph); |
| SSABuilder ssaBuilder(irm.getOpndManager(),irm.getInstFactory(),frontier,&flowGraph, irm.getOptimizerFlags()); |
| bool phiInserted = ssaBuilder.fixupVars(&irm.getFlowGraph(), irm.getMethodDesc()); |
| irm.setInSsa(true); |
| if (phiInserted) |
| irm.setSsaUpdated(); |
| } |
| |
| |
| void |
| EscAnalyzer::printCnGNodes(const char* text,::std::ostream& os) { |
| CnGNodes::const_iterator it; |
| std::string t1; |
| std::string t2; |
| os << " "<< text << std::endl; |
| for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { |
| os <<" "; |
| printCnGNode(*it,os); |
| os << std::endl; |
| os << " "; |
| if ((*it)->nodeType & (NT_OBJS|NT_EXITVAL|NT_LDVAL)) { //node of created or exit object |
| ((Opnd*)(*it)->refObj)->printWithType(os); |
| } |
| if ((*it)->nodeType == NT_RETVAL) { |
| os << std::endl; os << " "; |
| Inst* inst = ((Opnd*)(*it)->refObj)->getInst(); |
| inst->print(os); |
| if (inst->getOpcode()==Op_IndirectMemoryCall) { |
| os << std::endl; os << " "; |
| printCallMethodName(inst, os); |
| } |
| } |
| if ((*it)->nodeType & NT_ACTARG) { //node of actual method parameter |
| ((MethodPtrType*)(*it)->refObj)->print(os); |
| os << std::endl; |
| } |
| if ((*it)->nodeType & NT_STFLD) { //field node |
| Inst* inst = (Inst*)(*it)->refObj; |
| inst->print(os); |
| } |
| os << std::endl; |
| } |
| } // printCnGNodes(char* text,::std::ostream& os) |
| |
| |
| void |
| EscAnalyzer::printCnGNode(CnGNode* cgn,::std::ostream& os) { |
| std::string t2; |
| |
| os << "nodeId "<<cgn->cngNodeId<<" "; |
| if (cgn->nodeType & (NT_OBJS|NT_LDVAL)) { //node of object created in the method |
| os << "opId "<<cgn->opndId<<" "; |
| } else { |
| if (cgn->nodeType & NT_ACTARG) { //node of actual method parameter |
| os << "nArg "<<cgn->argNumber<<" "; |
| os << "method "; |
| ((MethodPtrType*)cgn->refObj)->print(os); |
| } |
| } |
| if (cgn->nodeType==NT_DEFARG) |
| os << " nArg "<<cgn->argNumber<<" "; //Arg number for defarg |
| os << " inst "<<cgn->instrId<<" ("<<nodeTypeToString(cgn)<<cgn->nodeType<<", "; |
| switch (cgn->nodeRefType) { |
| case NR_PRIM : t2="Prim-"; break; |
| case NR_REF : t2="Ref -"; break; |
| case NR_ARR : t2="Arr -"; break; |
| case NR_REFARR : t2="RArr-"; break; |
| default : t2=" -"; |
| } |
| os <<t2<<cgn->nodeRefType<<") "; |
| if (cgn->lNode) { |
| os << "( " << cgn->lNode->cngNodeId << "-" << cgn->lNode->opndId << " ) "; |
| } |
| os << "st. "; |
| printState(cgn,os); os << " "; |
| } // printCnGNode(CnGNode* cgn,::std::ostream& os) |
| |
| |
| std::string |
| EscAnalyzer::nodeTypeToString(CnGNode* cgn) { |
| std::string t1; |
| switch (cgn->nodeType) { |
| case NT_OBJECT : t1="Obj -"; break; |
| case NT_DEFARG : t1="DArg-"; break; |
| case NT_RETVAL : t1="RVal-"; break; |
| case NT_CATCHVAL: t1="CVal-"; break; |
| case NT_STFLD : t1="SFld-"; break; |
| case NT_INSTFLD : t1="IFld-"; break; |
| case NT_LDOBJ : t1="LObj-"; break; |
| case NT_INTPTR : t1="IPtr-"; break; |
| case NT_VARVAL : t1="VVal-"; break; |
| case NT_ARRELEM : t1="ArEl-"; break; |
| case NT_REF : t1="REF -"; break; |
| case NT_ACTARG : t1="AArg-"; break; |
| case NT_EXITVAL : t1="EVal-"; break; |
| case NT_THRVAL : t1="TVal-"; break; |
| case NT_LDVAL : t1="LVal-"; break; |
| default : t1=" -"; |
| } |
| return t1; |
| } // nodeTypeToString(CnGNode* cgn) |
| |
| |
| void |
| EscAnalyzer::printCnGEdges(const char* text,::std::ostream& os) { |
| CnGEdges* cge = cngEdges; |
| CnGEdges::iterator it; |
| CnGRefs::iterator it1; |
| os << " "<< text << std::endl; |
| if (cge==NULL) { |
| os <<" NULL"<< std::endl; |
| return; |
| } |
| for (it = cge->begin( ); it != cge->end( ); it++ ) { |
| os << " from "; |
| printCnGNode((*it)->cngNodeFrom,os); |
| os << " to " << std::endl; |
| for (it1 = (*it)->refList->begin( ); it1 != (*it)->refList->end( ); it1++ ) { |
| os << " "; |
| os <<(*it1)->cngNodeTo->cngNodeId<<" ("; |
| os <<edgeTypeToString(*it1)<<(*it1)->edgeType<<"), "; |
| printCnGNode(findCnGNode_id((*it1)->cngNodeTo->cngNodeId),os); |
| os << std::endl; |
| } |
| } |
| } // printCnGEdges(char* text,::std::ostream& os) |
| |
| |
| std::string |
| EscAnalyzer::edgeTypeToString(CnGRef* edr) { |
| std::string t1; |
| switch (edr->edgeType) { |
| case ET_POINT : t1="poi-"; break; |
| case ET_DEFER : t1="ref-"; break; |
| case ET_FIELD : t1="fld-"; break; |
| default : t1=" -"; |
| } |
| return t1; |
| } // edgeTypeToString(CnGRef* edr) |
| |
| |
| void |
| EscAnalyzer::printRefInfo(::std::ostream& os) { |
| CnGNodes::iterator it; |
| os << "================ Static Fields" << std::endl; |
| for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { |
| if ((*it)->nodeType==NT_STFLD) { |
| printCnGNodeRefs(*it, "", os); |
| } |
| } |
| scannedObjs->clear(); |
| os << "================ Method Agruments" << std::endl; |
| for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { |
| if ((*it)->nodeType==NT_ACTARG) { |
| printCnGNodeRefs(*it, "", os); |
| } |
| } |
| scannedObjs->clear(); |
| os << "================ Return Values" << std::endl; |
| for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { |
| if ((*it)->nodeType==NT_EXITVAL) { |
| printCnGNodeRefs(*it, "", os); |
| } |
| } |
| scannedObjs->clear(); |
| os << "================ Thrown Values" << std::endl; |
| for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { |
| if ((*it)->nodeType==NT_THRVAL) { |
| printCnGNodeRefs(*it, "", os); |
| } |
| } |
| scannedObjs->clear(); |
| os << "================ Instsnce Fields" << std::endl; |
| for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { |
| if ((*it)->nodeType==NT_INSTFLD) { |
| printCnGNodeRefs(*it, "", os); |
| } |
| } |
| scannedObjs->clear(); |
| } // printRefInfo(::std::ostream& os) |
| |
| |
| void |
| EscAnalyzer::printCnGNodeRefs(CnGNode* cgn, std::string text,::std::ostream& os) { |
| CnGNode* node; |
| CnGRefs::iterator it1; |
| Inst* inst; |
| os << text; |
| if (scannedObjs->size()!=0) { |
| if (checkScannedObjs(cgn->cngNodeId)) { |
| os << "nodeId " << cgn->cngNodeId << " . . . " << std::endl; |
| return; |
| } |
| } |
| printCnGNode(cgn,os); |
| os << std::endl; |
| os << text; cgn->nInst->print(os); os << std::endl; |
| scannedObjs->push_back(cgn->cngNodeId); |
| if (cgn->outEdges != NULL) { |
| for (it1 = cgn->outEdges->begin( ); it1 != cgn->outEdges->end( ); it1++ ) { |
| os << text << edgeTypeToString(*it1) << std::endl; |
| if ((node=findCnGNode_id((*it1)->cngNodeTo->cngNodeId))!=NULL) |
| printCnGNodeRefs(node,text+" ",os); |
| } |
| } |
| scannedObjs->pop_back(); |
| if (cgn->nodeType==NT_RETVAL) { |
| inst = cgn->nInst; |
| if (inst->getOpcode()==Op_IndirectMemoryCall) { |
| os << text << " "; |
| printCallMethodName(inst, os); |
| os << std::endl; |
| } |
| } |
| if (cgn->nodeType==NT_LDOBJ && getEscState(cgn)!=GLOBAL_ESCAPE) { |
| inst = cgn->nInst; |
| lObjectHistory(inst,text,os); |
| scannedInsts->clear(); |
| } |
| } // printCnGNodeRefs(CnGNode* cgn, std::string text,::std::ostream& os) |
| |
| |
| void |
| EscAnalyzer::printCallMethodName(Inst* inst, ::std::ostream& os) { |
| assert(inst); |
| Opnd* zeroOpnd = inst->getSrc(0); |
| Inst* srcInst = zeroOpnd->getInst(); |
| if (srcInst->getOpcode()== Op_LdVar) { |
| MethodDesc* md = zeroOpnd->getType()->asMethodPtrType()->getMethodDesc(); |
| md->printFullName(os); |
| } else if (inst->isMethod()) { |
| MethodDesc* md = inst->asMethodInst()->getMethodDesc(); |
| md->printFullName(os); |
| } else if (srcInst->isMethod()) { |
| // Op_TauLdVirtFunAddrSlot |
| MethodDesc* md = srcInst->asMethodInst()->getMethodDesc(); |
| md->printFullName(os); |
| } else if (srcInst->isVMHelperCallInst()) { |
| // A dst operand from VMHelperCallInst might also be srcInst for |
| // IndirectMemoryCall (for example, lazy resolution helper). |
| // There is no MethodDesc to print for such calls. |
| os << "some vmhelper"; |
| } else { |
| assert(0); |
| } |
| os << std::endl; |
| } // printCallMethodName(Inst* inst, std::string text,::std::ostream& os) |
| |
| void |
| EscAnalyzer::lObjectHistory(Inst* inst,std::string text,::std::ostream& os) { |
| Inst* inst1; |
| U_32 nsrc=inst->getNumSrcOperands(); |
| |
| if (scannedInsts->size()!=0) { |
| if (checkScannedInsts(inst->getId())) { |
| os << text << "instId " << inst->getId() << " . . . " << std::endl; |
| return; |
| } |
| } |
| os << text; inst->print(os); os << std::endl; |
| if (inst->getOpcode()==Op_DirectCall || inst->getOpcode()==Op_IndirectMemoryCall) { |
| Opnd *returnOpnd = inst->getDst(); |
| if (returnOpnd != NULL) { |
| CnGNode* n = findCnGNode_op(returnOpnd->getId()); |
| if (n != NULL) { |
| os<< text << " "; printCnGNode(n,os); os<< std::endl; |
| } |
| } |
| if (inst->getOpcode()==Op_IndirectMemoryCall) { |
| os << text << " "; |
| printCallMethodName(inst, os); |
| os << std::endl; |
| } |
| return; |
| } |
| scannedInsts->push_back(inst->getId()); |
| for (U_32 i=0; i<nsrc; i++) { |
| inst1 = inst->getSrc(i)->getInst(); |
| if (!(Type::isTau(inst->getSrc(i)->getType()->tag))) |
| lObjectHistory(inst1,text+" ",os); |
| } |
| } // lObjectHistory(Inst* inst,std::string text,::std::ostream& os) |
| |
| |
| void |
| EscAnalyzer::printCreatedObjectsInfo(::std::ostream& os) { |
| CnGNodes::iterator it; |
| NodeMDs::iterator it1; |
| os << "================ Created Object States < "; |
| irManager.getMethodDesc().printFullName(os); |
| os << std::endl; |
| for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { |
| U_32 nt = (*it)->nodeType; |
| if (nt&(NT_OBJECT|NT_RETVAL) || nt==NT_LDOBJ) { |
| printCnGNode(*it,os); |
| ((Opnd*)(*it)->refObj)->printWithType(os); |
| if (getEscState(*it)==ARG_ESCAPE) { |
| for (it1 = (*it)->nodeMDs->begin(); it1 != (*it)->nodeMDs->end(); it1++) { |
| CnGNode* n=findCnGNode_id(*it1); |
| assert(n!=NULL); |
| os << std::endl; os <<" "; |
| printCnGNode(n,os); |
| os << std::endl; os <<" "; |
| ((MethodPtrType*)n->refObj)->print(os); |
| } |
| } |
| os << std::endl; |
| os << " =="; ((Opnd*)(*it)->refObj)->getInst()->print(os); |
| os << std::endl; |
| } |
| } |
| os << "================ > " ; |
| irManager.getMethodDesc().printFullName(os); |
| os << std::endl; |
| } // printCreatedObjectsInfo(::std::ostream& os) |
| |
| |
| void |
| EscAnalyzer::createdObjectInfo() { |
| CnGNodes::iterator it; |
| int n0 = 0; |
| int n_ge = 0; |
| int n_ae = 0; |
| int n_ne = 0; |
| U_32 state = 0; |
| |
| for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { |
| if ((*it)->nodeType == NT_OBJECT) { |
| n0++; |
| state = getEscState(*it); |
| if (state == GLOBAL_ESCAPE) |
| n_ge++; |
| if (state == ARG_ESCAPE) |
| n_ae++; |
| if (state == NO_ESCAPE) |
| n_ne++; |
| } |
| } |
| if (verboseLog) { |
| Log::out() << "************** Created object info: "; |
| mh.printFullName(Log::out()); |
| Log::out() << std::endl; |
| Log::out() << " Number of created objects: " << n0 << std::endl; |
| if (n0>0) { |
| Log::out() << " Global escaped objects: " << n_ge << std::endl; |
| Log::out() << " Arg. escaped objects: " << n_ae << std::endl; |
| Log::out() << " Non escaped objects: " << n_ne << std::endl; |
| } |
| Log::out() << "************** " << std::endl; |
| } |
| |
| comObjStat._n0+=n0; |
| comObjStat._n_ge+=n_ge; |
| comObjStat._n_ae+=n_ae; |
| comObjStat._n_ne+=n_ne; |
| |
| if (verboseLog) { |
| Log::out() << "************** Common created object info " << std::endl; |
| Log::out() << " Number of created objects: " << comObjStat._n0 << std::endl; |
| Log::out() << " Global escaped objects: " << comObjStat._n_ge << std::endl; |
| Log::out() << " Arg. escaped objects: " << comObjStat._n_ae << std::endl; |
| Log::out() << " Non escaped objects: " << comObjStat._n_ne << std::endl; |
| Log::out() << " Objects in loop: " << comObjStat._n_lo << std::endl; |
| Log::out() << "************** " << std::endl; |
| } |
| } // createdObjectInfo() |
| |
| |
| void |
| EscAnalyzer::printOriginObjects(Inst* inst, bool all, std::string text) { |
| Inst* inst1 = NULL; |
| U_32 nsrc=inst->getNumSrcOperands(); |
| |
| if (scannedObjs->size()!=0) { |
| if (checkScannedObjs(inst->getId())) { |
| if (verboseLog) { |
| Log::out() << "instId " << inst->getId() << " . . . " << std::endl; |
| } |
| return; |
| } |
| } |
| if (verboseLog) { |
| Log::out() << text; |
| inst->print(Log::out()); |
| Log::out() << std::endl; |
| } |
| if (inst->getOpcode()==Op_DirectCall || inst->getOpcode()==Op_IndirectMemoryCall) { |
| Opnd *returnOpnd = inst->getDst(); |
| if (returnOpnd != NULL) { |
| CnGNode* n = findCnGNode_op(returnOpnd->getId()); |
| if (n != NULL) { |
| if (verboseLog) { |
| Log::out()<< text << " "; |
| printCnGNode(n,Log::out()); |
| Log::out()<< std::endl; |
| } |
| } |
| } |
| if (inst->getOpcode()==Op_IndirectMemoryCall) { |
| if (verboseLog) { |
| Log::out() << text << " "; |
| printCallMethodName(inst, Log::out()); |
| Log::out() << std::endl; |
| } |
| } |
| return; |
| } |
| if (inst->getOpcode()==Op_TauLdInd || inst->getOpcode()==Op_LdVar) { // ldind,ldvar |
| Opnd *dst = inst->getDst(); |
| CnGNode* n = findCnGNode_op(dst->getId()); |
| if (n != NULL) { |
| if (verboseLog) { |
| Log::out()<< text << " "; |
| printCnGNode(n,Log::out()); |
| Log::out()<< std::endl; |
| } |
| } |
| } |
| switch (inst->getOpcode()) { |
| case Op_LdRef: // ldref |
| case Op_NewObj: // newobj |
| case Op_NewArray: // newarray |
| case Op_NewMultiArray: // newmultiarray |
| case Op_DefArg: // defarg |
| { |
| CnGNode* n = findCnGNode_in(inst->getId()); |
| if (n != NULL) { |
| if (verboseLog) { |
| Log::out() << text << " "; |
| printCnGNode(n,Log::out() ); |
| Log::out() << std::endl; |
| } |
| } |
| break; |
| } |
| default: |
| break; |
| } |
| scannedObjs->push_back(inst->getId()); |
| if (all) { |
| for (U_32 i=0; i<nsrc; i++) { |
| inst1 = inst->getSrc(i)->getInst(); |
| printOriginObjects(inst1,true,text+" "); |
| } |
| } else { |
| switch (inst->getOpcode()) { |
| case Op_TauLdInd: // ldind |
| case Op_AddScaledIndex: // addindex |
| inst1 = inst->getSrc(0)->getInst(); |
| printOriginObjects(inst1,false,text+" "); |
| break; |
| case Op_TauStInd: // stind |
| for (U_32 i=0; i<2; i++) { |
| inst1 = inst->getSrc(i)->getInst(); |
| printOriginObjects(inst1,false,text+" "); |
| } |
| break; |
| default: |
| for (U_32 i=0; i<nsrc; i++) { |
| inst1 = inst->getSrc(i)->getInst(); |
| printOriginObjects(inst1,false,text+" "); |
| } |
| } |
| } |
| scannedObjs->pop_back(); |
| } // printOriginObjects(Inst* inst, bool all, std::string text) |
| |
| |
| void |
| EscAnalyzer::printMethodInfo(CalleeMethodInfo* mi) { |
| ParamInfos::iterator it2; |
| Log::out() << "==== debug ===== calleeMethodInfo " << std::endl; |
| if (mi==NULL) |
| Log::out() << " calleeMethodInfo is NULL " << std::endl; |
| else { |
| Log::out() << mi->methodIdent->parentName << " "; |
| Log::out() << mi->methodIdent->name << " "; |
| Log::out() << mi->methodIdent->signature << " "; |
| Log::out() << "Number of parameters: " << mi->numberOfArgs<< " " << std::endl; |
| for (it2 = mi->paramInfos->begin( ); it2 != mi->paramInfos->end( ); it2++) { |
| Log::out() << (*it2)->paramNumber << " st."; |
| printState((*it2)->state); |
| Log::out() << std::endl; |
| } |
| Log::out() << "Return value state: "; |
| printState(mi->retValueState); |
| Log::out() << " " << std::endl; |
| } |
| Log::out() << "==== end ===== calleeMethodInfo " << std::endl; |
| } // printMethodInfo(CalleeMethodInfo* mi) |
| |
| |
| void |
| EscAnalyzer::what_inst(Inst* inst,::std::ostream& os) { |
| if (inst->asCallInst()) |
| os << " CallInst" << std::endl; |
| if (inst->asFieldAccessInst()) { |
| os << " FieldAccessInst" << std::endl; |
| FieldAccessInst* fai=inst->asFieldAccessInst(); |
| FieldDesc* fd=fai->getFieldDesc(); |
| Type* tt=fd->getFieldType(); |
| os << " isInitOnly " << fd->isInitOnly() << std::endl; |
| os << " isVolatile " << fd->isVolatile() << std::endl; |
| os << " fldT " << tt->getName() <<" "<< tt->tag<< std::endl; |
| os << " isObject " << tt->isObject() << std::endl; |
| os << " isRef " << tt->isReference()<< std::endl; |
| if (tt->isReference()) { |
| ref_type_info(tt,os); |
| } |
| os << " getName " << fd->getName() << std::endl; |
| os << " signature " << fd->getSignatureString() << std::endl; |
| os << " parentType " << fd->getParentType()->getName() << std::endl; |
| os << " getId " << fd->getId() << std::endl; |
| os << " isPrivate " << fd->isPrivate() << std::endl; |
| os << " isStatic " << fd->isStatic() << std::endl; |
| os << " "; |
| fd->printFullName(os); |
| os << std::endl; |
| } |
| if (inst->asMethodCallInst()) |
| os << " MethodCallInst" << std::endl; |
| if (inst->asMultiSrcInst()) |
| os << " MultiSrcInst" << std::endl; |
| if (inst->asVarAccessInst()) { |
| os << " VarAccessInst" << std::endl; |
| if (inst->asVarAccessInst()->getVar()!=NULL) { |
| os << " Var: "; |
| inst->asVarAccessInst()->getVar()->print(os);os << std::endl; |
| os << " "; |
| inst->asVarAccessInst()->getVar()->printWithType(os);os<< std::endl; |
| } |
| if (inst->asVarAccessInst()->getBaseVar()!=NULL) { |
| os << " BaseVar: "; |
| inst->asVarAccessInst()->getBaseVar()->print(os);os << std::endl; |
| os << " "; |
| inst->asVarAccessInst()->getBaseVar()->printWithType(os);os << std::endl; |
| } |
| } |
| if (inst->asBranchInst()) |
| os << " BranchInst" << std::endl; |
| if (inst->asCatchLabelInst()) |
| os << " CatchLabelInst" << std::endl; |
| if (inst->asConstInst()) |
| os << " ConstInst" << std::endl; |
| if (inst->asDispatchLabelInst()) |
| os << " DispatchLabelInst" << std::endl; |
| if (inst->asLabelInst()) |
| os << " LabelInst" << std::endl; |
| if (inst->asMethodEntryInst()) |
| os << " MethodEntryInst" << std::endl; |
| if (inst->asMethodInst()) { |
| os << " MethodInst" << std::endl; |
| MethodDesc* md=inst->asMethodInst()->getMethodDesc(); |
| logMethod(md); |
| U_32 n=md->getNumParams(); |
| os << " Params " << n << std::endl; |
| for (U_32 i = 0; i < n; i++) { |
| Type* tt = md->getParamType(i); |
| os << " << "<<i<<" >> " << tt->getName() <<" "<< tt->tag<< std::endl; |
| os << " isObject " << tt->isObject(); |
| os << " isRef " << tt->isReference()<< std::endl; |
| if (tt->isReference()) { |
| ref_type_info(tt,os); |
| } |
| } |
| os << " Id " << md->getId() << std::endl; |
| os << " isPrivate " << md->isPrivate() << std::endl; |
| os << " ParentName " << md->getParentType()->getName();os << std::endl; |
| md->printFullName(os);os << std::endl; |
| } |
| if (inst->asMethodMarkerInst()) |
| os << " MethodMarkerInst" << std::endl; |
| if (inst->asPhiInst()) |
| os << " PhiInst" << std::endl; |
| if (inst->asTauPiInst()) |
| os << " TauPiInst" << std::endl; |
| if (inst->asSwitchInst()) |
| os << " SwitchInst" << std::endl; |
| if (inst->asTokenInst()) |
| os << " TokenInst" << std::endl; |
| if (inst->asTypeInst()) { |
| Type* tt = inst->asTypeInst()->getTypeInfo(); |
| os << " TypeInst" << std::endl; |
| os << " "<< tt->getName() <<" "<< tt->tag<< std::endl; |
| } |
| } // what_inst(Inst* inst,::std::ostream& os) |
| |
| |
| void |
| EscAnalyzer::ref_type_info(Type* type,::std::ostream& os) { |
| NamedType* arreltype; |
| os << " isArr " << type->isArray(); |
| if (type->asArrayType()) { |
| arreltype=type->asArrayType()->getElementType(); |
| os << " elmT " << arreltype->getName() << " " << arreltype->tag<<" "; |
| os << " isRef " << arreltype->isReference(); |
| } |
| os << " isArrElem " << type->isArrayElement()<< std::endl; |
| } // ref_type_info(Type* type,::std::ostream& os) |
| |
| |
| void |
| EscAnalyzer::debug_inst_info(Inst* inst,::std::ostream& os) { |
| Opnd* dst; |
| Opnd* src; |
| U_32 nsrc; |
| |
| os << " =="; inst->print(os); os << std::endl; |
| if (verboseLog) { |
| os << " Inst Info:" << std::endl; |
| what_inst(inst,os); |
| os << " Dst & Src Info:" << std::endl; |
| dst=inst->getDst(); |
| nsrc=inst->getNumSrcOperands(); |
| os << " "; |
| if (!dst->isNull()) |
| dst->print(os); |
| else |
| os << "dst NULL"; |
| os << " --srcnum " << nsrc << std::endl; |
| if (!dst->isNull()) { |
| os << " dst "; |
| debug_opnd_info(dst, os); |
| } else |
| os << std::endl; |
| if ( nsrc != 0 ) { |
| os << " sources" << std::endl; |
| for (U_32 i=0; i<nsrc; i++) { |
| src=inst->getSrc(i); |
| os << " <<" <<i<<">> "; |
| debug_opnd_info(src, os); |
| } |
| } |
| } |
| } // debug_inst_info(Inst* inst,::std::ostream& os) |
| |
| |
| void |
| EscAnalyzer::debug_opnd_info(Opnd* opnd,::std::ostream& os) { |
| Type* type=opnd->getType(); |
| |
| opnd->print(os); |
| os << " id. " <<opnd->getId(); |
| os << " type " << type->getName() << " " << type->tag<<" "; |
| os << " isRef " << type->isReference(); |
| os << " isObj " << type->isObject(); |
| os << " isVal " << type->isValue() << std::endl; |
| if (type->isReference()) |
| ref_type_info(type,os); |
| os << " "; |
| opnd->printWithType(os ); |
| os << std::endl; |
| os << " prop " << opnd->getProperties(); |
| os << " isVar " << opnd->isVarOpnd(); |
| os << " isSsa " << opnd->isSsaOpnd(); |
| os << " isSsaVar " << opnd->isSsaVarOpnd(); |
| os << " isSsaTmp " << opnd->isSsaTmpOpnd(); |
| os << " isPi " << opnd->isPiOpnd() << std::endl; |
| if (!opnd->isVarOpnd()) { |
| os << " "; |
| opnd->getInst()->print(os); |
| os << std::endl; |
| what_inst(opnd->getInst(),os); |
| } |
| } // debug_opnd_info(Opnd* opnd,::std::ostream& os) |
| |
| |
| |
| /* **************************************** |
| Monitors elimination optimization |
| **************************************** */ |
| |
| void |
| EscAnalyzer::addMonInst(Inst* inst) { |
| U_32 monOpndId = inst->getSrc(0)->getId(); |
| MonUnit* monUnit = NULL; |
| monUnit = findMonUnit(monOpndId); |
| if (monUnit == NULL) { |
| monUnit = new (eaMemManager) MonUnit; // new monitor unit |
| monUnit->opndId = monOpndId; |
| monUnit->monInsts = new (eaMemManager) Insts(eaMemManager); |
| monitorInstUnits->push_back(monUnit); |
| monUnit->icallInsts = NULL; |
| } |
| monUnit->monInsts->push_back(inst); |
| } // addMonInst(Inst* inst) |
| |
| |
| EscAnalyzer::MonUnit* |
| EscAnalyzer::findMonUnit(U_32 opndId) { |
| MonInstUnits::iterator it; |
| assert(monitorInstUnits != NULL); |
| for (it = monitorInstUnits->begin( ); it != monitorInstUnits->end( ); it++ ) { |
| if ((*it)->opndId == opndId) |
| return *it; |
| } |
| return NULL; |
| } |
| |
| |
| void |
| EscAnalyzer::addMonUnitVCall(MonUnit* mu, Inst* inst) { |
| if (mu->icallInsts == NULL) { |
| mu->icallInsts = new (eaMemManager) Insts(eaMemManager); |
| } |
| mu->icallInsts->push_back(inst); |
| } // addMonUnitVCall(MonUnit* mu, Inst* inst) |
| |
| |
| bool |
| EscAnalyzer::checkMonitorsOnThis() { |
| MonInstUnits::iterator it; |
| Insts::iterator it1; |
| CnGNode* node; |
| |
| if (monitorInstUnits==NULL) |
| return false; |
| for (it = monitorInstUnits->begin( ); it != monitorInstUnits->end( ); it++ ) { |
| node = findCnGNode_op((*it)->opndId); |
| |
| Inst* opndInst = node->nInst; |
| if (verboseLog) { |
| Log::out() << " checkMOT: "; |
| opndInst->print(Log::out()); |
| Log::out() << std::endl; |
| } |
| if (opndInst->getOpcode()==Op_DefArg && opndInst->getDefArgModifier()==NonNullThisArg) { |
| if (verboseLog) { |
| Log::out() << " checkMOT: " << (int)(opndInst->getDefArgModifier()) << " " |
| << (opndInst->getDefArgModifier()==DefArgNoModifier) << " " |
| << (opndInst->getDefArgModifier()==NonNullThisArg) << " " |
| << (opndInst->getDefArgModifier()==DefArgBothModifiers) << " state: "; |
| printState(node,Log::out()); |
| Log::out() << std::endl; |
| if (getEscState(node) != GLOBAL_ESCAPE) { |
| Log::out() << " defarg.ths isn't global "<< std::endl; |
| } |
| } |
| return true; |
| } |
| } |
| return false; |
| } // checkMonitorsOnThis() |
| |
| |
| void |
| EscAnalyzer::scanSyncInsts() { |
| MonInstUnits::iterator it; |
| Insts::iterator it1; |
| NodeMDs::iterator it2; |
| Insts* syncInsts; |
| Insts* vcInsts; |
| CnGNode* node; |
| U_32 checkedState = 0; |
| U_32 nState = 0; |
| bool to_fix_ssa = false; |
| BitSet fgnodes(eaMemManager,irManager.getFlowGraph().getMaxNodeId()); |
| |
| if (monitorInstUnits == NULL) |
| return; |
| |
| if (verboseLog) { |
| if (monitorInstUnits->size() > 0) { |
| Log::out() << "Synchronized units: " << monitorInstUnits->size() << std::endl; |
| } |
| } |
| for (it = monitorInstUnits->begin( ); it != monitorInstUnits->end( ); it++ ) { |
| node = findCnGNode_op((*it)->opndId); |
| checkedState = 0; |
| nState = getEscState(node); |
| if (node->nodeType == NT_OBJECT || nState == GLOBAL_ESCAPE) |
| checkedState = nState; |
| if (nState != GLOBAL_ESCAPE && (node->nodeType != NT_OBJECT)) { |
| checkedState = checkState(node->nInst,nState); |
| scannedObjs->clear(); |
| if (checkedState != nState && checkedState != 0) { |
| if (verboseLog) { |
| Log::out() <<"--scanSyncInsts 1: node " <<node->cngNodeId<<" opndId "<<node->opndId <<" state "; |
| printState(node); |
| Log::out()<<" to esc.state "<< checkedState << std::endl; |
| } |
| setEscState(node,checkedState); |
| } |
| } |
| if (verboseLog) { |
| Log::out() <<"--sync: state "; |
| Log::out() << checkedState << " "; |
| if (checkedState != nState) |
| Log::out() << "initState " << nState << " "; |
| Log::out() << node->cngNodeId << " - " << node->opndId << " "; |
| printCnGNode(node,Log::out()); |
| Log::out() << std::endl; |
| if (node->nodeMDs !=NULL) { |
| Log::out() << " Callee methods (nodeMDs): " << std::endl; |
| for (it2 = node->nodeMDs->begin(); it2 != node->nodeMDs->end(); it2++) { |
| CnGNode* n=findCnGNode_id(*it2); |
| assert(n!=NULL); |
| Log::out() << " " << n->nInst->getNode()->getId() << " "; |
| FlowGraph::printLabel(Log::out(),n->nInst->getNode()); |
| Log::out() << " "; n->nInst->print(Log::out()); |
| Log::out()<< std::endl; |
| } |
| } else { |
| Log::out() << " no Callee methods (nodeMDs) " << std::endl; |
| } |
| } |
| |
| syncInsts = (*it)->monInsts; |
| vcInsts = (*it)->icallInsts; |
| if (verboseLog) { |
| for (it1 = syncInsts->begin( ); it1 != syncInsts->end( ); it1++ ) { |
| Log::out() << " -"; |
| (*it1)->print(Log::out()); |
| Log::out() << " // node " |
| << (*it1)->getNode()->getId() << " "; |
| FlowGraph::printLabel(Log::out(),(*it1)->getNode()); |
| Log::out()<< std::endl; |
| } |
| if (vcInsts != NULL) { |
| Log::out() << " VCallee methods (icallInsts): " << std::endl; |
| for (it1 = vcInsts->begin( ); it1 != vcInsts->end( ); it1++ ) { |
| Log::out() << " node " |
| << (*it1)->getNode()->getId() << " "; |
| FlowGraph::printLabel(Log::out(),(*it1)->getNode()); |
| Log::out() << " "; |
| (*it1)->print(Log::out()); Log::out() << std::endl; |
| } |
| } else { |
| Log::out() << " no VCallee methods (icallInsts) " << std::endl; |
| } |
| } |
| if (getVirtualCall(node)!=0) { |
| if (checkedState > GLOBAL_ESCAPE && do_sync_removal_vc) { |
| U_32 bs_size = irManager.getFlowGraph().getMaxNodeId(); |
| if (fgnodes.getSetSize() < bs_size) { |
| fgnodes.resizeClear(bs_size); |
| } else { |
| fgnodes.clear(); |
| } |
| markLockedNodes(&fgnodes,syncInsts); |
| if (verboseLog) { |
| Log::out() << "=-=- vc loc.esc." << std::endl; |
| printOriginObjects(node->nInst,false); |
| scannedObjs->clear(); |
| } |
| if (node->nodeType==NT_OBJECT) { |
| if (verboseLog) { |
| Log::out() << "=-=- vc to optimize object "; |
| node->nInst->print(Log::out()); |
| Log::out() << std::endl; |
| } |
| fixMonitorInstsVCalls(*it,&fgnodes); |
| } |
| if (node->nodeType==NT_RETVAL) { |
| if (verboseLog) { |
| Log::out() << "=-=- vc to optimize retval "; |
| node->nInst->print(Log::out()); |
| Log::out() << std::endl; |
| } |
| fixMonitorInstsVCalls(*it,&fgnodes); |
| } |
| to_fix_ssa = true; |
| } else { |
| if (verboseLog && do_sync_removal_vc) { |
| Log::out() << "=-=- vc gl.esc." << std::endl; |
| printOriginObjects(node->nInst,false); |
| scannedObjs->clear(); |
| } |
| } |
| } else { |
| if (node->nodeType==NT_OBJECT && getEscState(node) != GLOBAL_ESCAPE) { |
| if (verboseLog) { |
| Log::out() << "++++ to optimize (remove) object" << std::endl; |
| } |
| removeMonitorInsts(syncInsts); |
| } |
| |
| if (node->nodeType==NT_DEFARG && getEscState(node) != GLOBAL_ESCAPE |
| && node->nInst->getDefArgModifier()==NonNullThisArg && mh.isSynchronized()) |
| { |
| if (verboseLog) { |
| Log::out() << "++++ to optimize (fix) defarg.ths" << std::endl; |
| } |
| #ifndef PLATFORM_POSIX |
| if (do_sync_removal_sm) { |
| fixSyncMethodMonitorInsts(syncInsts); |
| } |
| #endif |
| } |
| } |
| } |
| #ifndef PLATFORM_POSIX |
| if (do_sync_removal_sm) { |
| checkCallSyncMethod(); |
| } |
| #endif |
| // to fix var operand inserted by fixMonitorInstsVCalls method |
| if (to_fix_ssa) { |
| eaFixupVars(irManager); |
| } |
| return; |
| } // scanSyncInsts() |
| |
| |
| void |
| EscAnalyzer::markLockedNodes(BitSet* bs, Insts* syncInsts) { |
| Insts::iterator si_i; |
| Opnd* mop = NULL; |
| Inst* inst = NULL; |
| Node* n = NULL; |
| if (syncInsts == NULL) { |
| return; |
| } |
| scannedObjs->clear(); |
| mop = syncInsts->front()->getSrc(0); |
| for (si_i = syncInsts->begin(); si_i != syncInsts->end(); si_i++) { |
| if ((*si_i)->getOpcode() == Op_TauMonitorEnter) { //monenter |
| n = (*si_i)->getNode(); |
| bs->setBit(n->getId(),true); |
| if (verboseLog) { |
| Log::out() << "=-=-=Marked node: " << n->getId() << " "; |
| FlowGraph::printLabel(Log::out(),n); Log::out() << " "; |
| (*si_i)->print(Log::out()); Log::out() << std::endl; |
| } |
| inst = (Inst*)(n->getLastInst()); |
| assert(inst!=NULL); |
| if (inst->getOpcode() == Op_TauMonitorExit) { |
| continue; |
| } |
| if (n->getOutDegree() != 0) { |
| markLockedNodes2(n, bs, mop); |
| } |
| } |
| } |
| } // markLockedNodes(BitSet* bs, Insts* syncInsts) |
| |
| |
| bool |
| EscAnalyzer::markLockedNodes2(Node* node, BitSet* bs, Opnd* moninstop) { |
| const Edges& oedges = node->getOutEdges(); |
| Edges::const_iterator eit; |
| Inst* inst; |
| Node* n; |
| bool found = true; |
| |
| if (scannedObjs->size()!=0) { |
| if (checkScannedObjs(node->getId())) { |
| if (verboseLog) { |
| Log::out() << "=-=- marked node previously: " << node->getId() << " "; |
| FlowGraph::printLabel(Log::out(),node); |
| Log::out() << std::endl; |
| } |
| return found; |
| } |
| } |
| scannedObjs->push_back(node->getId()); |
| for (eit=oedges.begin(); eit!=oedges.end(); eit++) { |
| n = (*eit)->getTargetNode(); |
| bs->setBit(n->getId(),true); |
| if (verboseLog) { |
| Log::out() << "=-=- Marked node: " << n->getId() << " "; |
| FlowGraph::printLabel(Log::out(),n); |
| Log::out() << std::endl; |
| } |
| inst = (Inst*)(n->getLastInst()); |
| if (inst !=NULL) { |
| if (inst->getOpcode() == Op_TauMonitorExit) { |
| if (verboseLog) { |
| Log::out() << "=-=- Marked node: found monexit " << n->getId() << " "; |
| FlowGraph::printLabel(Log::out(),n); Log::out() << " "; |
| inst->print(Log::out()); Log::out() << std::endl; |
| } |
| continue; |
| } |
| } |
| if (n->getOutDegree() != 0) { |
| found = markLockedNodes2(n,bs,moninstop); |
| } else { |
| found = false; |
| } |
| } |
| return found; |
| } // markLockedNodes2(BitSet* bs, Insts* syncInsts) |
| |
| |
| U_32 |
| EscAnalyzer::checkState(Inst* inst,U_32 st) { |
| U_32 st1; |
| Inst* inst1; |
| Opnd* opnd1; |
| U_32 nsrc=inst->getNumSrcOperands(); |
| |
| if (st <= GLOBAL_ESCAPE) |
| return st; |
| if (scannedObjs->size()!=0) { |
| if (checkScannedObjs(inst->getId())) { |
| return st; |
| } |
| } |
| if (inst->getOpcode()==Op_DirectCall || inst->getOpcode()==Op_IndirectMemoryCall) { |
| Opnd *returnOpnd = inst->getDst(); |
| if (returnOpnd != NULL) { |
| CnGNode* n = findCnGNode_op(returnOpnd->getId()); |
| if (n != NULL) { |
| st1 = getEscState(n); |
| if (st > st1) |
| st=st1; |
| } |
| } |
| return st; |
| } |
| if (st <= GLOBAL_ESCAPE) |
| return st; |
| if (inst->getOpcode()==Op_TauLdInd || inst->getOpcode()==Op_LdVar) { // ldind, ldvar |
| Opnd *dst = inst->getDst(); |
| CnGNode* n = findCnGNode_op(dst->getId()); |
| if (n != NULL) { |
| st1 = getEscState(n); |
| if (st > st1) |
| st=st1; |
| } |
| } |
| if (st <= GLOBAL_ESCAPE) |
| return st; |
| switch (inst->getOpcode()) { |
| case Op_LdRef: // ldref |
| case Op_NewObj: // newobj |
| case Op_NewArray: // newarray |
| case Op_NewMultiArray: // newmultiarray |
| case Op_DefArg: // defarg |
| { |
| CnGNode* n = findCnGNode_in(inst->getId()); |
| if (n != NULL) { |
| st1 = getEscState(n); |
| if (st > st1) |
| st=st1; |
| } |
| break; |
| } |
| default: |
| break; |
| } |
| if (st <= GLOBAL_ESCAPE) |
| return st; |
| scannedObjs->push_back(inst->getId()); |
| for (U_32 i=0; i<nsrc; i++) { |
| opnd1 = inst->getSrc(i); |
| if (opnd1->isVarOpnd()) { |
| inst1 = opnd1->asVarOpnd()->getVarAccessInsts(); |
| } else { |
| inst1 = opnd1->getInst(); |
| } |
| st1 = checkState(inst1,st); |
| if (st > st1) |
| st=st1; |
| if (st<=GLOBAL_ESCAPE) |
| break; |
| } |
| scannedObjs->pop_back(); |
| return st; |
| } // checkState(Inst* inst,U_32 st) |
| |
| |
| void |
| EscAnalyzer::fixMonitorInstsVCalls(MonUnit* mu, BitSet* bs) { |
| Inst* opi = findCnGNode_op(mu->opndId)->nInst; |
| OpndManager& _opndManager = irManager.getOpndManager(); |
| InstFactory& _instFactory = irManager.getInstFactory(); |
| TypeManager& _typeManager = irManager.getTypeManager(); |
| Type* typeInt32 = _typeManager.getInt32Type(); |
| VarOpnd* muflag = _opndManager.createVarOpnd(typeInt32, false); |
| Inst* stvar0; // = _instFactory.makeStVar(muflag, i32_0); |
| Inst* stvar1; |
| Insts::iterator inst_it; |
| Insts* vcInsts = mu->icallInsts;; |
| Insts* syncInsts = mu->monInsts; |
| Node* oldCallNode = NULL; |
| Node* addedMonNode = NULL; |
| Node* newCallNode = NULL; |
| ControlFlowGraph& fg = irManager.getFlowGraph(); |
| |
| Node* entry_node = fg.getEntryNode(); |
| Node* muo_node = opi->getNode(); |
| |
| // values 0 and 1 to set flag variable |
| if (verboseLog) { |
| Log::out() << "=-=- w0 Before " << std::endl; |
| FlowGraph::print(Log::out(),entry_node); |
| } |
| insertLdConst(1); |
| insertLdConst(0); |
| |
| if (verboseLog) { |
| Log::out() << "=-=- w0 After " << std::endl; |
| FlowGraph::print(Log::out(),entry_node); |
| } |
| |
| // insert flag=0 before monitor instruction source opnd creation instruction |
| if (verboseLog) { |
| Log::out() << "=-=- w1 Before " << std::endl; |
| FlowGraph::print(Log::out(),muo_node); |
| } |
| stvar0 = _instFactory.makeStVar(muflag, i32_0); |
| stvar0->insertBefore(opi); |
| if (verboseLog) { |
| Log::out() << "=-=- w1 After " << std::endl; |
| FlowGraph::print(Log::out(),muo_node); |
| } |
| |
| // insert flag=1 before virtual call instructions |
| if (verboseLog) { |
| Log::out() << "=-=-=-=- Start w2" << std::endl; |
| } |
| for (inst_it = vcInsts->begin( ); inst_it != vcInsts->end( ); inst_it++ ) { |
| oldCallNode = (*inst_it)->getNode(); |
| addedMonNode = NULL; |
| newCallNode = NULL; |
| if (verboseLog) { |
| Log::out() << "=-=- w2 Before " << std::endl; |
| FlowGraph::print(Log::out(),oldCallNode); |
| if (bs->getBit(oldCallNode->getId())) { |
| Log::out() << "=-=- monenter is needed " << std::endl; |
| } else { |
| Log::out() << "=-=- monenter isn't needed " << std::endl; |
| } |
| } |
| stvar1 = _instFactory.makeStVar(muflag, i32_1); |
| stvar1->insertBefore(*inst_it); |
| if (bs->getBit((*inst_it)->getNode()->getId())) { |
| Inst* mi = syncInsts->front(); |
| Inst* ime = _instFactory.makeTauMonitorEnter(mi->getSrc(0), mi->getSrc(1)); |
| assert(mi->getBCOffset()!=ILLEGAL_BC_MAPPING_VALUE); |
| ime->setBCOffset(mi->getBCOffset()); |
| ime->insertBefore(*inst_it); |
| newCallNode = fg.splitNodeAtInstruction(ime,true,false,_instFactory.makeLabel()); |
| SsaTmpOpnd* opflag = _opndManager.createSsaTmpOpnd(typeInt32); |
| _instFactory.makeLdVar(opflag,(VarOpnd*)muflag)->insertBefore(stvar1); |
| Inst* branch_inst = _instFactory.makeBranch(Cmp_EQ, Type::Int32, |
| opflag, i32_1, (LabelInst*)(newCallNode->getFirstInst())); |
| // insert flag check |
| branch_inst->insertBefore(stvar1); |
| addedMonNode = fg.splitNodeAtInstruction(branch_inst,true, false, _instFactory.makeLabel()); |
| fg.addEdge(oldCallNode,newCallNode); |
| } |
| if (verboseLog) { |
| if (bs->getBit(oldCallNode->getId())) { |
| Log::out() << "=-=- monenter is inserted " << std::endl; |
| } |
| Log::out() << "=-=- w2 After " << std::endl; |
| FlowGraph::print(Log::out(),oldCallNode); |
| if (addedMonNode != NULL) { |
| FlowGraph::print(Log::out(),addedMonNode); |
| } |
| if (newCallNode != NULL) { |
| FlowGraph::print(Log::out(),newCallNode); |
| } |
| } |
| } |
| if (verboseLog) { |
| Log::out() << "=-=-=-=- Finish w2" << std::endl; |
| } |
| |
| insertFlagCheck(syncInsts,muflag,0); |
| |
| } // fixMonitorInstsVCalls(MonUnit* mu, BitSet* bs) |
| |
| |
| void |
| EscAnalyzer::insertFlagCheck(Insts* syncInsts, Opnd* muflag, U_32 chk) { |
| Insts::iterator inst_it; |
| OpndManager& _opndManager = irManager.getOpndManager(); |
| InstFactory& _instFactory = irManager.getInstFactory(); |
| ControlFlowGraph& fg = irManager.getFlowGraph(); |
| TypeManager& _typeManager = irManager.getTypeManager(); |
| Type* typeInt32 = _typeManager.getInt32Type(); |
| SsaTmpOpnd* chk_opnd = NULL; |
| |
| // check flag before monitor instructions |
| assert(muflag->isVarOpnd()||muflag->isSsaTmpOpnd()); |
| if (chk == 0) { |
| chk_opnd = insertLdConst(0); |
| } |
| if (chk == 1) { |
| chk_opnd = insertLdConst(1); |
| } |
| assert(chk_opnd!=NULL); |
| if (verboseLog) { |
| Log::out() << "=-=-=-=- Start w3" << std::endl; |
| } |
| for (inst_it = syncInsts->begin( ); inst_it != syncInsts->end( ); inst_it++ ) { |
| Inst* curMonInst = (*inst_it); |
| Node* oldnode = curMonInst->getNode(); |
| if (verboseLog) { |
| Log::out() << "=-=- w3 Before " << std::endl; |
| FlowGraph::print(Log::out(),oldnode); |
| } |
| Node* afterMonInstBlock = NULL; |
| Node* tiInstBlock = NULL; |
| if ((*inst_it)->getNextInst()!=NULL) { |
| // monitor inst isn'n last |
| tiInstBlock = fg.splitNodeAtInstruction(curMonInst, true, false, _instFactory.makeLabel()); |
| afterMonInstBlock = tiInstBlock; |
| } else { |
| // monitor inst is last |
| afterMonInstBlock = (Node*)(oldnode->getUnconditionalEdge()->getTargetNode()); |
| } |
| SsaTmpOpnd* i32_flag; |
| if (muflag->isVarOpnd()) { |
| i32_flag = _opndManager.createSsaTmpOpnd(typeInt32); |
| _instFactory.makeLdVar(i32_flag,(VarOpnd*)muflag)->insertBefore(curMonInst); |
| } else { |
| i32_flag = (SsaTmpOpnd*)muflag; |
| } |
| Inst* branch_inst = _instFactory.makeBranch(Cmp_EQ, Type::Int32, |
| i32_flag, chk_opnd, (LabelInst*)(afterMonInstBlock->getFirstInst())); |
| // insert flag check |
| branch_inst->insertBefore(curMonInst); |
| Node* monInstBlock = fg.splitNodeAtInstruction(branch_inst,true, false, _instFactory.makeLabel()); |
| fg.addEdge(oldnode,afterMonInstBlock); |
| if (verboseLog) { |
| Log::out() << "=-=- w3 After " << std::endl; |
| FlowGraph::print(Log::out(),oldnode); |
| FlowGraph::print(Log::out(),monInstBlock); |
| if (tiInstBlock != NULL) { |
| FlowGraph::print(Log::out(),tiInstBlock); |
| } |
| } |
| } |
| if (verboseLog) { |
| Log::out() << "=-=-=-=- Finish w3" << std::endl; |
| } |
| } // insertFlagCheck(Insts* syncInsts, Opnd* muflag, U_32 chk) |
| |
| |
| void |
| EscAnalyzer::removeMonitorInsts(Insts* syncInsts) { |
| ControlFlowGraph& fg = irManager.getFlowGraph(); |
| Insts::iterator it1; |
| Edge* excedge = NULL; |
| Node* targetnode = NULL; |
| Inst* reminst; |
| bool canthrow = false; |
| |
| for (it1 = syncInsts->begin( ); it1 != syncInsts->end( ); it1++ ) { |
| reminst = *it1; |
| if (reminst->getOperation().canThrow()==true) { |
| excedge = (Edge*)reminst->getNode()->getExceptionEdge(); |
| if (excedge != NULL) |
| targetnode = excedge->getTargetNode(); |
| else |
| targetnode = NULL; |
| } else { |
| excedge = NULL; |
| targetnode = NULL; |
| } |
| if (shortLog) { |
| canthrow = reminst->getOperation().canThrow(); |
| reminst->print(Log::out()); |
| Log::out() << " "; |
| if (verboseLog) { |
| Log::out() << std::endl; Log::out() << " canThrow "<< canthrow; Log::out() << std::endl; |
| if (excedge==NULL) { |
| Log::out() << " exception edge is NULL " << std::endl; |
| } else { |
| Log::out() << " target node is " << targetnode->getId() << std::endl; |
| } |
| if (canthrow && (excedge==NULL)) { |
| const Edges& out_edges = reminst->getNode()->getOutEdges(); |
| for (Edges::const_iterator eit = out_edges.begin(); eit != out_edges.end(); ++eit) { |
| Node* n = (*eit)->getTargetNode(); |
| Log::out() << " edge to node " << n->getId() << " kind " << (*eit)->getKind() << std::endl; |
| } |
| } |
| } |
| } |
| |
| reminst->unlink(); |
| if (shortLog) { |
| Log::out() << " unlinked: "; |
| reminst->print(Log::out()); |
| Log::out() << std::endl; |
| } |
| if (targetnode != NULL) { |
| if (targetnode->getInEdges().size() > 1) { |
| fg.removeEdge(excedge); |
| if (shortLog) { |
| Log::out() << " removed edge: " |
| << excedge->getSourceNode()->getId() << " -> " |
| << excedge->getTargetNode()->getId() << " kind " << excedge->getKind() << std::endl; |
| } |
| } else { |
| scannedObjs->clear(); |
| removeNode(targetnode); |
| scannedObjs->clear(); |
| } |
| } |
| } |
| |
| } // removeMonitorInsts(Insts* syncInsts) |
| |
| |
| void |
| EscAnalyzer::removeNode(Node* node) { |
| const Edges& out_edges = node->getOutEdges(); |
| Edges::const_iterator eit; |
| Node* n; |
| |
| if (shortLog) { |
| Log::out() << " to remove node "; FlowGraph::printLabel(Log::out(), node); Log::out() << std::endl; |
| } |
| if (scannedObjs->size()!=0) { |
| if (checkScannedObjs(node->getId())) { |
| return; |
| } |
| } |
| scannedObjs->push_back(node->getId()); |
| Nodes nodes2delete(irManager.getMemoryManager()); |
| for (eit = out_edges.begin(); eit != out_edges.end(); ++eit) { |
| n = (*eit)->getTargetNode(); |
| if (n->getInEdges().size() == 1) { |
| nodes2delete.push_back(n); |
| } |
| } |
| Nodes::iterator iter = nodes2delete.begin(), end = nodes2delete.end(); |
| for (; iter != end; ++iter) { |
| n = (*iter); |
| removeNode(n); |
| } |
| irManager.getFlowGraph().removeNode(node); |
| scannedObjs->pop_back(); |
| if (shortLog) { |
| Log::out() << " removed node "; FlowGraph::printLabel(Log::out(), node); Log::out() << std::endl; |
| } |
| } // removeNode(Node* node) |
| |
| |
| void |
| EscAnalyzer::fixSyncMethodMonitorInsts(Insts* syncInsts) { |
| SsaTmpOpnd* stThis = (SsaTmpOpnd*)insertReadJitHelperCall(); |
| insertFlagCheck(syncInsts,stThis,1); |
| } // fixSyncMethodMonitorInsts(Insts* syncInsts) |
| |
| |
| Opnd* |
| EscAnalyzer::insertReadJitHelperCall() { |
| ControlFlowGraph& fg = irManager.getFlowGraph(); |
| Node* oldBlock = fg.getEntryNode(); |
| Inst* inst_after = (Inst*)oldBlock->getFirstInst(); |
| TypeManager& _typeManager = irManager.getTypeManager(); |
| Type* typeInt32 = _typeManager.getInt32Type(); |
| OpndManager& _opndManager = irManager.getOpndManager(); |
| SsaTmpOpnd* stThis = _opndManager.createSsaTmpOpnd(typeInt32); |
| Node* newBlock = NULL; |
| |
| if (verboseLog) { |
| Log::out() << "++++ insertRJHC: before" << std::endl; |
| FlowGraph::print(Log::out(),oldBlock); |
| Log::out() << "++++ insertRJHC: before end" << std::endl; |
| } |
| // insert jit helper call |
| Opnd** args = NULL; |
| InstFactory& instfactory = irManager.getInstFactory(); |
| Inst* jhcinst = instfactory.makeJitHelperCall( |
| stThis, ReadThisState, NULL, NULL, 0, args); |
| jhcinst->insertAfter(inst_after); |
| newBlock = fg.splitNodeAtInstruction(jhcinst,true, false,instfactory.makeLabel()); |
| fg.addEdge(oldBlock,fg.getUnwindNode()); |
| insertLdConst(0); |
| if (verboseLog) { |
| Log::out() << "++++ insertRJHC: after" << std::endl; |
| FlowGraph::print(Log::out(),oldBlock); |
| FlowGraph::print(Log::out(),newBlock); |
| Log::out() << "++++ insertRJHC: after end" << std::endl; |
| } |
| insertSaveJitHelperCall((Inst*)(newBlock->getFirstInst()),i32_0); // to restore default value |
| return stThis; |
| } // insertReadJitHelperCall() |
| |
| |
| void |
| EscAnalyzer::checkCallSyncMethod() { |
| CnGNodes::iterator it; |
| CnGRefs::iterator it2; |
| |
| for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { |
| CnGNode* node = NULL; |
| CnGNode* aanode = NULL; |
| MethodPtrType* mpt = NULL; |
| CalleeMethodInfo* mtdInfo = NULL; |
| U_32 callee_state = 0; |
| |
| node = (*it); |
| if (node->nodeType == NT_ACTARG && node->argNumber == 0) { |
| mpt = (MethodPtrType*)(node->refObj); |
| if (!mpt->isUnresolvedMethodPtrType() && mpt->getMethodDesc()->isSynchronized() && node->nInst->getOpcode()==Op_DirectCall) { |
| MethodDesc* md = mpt->getMethodDesc(); |
| const char* ch1 = md->getParentType()->getName(); |
| const char* ch2 = md->getName(); |
| const char* ch3 = md->getSignatureString(); |
| mtdInfo = getMethodInfo(ch1,ch2,ch3); |
| if (mtdInfo==NULL) { |
| callee_state = 0; |
| if (verboseLog) { |
| Log::out() << "=- Methodinfo is NULL"; |
| Log::out() << std::endl; |
| } |
| } else { |
| callee_state = getMethodParamState(mtdInfo,0); |
| } |
| if (verboseLog) { |
| Log::out() << "---- checkCallSyncMethod:" << std::endl; |
| node->nInst->print(Log::out()); |
| Log::out() << std::endl; |
| printCnGNode(node,Log::out()); |
| Log::out() << std::endl; |
| if (node->outEdges != NULL) { |
| for (it2 = node->outEdges->begin(); it2 != node->outEdges->end(); it2++ ) { |
| Log::out() << " ccsm: "; |
| printState(callee_state); |
| Log::out() << " "; |
| printCnGNode((*it2)->cngNodeTo,Log::out()); |
| Log::out() << std::endl; |
| } |
| } |
| Log::out() << "++++ checkCallSyncMethod: "; |
| Log::out() << " instance: " << md->isInstance() << |
| " initializer: " << md->isInstanceInitializer() << " end" << std::endl; |
| } |
| if (callee_state == 0) |
| callee_state = GLOBAL_ESCAPE; |
| if (!isGlobalState(callee_state)) { |
| assert(node->outEdges->size()==1); |
| aanode = node->outEdges->front()->cngNodeTo; |
| if (!isGlobalState(aanode->state)&& |
| (aanode->nodeType==NT_OBJECT||aanode->nodeType==NT_RETVAL)) { |
| if (verboseLog) { |
| Log::out() << "=-=- sm this.agr.saving for "; |
| node->nInst->print(Log::out()); |
| Log::out() << std::endl; |
| } |
| insertLdConst(1); |
| insertSaveJitHelperCall(node->nInst,i32_1); |
| if (verboseLog) { |
| Log::out() << " checkCSM: this was saved" << std::endl; |
| } |
| } else { |
| if (verboseLog) { |
| Log::out() << " checkCSM: this wasn't saved" << std::endl; |
| } |
| } |
| } |
| } |
| } |
| } |
| } // checkCallSyncMethod() |
| |
| |
| void |
| EscAnalyzer::insertSaveJitHelperCall(Inst* inst_before, SsaTmpOpnd* stVal) { |
| Node* oldBlock = inst_before->getNode(); |
| ControlFlowGraph& fg = irManager.getFlowGraph(); |
| |
| Node* icBlock = stVal->getInst()->getNode(); |
| if (verboseLog) { |
| Log::out() << "++++ insertSJHC: before" << std::endl; |
| if (icBlock != oldBlock) |
| FlowGraph::print(Log::out(),icBlock); |
| FlowGraph::print(Log::out(),oldBlock); |
| Log::out() << "++++ insertSJHC: before end" << std::endl; |
| } |
| // create jit helper call |
| Opnd* args[1] = {stVal}; |
| InstFactory& instfactory = irManager.getInstFactory(); |
| Inst* jhcinst = instfactory.makeJitHelperCall( |
| OpndManager::getNullOpnd(), SaveThisState, NULL, NULL, 1, args); |
| // insert jit helper |
| if (inst_before->getNode()->getFirstInst() == inst_before) { |
| jhcinst->insertAfter(inst_before); |
| } else { |
| jhcinst->insertBefore(inst_before); |
| } |
| UNUSED Node* newBlock = fg.splitNodeAtInstruction(jhcinst, true, false, instfactory.makeLabel()); |
| // add dispatch edge to oldBlock |
| fg.addEdge(oldBlock,fg.getUnwindNode()); |
| if (verboseLog) { |
| Log::out() << "++++ insertSJHC: after" << std::endl; |
| if (icBlock != oldBlock) { |
| FlowGraph::print(Log::out(),icBlock); |
| } |
| FlowGraph::print(Log::out(),oldBlock); |
| FlowGraph::print(Log::out(),newBlock); |
| Log::out() << "++++ insertSJHC: after end" << std::endl; |
| } |
| } // insertSaveJitHelperCall(Inst* inst_before, SsaTmpOpnd* stVal) |
| |
| |
| SsaTmpOpnd* |
| EscAnalyzer::insertLdConst(U_32 value) { |
| TypeManager& _typeManager = irManager.getTypeManager(); |
| Type* typeInt32 = _typeManager.getInt32Type(); |
| OpndManager& _opndManager = irManager.getOpndManager(); |
| InstFactory& _instFactory = irManager.getInstFactory(); |
| Inst* ildc = NULL; |
| if (value == 0) |
| if (i32_0 == NULL) { |
| i32_0 = _opndManager.createSsaTmpOpnd(typeInt32); |
| ildc = _instFactory.makeLdConst(i32_0, 0); |
| } |
| if (value == 1) |
| if (i32_1 == NULL) { |
| i32_1 = _opndManager.createSsaTmpOpnd(typeInt32); |
| ildc = _instFactory.makeLdConst(i32_1, 1); |
| } |
| if (ildc != NULL) { |
| ildc->insertAfter(irManager.getFlowGraph().getEntryNode()->getFirstInst()); |
| } |
| if (value == 0) |
| return i32_0; |
| return i32_1; |
| } // insertLdConst(U_32 value) |
| |
| |
| |
| /* **************************************** |
| Scalar replacement optimization |
| **************************************** */ |
| |
| void |
| EscAnalyzer::scanLocalObjects() { |
| CnGNodes::iterator it; |
| U_32 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++ ) { |
| CnGNode* cgNode = *it; |
| if (cgNode->nodeType == NT_OBJECT && getEscState(cgNode)==NO_ESCAPE |
| && getOutEscaped(cgNode) == 0 && !(cgNode->nInst->getOpcode()==Op_LdRef)) { |
| if (prTitle) { |
| if (verboseLog) { |
| os_sc << "================ Local Object States < "; |
| irManager.getMethodDesc().printFullName(os_sc); |
| os_sc << std::endl; |
| } |
| prTitle = false; |
| } |
| lo_count++; // number of local objects |
| stnode = checkCnGtoScalarize(cgNode,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 (verboseLog) { |
| 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 (verboseLog) { |
| os_sc << "CFGOpnds: " << irManager.getOpndManager().getNumSsaOpnds() << " CnGNodes: " |
| << cngNodes->size() << " Local Objects: " << lo_count << std::endl; |
| } |
| if (lnoids != NULL || lloids != NULL) { |
| if (verboseLog) { |
| 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 (verboseLog) { |
| 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 (verboseLog) { |
| os_sc << "lnoids size: 0" << std::endl; |
| } |
| } |
| } |
| if (lloids != NULL) { |
| if (lloids->size()>0) { |
| doopt = true; |
| if (verboseLog) { |
| 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 (verboseLog) { |
| os_sc << "lloids size: 0" << std::endl; |
| } |
| } |
| } |
| if (doopt && do_scalar_repl) { |
| if (lnoids != NULL) { |
| doLOScalarReplacement(lnoids); |
| } |
| if (lloids != NULL) { |
| doLOScalarReplacement(lloids); |
| } |
| } } |
| if (verboseLog) { |
| os_sc << "================ > " ; |
| irManager.getMethodDesc().printFullName(os_sc); |
| os_sc << std::endl; |
| } |
| } // scanLocalObjects() |
| |
| |
| void |
| EscAnalyzer::scanEscapedObjects() { |
| CnGNodes::iterator it; |
| U_32 vco_count=0; // number of local objects |
| U_32 ob_ref_type=0; // object ref type |
| ObjIds* lnoids = NULL; // list of CnG node Ids for new opnds to optimize |
| ObjIds* lloids = NULL; // list of CnG node Ids for load opnds to optimize |
| ObjIds::iterator lo_it; |
| bool prTitle = true; |
| CnGNode* stnode = NULL; |
| |
| for (it = cngNodes->begin( ); it != cngNodes->end( ); it++ ) { |
| // if ((*it)->nodeType == NT_OBJECT && getEscState(*it)!=NO_ESCAPE |
| if ((*it)->nodeType == NT_OBJECT |
| && getOutEscaped(*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 (verboseLog) { |
| os_sc << "================ Escaped Object States < "; |
| irManager.getMethodDesc().printFullName(os_sc); |
| os_sc << std::endl; |
| } |
| prTitle = false; |
| } |
| |
| stnode = checkCnGtoScalarize(*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 (verboseLog) { |
| 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 (verboseLog) { |
| 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 (verboseLog) { |
| 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 (verboseLog) { |
| 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 (verboseLog) { |
| 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 (verboseLog) { |
| os_sc << "================ > " ; |
| irManager.getMethodDesc().printFullName(os_sc); |
| os_sc << std::endl; |
| } |
| } // scanEscapedObjects() |
| |
| |
| void |
| EscAnalyzer::doLOScalarReplacement(ObjIds* loids) { |
| ObjIds::iterator lo_it; |
| CnGNode* onode; |
| 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 (verboseLog) { |
| os_sc << " - - no cng node for opId " << *lo_it << std::endl; |
| } |
| continue; |
| } |
| if (onode->nodeRefType == NR_PRIM) { |
| continue; |
| } |
| if (verboseLog) { |
| 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 (verboseLog) { |
| os_sc << " doLOSR: found object fields " << scObjFlds->size() << std::endl; |
| } |
| |
| if (onode->nodeType == NT_LDOBJ) { |
| if (verboseLog) { |
| 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; |
| } |
| Type* fl_type = NULL; |
| Type* fl_type1 = NULL; |
| Inst* ii = sco->ls_insts->front(); |
| if (ii->getOpcode()==Op_TauStInd) { |
| fl_type1 = ii->getSrc(1)->getType()->asPtrType()->getPointedToType(); |
| fl_type = ii->getSrc(0)->getType(); |
| } else { |
| fl_type1 = ii->getSrc(0)->getType()->asPtrType()->getPointedToType(); |
| fl_type = ii->getDst()->getType(); |
| } |
| VarOpnd* fl_var_opnd = _opndManager.createVarOpnd(fl_type, false); |
| SsaTmpOpnd* fl_init_opnd = _opndManager.createSsaTmpOpnd(fl_type); |
| Inst* ld_init_val_inst = NULL; |
| sco->fldVarOpnd = fl_var_opnd; |
| |
| if (verboseLog) { |
| os_sc<<" PointedType "; fl_type1->print(os_sc); os_sc <<std::endl; |
| os_sc<<" OperandType "; fl_type->print(os_sc); os_sc <<std::endl; |
| } |
| if (fl_type->isReference()) { |
| ld_init_val_inst = _instFactory.makeLdNull(fl_init_opnd); |
| } else { |
| ld_init_val_inst = _instFactory.makeLdConst(fl_init_opnd, 0); |
| } |
| |
| scalarizeOFldUsage(sco); |
| if (verboseLog) { |
| 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 (verboseLog) { |
| 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; |
| } |
| } |
| } |
| Node* no_node = onode->nInst->getNode(); |
| if (no_node != NULL) { |
| if (verboseLog) { |
| os_sc << "++++ old newobj removed: before" << std::endl; |
| FlowGraph::print(os_sc,no_node); |
| os_sc << "++++ old newobj: before end" << std::endl; |
| } |
| removeInst(onode->nInst); |
| if (verboseLog) { |
| os_sc << "++++ old newobj removed: after" << std::endl; |
| FlowGraph::print(os_sc,no_node); |
| os_sc << "++++ old newobj: after end" << std::endl; |
| } |
| } |
| } |
| } // doLOScalarReplacement(ObjIds* loids) |
| |
| |
| void |
| EscAnalyzer::doEOScalarReplacement(ObjIds* loids) { |
| ObjIds::iterator lo_it; |
| CnGNode* onode; |
| 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 (verboseLog) { |
| 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; |
| } |
| double path_prob = -1; |
| path_prob = checkLocalPath(onode->nInst); |
| if (verboseLog) { |
| os_sc<<"pp " << (path_prob )<<std::endl; |
| os_sc<<"en*m " << (entryNode_execCount*ec_mult)<<std::endl; |
| os_sc<<"pp<en*m " << (path_prob < entryNode_execCount*ec_mult)<<std::endl; |
| os_sc<<"pp==0 " << (path_prob==0)<<std::endl; |
| os_sc<<"* " << (path_prob < entryNode_execCount*ec_mult || path_prob==0)<<std::endl; |
| } |
| if (path_prob < entryNode_execCount*ec_mult || path_prob==0) { |
| if (do_scalar_repl_final_fields) { |
| checkToScalarizeFinalFiels(onode, scObjFlds); |
| } |
| continue; |
| } |
| if (verboseLog) { |
| os_sc << " - - method: "; |
| irManager.getMethodDesc().printFullName(os_sc); |
| os_sc << std::endl; |
| if (onode->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) { |
| if (verboseLog) { |
| printOriginObjects(onode->nInst,false); |
| } |
| if (onode->nInst->getOpcode() != Op_LdVar) { |
| if (verboseLog) { |
| 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 (verboseLog) { |
| os_sc << " doEO 2 "; phi->print(os_sc); |
| os_sc << std::endl; |
| } |
| continue; |
| } |
| U_32 nsrc = phi->getNumSrcOperands(); |
| if (nsrc > 2) { |
| if (verboseLog) { |
| os_sc << " doEO 3" << std::endl; |
| } |
| continue; |
| } |
| for (U_32 i=0; i<nsrc; i++) { |
| inst = phi->getSrc(i)->getInst(); |
| if (verboseLog) { |
| os_sc << " doEO phi "; inst->print(os_sc); |
| os_sc << std::endl; |
| } |
| if (inst->getOpcode() != Op_StVar) { |
| break; |
| } |
| inst = inst->getSrc(0)->getInst(); |
| if (verboseLog) { |
| 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 (verboseLog) { |
| 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 (verboseLog) { |
| 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 (verboseLog) { |
| 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 (verboseLog) { |
| os_sc << " doEOSR: found object fields for newobj " << nscObjFlds->size() << std::endl; |
| } |
| if (!checkObjFlds(nscObjFlds, scObjFlds)) { |
| if (verboseLog) { |
| os_sc << " checkObjFlds failed " << std::endl; |
| } |
| continue; |
| } |
| if (verboseLog) { |
| os_sc << " checkObjFlds passed " << std::endl; |
| } |
| } |
| |
| // to collect call & callimem instructions |
| collectCallInsts(onode->cngNodeId, vc_insts, vcids); |
| |
| if (verboseLog) { |
| os_sc << " doEOSR: found object fields " << scObjFlds->size() << " vc_inst " << vc_insts->size() |
| << std::endl; |
| } |
| if (verboseLog) { |
| 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(); |
| Inst* nobj_inst = nonode->nInst; // optimized newobj inst for ldvar opnd |
| Inst* lobj_inst = NULL; // load opnd inst for ldvar opnd |
| VarOpnd* ob_var_opnd = _opndManager.createVarOpnd(nobj_inst->getDst()->getType(), false); |
| SsaTmpOpnd* ob_init_opnd = _opndManager.createSsaTmpOpnd(ob_var_opnd->getType()); |
| U_32 ob_id = onode->opndId; |
| Insts::iterator itvc; |
| ScObjFlds::iterator ito; |
| Node* node_no = nobj_inst->getNode(); |
| ScObjFld* sco = NULL; |
| |
| if (lobj_opt) { |
| lobj_inst = lonode->nInst; |
| } |
| if (scObjFlds->size() > 0) { |
| for (ito = scObjFlds->begin( ); ito != scObjFlds->end( ); ito++ ){ |
| sco = (*ito); |
| if (sco->ls_insts->size()==0) |
| continue; |
| Type* fl_type = NULL; |
| Type* fl_type1 = NULL; |
| Inst* ii = sco->ls_insts->front(); |
| Inst* iadr = NULL; |
| if (ii->getOpcode()==Op_TauStInd) { |
| iadr=ii->getSrc(1)->getInst(); |
| fl_type1 = ii->getSrc(1)->getType()->asPtrType()->getPointedToType(); |
| fl_type = ii->getSrc(0)->getType(); |
| } else { |
| iadr=ii->getSrc(0)->getInst(); |
| fl_type1 = ii->getSrc(0)->getType()->asPtrType()->getPointedToType(); |
| fl_type = ii->getDst()->getType(); |
| } |
| VarOpnd* fl_var_opnd = _opndManager.createVarOpnd(fl_type, false); |
| SsaTmpOpnd* fl_init_opnd = _opndManager.createSsaTmpOpnd(fl_type); |
| Inst* ld_init_val_inst = NULL; |
| sco->fldVarOpnd = fl_var_opnd; |
| |
| if (verboseLog) { |
| os_sc<<" PoitedType "; fl_type1->print(os_sc); os_sc <<std::endl; |
| os_sc<<" OperandType "; fl_type->print(os_sc); os_sc <<std::endl; |
| } |
| if (fl_type->isReference()) { |
| ld_init_val_inst = _instFactory.makeLdNull(fl_init_opnd); |
| } else { |
| ld_init_val_inst = _instFactory.makeLdConst(fl_init_opnd, 0); |
| } |
| scalarizeOFldUsage(sco); |
| if (verboseLog) { |
| 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 (verboseLog) { |
| 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) { |
| // |
| bool comprRefs = compressedReferencesArg |
| || (VMInterface::areReferencesCompressed()); |
| Modifier mod1 = comprRefs ? AutoCompress_Yes : AutoCompress_No; |
| 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(mod1,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_id); |
| if (verboseLog) { |
| 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.makeLdNull(ob_init_opnd)->insertBefore(nobj_inst); |
| _instFactory.makeStVar(ob_var_opnd,ob_init_opnd)->insertBefore(nobj_inst); |
| if (lobj_opt) { |
| _instFactory.makeStVar(ob_var_opnd,(Opnd*)(lonode->refObj))->insertAfter(lonode->nInst); |
| } |
| if (methodEndInsts->size()!=0) |
| fixMethodEndInsts(ob_id); |
| removeInst(nobj_inst); |
| if (verboseLog) { |
| 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); |
| } |
| U_32 nsrc = phi->getNumSrcOperands(); |
| |
| for (U_32 i=0; i<nsrc; i++) { |
| inst = phi->getSrc(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 (verboseLog) { |
| 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 (verboseLog) { |
| 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 (verboseLog) { |
| 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 (verboseLog) { |
| os_sc << "- - - to remove 2: "; |
| onode->nInst->print(os_sc); |
| os_sc << std::endl; |
| } |
| } |
| } // collectStLdInsts(CnGNode* onode, ScObjFld* scObjFlds) |
| |
| |
| void |
| EscAnalyzer::collectCallInsts(U_32 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; |
| U_32 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; |
| U_32 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 (verboseLog) { |
| 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); |
| removeInst(inst_ad); |
| if (inst_ad->getOpcode()==Op_AddScaledIndex) { |
| removeInst(inst_ad->getSrc(0)->getInst()); |
| } |
| if (verboseLog) { |
| 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 do_break = false; |
| |
| if (verboseLog) { |
| 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()) { |
| U_32 nsrc = inst->getNumSrcOperands(); |
| for (U_32 i=0; i<nsrc; i++) { |
| if (!(opnd=inst->getSrc(i))->isSsaOpnd()) { // check ssa operands |
| if (verboseLog) { |
| os_sc << " not ssa opnd " << i << " "; |
| inst->print(os_sc); os_sc << std::endl; |
| } |
| continue; |
| } |
| U_32 opcode=inst->getOpcode(); |
| if (checkScanned(lnoids,opnd->getId())) { |
| if (verboseLog) { |
| 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; |
| if (verboseLog) { |
| os_sc << " no remove " << opnd->getId() << std::endl; |
| } |
| lnoids->remove(opnd->getId()); |
| } |
| if (checkScanned(lloids,opnd->getId())) { |
| if (verboseLog) { |
| os_sc << " lo "; FlowGraph::printLabel(os_sc,inst->getNode()); |
| os_sc << " "; inst->print(os_sc); os_sc << std::endl; |
| } |
| if (opcode == Op_Branch) { |
| checkInsts->push_back(inst); |
| continue; |
| } |
| if (opcode == Op_TauCheckNull || opcode == Op_TauIsNonNull || opcode == Op_TauHasType) { |
| if (checkTauOpnd(inst)) { |
| checkInsts->push_back(inst); |
| continue; |
| } |
| } |
| if (opcode == Op_MethodEnd) { |
| methodEndInsts->push_back(inst); |
| continue; |
| } |
| if (opcode == Op_LdFieldAddr || opcode == Op_LdArrayBaseAddr) |
| continue; |
| if (!check_loc) { |
| if (opcode == Op_IndirectMemoryCall || opcode == Op_DirectCall) { |
| continue; |
| } |
| } |
| if (verboseLog) { |
| 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 (verboseLog) { |
| os_sc << " -------- " << std::endl; |
| } |
| return; |
| } // checkOpndUsage(ObjIds* loids,bool check_loc,::std::ostream& os_sc) |
| |
| |
| bool |
| EscAnalyzer::checkTauOpnd(Inst* tau_inst) { |
| const Nodes& nodes = irManager.getFlowGraph().getNodes(); |
| Nodes::const_iterator niter; |
| bool maydo = true; |
| U_32 tau_opnd_id = tau_inst->getDst()->getId(); |
| U_32 sc_opnd_id = tau_inst->getSrc(0)->getId(); |
| Inst* inst1; |
| |
| if (verboseLog) { |
| os_sc << " -------- Check tau opnd " << std::endl; |
| } |
| for(niter = nodes.begin(); niter != nodes.end(); ++niter) { |
| Node* node = *niter; |
| Inst *headInst = (Inst*)node->getFirstInst(); |
| Opnd* opnd; |
| for (Inst* inst=headInst->getNextInst();inst!=NULL;inst=inst->getNextInst()) { |
| U_32 nsrc = inst->getNumSrcOperands(); |
| for (U_32 i=0; i<nsrc; i++) { |
| if (!(opnd=inst->getSrc(i))->isSsaOpnd()) // check ssa operands |
| continue; |
| if (opnd->getId()==tau_opnd_id) { |
| U_32 opcode=inst->getOpcode(); |
| if (verboseLog) { |
| 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) { |
| printCallMethodName(inst, os_sc); |
| } |
| } |
| if (opcode == Op_IndirectMemoryCall || opcode == Op_DirectCall) { |
| for (U_32 i1=0; i1<nsrc; i1++) { |
| if (inst->getSrc(i)->getId() == sc_opnd_id) |
| break; |
| if (i1 == nsrc) { |
| maydo = false; |
| } |
| } |
| } |
| if (opcode == Op_TauLdInd || opcode == Op_TauStInd) { |
| if (opcode == Op_TauLdInd) |
| inst1 = inst->getSrc(0)->getInst(); |
| else |
| inst1 = inst->getSrc(1)->getInst(); |
| if (inst1->getOpcode() != Op_LdFieldAddr) |
| maydo = false; |
| if (inst1->getSrc(0)->getId() != sc_opnd_id) |
| maydo = false; |
| if (verboseLog) { |
| os_sc << " "; FlowGraph::printLabel(os_sc,inst1->getNode()); |
| os_sc << " "; inst1->print(os_sc); os_sc << std::endl; |
| } |
| } |
| if (maydo == false) { |
| return maydo; |
| } |
| } |
| } |
| } |
| } |
| return maydo; |
| } // checkTauOpnd(Inst* tau_inst) |
| |
| |
| bool |
| EscAnalyzer::checkOpndUsage(U_32 lobjid) { |
| const Nodes& nodes = irManager.getFlowGraph().getNodes(); |
| Nodes::const_iterator niter; |
| bool maydo = true; |
| U_32 n_used = 0; |
| |
| if (verboseLog) { |
| 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()) { |
| U_32 nsrc = inst->getNumSrcOperands(); |
| for (U_32 i=0; i<nsrc; i++) { |
| if (!(opnd=inst->getSrc(i))->isSsaOpnd()) // check ssa operands |
| continue; |
| if (opnd->getId()==lobjid) { |
| n_used++; |
| U_32 opcode=inst->getOpcode(); |
| if (verboseLog) { |
| 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) { |
| printCallMethodName(inst, os_sc); |
| } |
| } |
| if (opcode != Op_LdFieldAddr && opcode != Op_LdArrayBaseAddr && |
| opcode != Op_IndirectMemoryCall && opcode != Op_DirectCall && |
| opcode != Op_MethodEnd && opcode != Op_StVar) { |
| maydo = false; |
| } |
| } |
| } |
| } |
| } |
| if (verboseLog) { |
| os_sc << " -------- opnd used: " << n_used << " maydo " << maydo << std::endl; |
| } |
| return maydo; |
| } // checkOpndUsage(U_32 lobjid) |
| |
| |
| EscAnalyzer::CnGNode* |
| EscAnalyzer::checkCnGtoScalarize(CnGNode* scnode, bool check_loc) { |
| U_32 ob_ref_type=0; // object ref type |
| U_32 ob_fld_count=0; // number of object references to fields |
| U_32 ob_fin_fld_count=0; // number of object references to final fields |
| U_32 ob_nfld_count=0; // number of object references to not a field |
| U_32 ref_to_obj_count=0; // number references to object |
| U_32 vcall_count=0; // number of virtual calls |
| U_32 call_count=0; // number of calls |
| U_32 ob_fld_stind_count=0; // number of stores in object field |
| U_32 ob_fld_ldind_count=0; // number of loads from object field |
| U_32 ob_fld_field_count=0; // number of fields of object field |
| U_32 ob_fld_unkn_count=0; // number of unknown references of object field |
| U_32 ob_fld_usage_count=0; // number of object field usage |
| U_32 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; |
| U_32 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 (scnode->nodeType == NT_OBJECT && ((Opnd*)scnode->refObj)->getType()->isUnresolvedType()) { |
| //do not scalarize unresolved types -> resolution can have side effect |
| return NULL; |
| } |
| if (verboseLog) { |
| os_sc << "=="; printCnGNode(scnode,os_sc); |
| ((Opnd*)scnode->refObj)->printWithType(os_sc); |
| NamedType* nt = (NamedType*)((Opnd*)scnode->refObj)->getType(); |
| if (nt->isUnresolvedType() || nt->isFinalizable()) { |
| os_sc << " - finalizable or unresolved"; |
| } |
| os_sc << std::endl; |
| os_sc << " =="; ((Opnd*)scnode->refObj)->getInst()->print(os_sc); |
| os_sc << std::endl; |
| checkOpndUsage(scnode->opndId); |
| } |
| |
| if (verboseLog) { |
| 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 (verboseLog) { |
| os_sc<<"++ "<<scnode->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 (verboseLog) { |
| 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 (verboseLog) { |
| 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 (verboseLog) { |
| 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 (verboseLog) { |
| os_sc << " not_fld " << edgeTypeToString(*it1) << " "; |
| (*it1)->cngNodeTo->nInst->print(os_sc); os_sc << std::endl; |
| } |
| } |
| } |
| } |
| if (verboseLog) { |
| os_sc << " -------- end - Ref from node " << std::endl; |
| } |
| U_32 n=scnode->cngNodeId; |
| |
| if (verboseLog) { |
| 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; |
| U_32 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 (verboseLog) { |
| 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) { |
| printCallMethodName(ii, os_sc); |
| } |
| } |
| } |
| } |
| } |
| if (verboseLog) { |
| 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 (verboseLog) { |
| os_sc << "----scalar no opt: check_loc " << check_loc |
| << " state " << getEscState(scnode) << std::endl; |
| } |
| } |
| } else { |
| if (verboseLog) { |
| 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 (verboseLog) { |
| os_sc << "----scalar no opt: stvar=1 final fields " << ob_fin_fld_count |
| << " used field " << ob_fld_usage_count << std::endl; |
| } |
| goto MM; |
| } |
| |
| if (verboseLog) { |
| os_sc << "************* " << ((Opnd*)scnode->refObj)->getType()->getName() << std::endl; |
| } |
| assert(vnode!=NULL); |
| CnGNode* lobj = getLObj(vnode); // scalarizable load object |
| if (lobj != NULL) { |
| if (verboseLog) { |
| printOriginObjects(lobj->nInst,false," "); |
| } |
| bool notnullsrcs = checkVVarSrcs(lobj->nInst); |
| if (verboseLog) { |
| os_sc << "----checkCnG: stvar=1 checkVVSrcs " << notnullsrcs << std::endl; |
| } |
| if (!notnullsrcs) { |
| goto MM; |
| } |
| if (verboseLog) { |
| os_sc << "----check srcs opernds for optimized load object (cng node): " |
| << lobj->cngNodeId << std::endl; |
| } |
| rnode = checkCnGtoScalarize(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_in_use) { |
| if (ob_fin_fld_count==ob_fld_usage_count) { |
| storeId = true; |
| } else { |
| if (verboseLog) { |
| 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 (verboseLog) { |
| 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 (verboseLog) { |
| os_sc << "----scalar no opt: arr: fld " << ob_fld_count |
| << " used flds " << ob_fld_usage_count << std::endl; |
| } |
| } |
| } else { |
| if (verboseLog) { |
| 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 (verboseLog) { |
| 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 (verboseLog) { |
| os_sc << "----scalar may be opt: "; printCnGNode(scnode,os_sc); |
| os_sc << std::endl; |
| } |
| return rnode; |
| } |
| if (verboseLog) { |
| os_sc << "----scalar no opt: "; printCnGNode(scnode,os_sc); |
| os_sc << std::endl; |
| } |
| return NULL; |
| |
| } // checkCnGtoScalarize(CnGNode* scnode, bool check_loc) |
| |
| |
| double |
| EscAnalyzer::checkLocalPath(Inst* nob_inst) { |
| double prob = 0; |
| Node* node = nob_inst->getNode(); |
| Opnd* objOpnd = nob_inst->getDst(); |
| U_32 objId = objOpnd ->getId(); |
| |
| if (verboseLog) { |
| 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 (verboseLog) { |
| 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, U_32 obId, double cprob) { |
| 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 (verboseLog) { |
| os_sc << " **** Node EXIT : "; FlowGraph::printLabel(os_sc,node); |
| os_sc << " id." << node->getId() << " execCount " << node->getExecCount() |
| << " in prob " << cprob << std::endl; |
| } |
| return r; |
| } |
| |
| if (scannedObjs->size()!=0) { |
| if (checkScannedObjs(node->getId())) { |
| 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 |
| } |
| } |
| for (Inst* inst=headInst->getNextInst();inst!=NULL;inst=inst->getNextInst()) { |
| if (inst->getOpcode()==Op_IndirectMemoryCall || inst->getOpcode()==Op_DirectCall) { |
| U_32 nsrc = inst->getNumSrcOperands(); |
| for (U_32 i=0; i<nsrc; i++) { |
| opnd=inst->getSrc(i); |
| if (opnd->getId()==obId) { |
| if (verboseLog) { |
| 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); |
| } else { |
| if ((tn1=node->getTrueEdgeTarget())!=NULL) { |
| r1 = checkNextNodes(tn1,obId,r); |
| } |
| if ((tn2=node->getFalseEdgeTarget())!=NULL) { |
| r2 = checkNextNodes(tn2,obId,r); |
| } |
| 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, U_32 obId, double cprob)) |
| |
| |
| void |
| EscAnalyzer::restoreEOCreation(Insts* vc_insts, ScObjFlds* scObjFlds, VarOpnd* ob_var_opnd, U_32 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 or chknull tau |
| Node* node_var1 = NULL; // node with call inst after opt |
| Node* node_after1 = NULL; // node with field var opnds updating after call |
| ScObjFlds::iterator ito; |
| const bool splitAfter = true; |
| SsaTmpOpnd* ob_opnd = NULL; |
| |
| for (itvc = vc_insts->begin( ); itvc != vc_insts->end( ); itvc++ ) { |
| Inst* vc = *itvc; |
| U_32 i; |
| U_32 nsrc = vc->getNumSrcOperands(); |
| |
| for (i=0; i<nsrc; i++) { |
| Opnd* opnd=vc->getSrc(i); |
| if (opnd->getId()==oid) { |
| break; |
| } |
| } |
| if (i>=nsrc) { |
| continue; |
| } |
| |
| node_before=vc->getNode(); |
| Node* dispatchNode = node_before->getExceptionEdgeTarget(); //now object allocation inst will be connected to this dispatch |
| assert(dispatchNode); |
| node_obj1 = NULL; |
| node_after1 = NULL; |
| node_var1 = NULL; |
| if (verboseLog) { |
| 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 |
| for (U_32 i1=0; i1<nsrc; i1++) { |
| if (vc->getSrc(i1)->getId()==oid) { |
| vc->setSrc(i1,ob_opnd ); |
| } |
| if (Type::isTau(vc->getSrc(i1)->getType()->tag)) { |
| Inst* tau_inst = NULL; |
| Insts::iterator iit; |
| U_32 to_id = vc->getSrc(i1)->getId(); |
| for (iit=checkInsts->begin(); iit!=checkInsts->end(); iit++) { |
| if ((*iit)->getDst()->isNull()) { |
| continue; |
| } |
| if ((*iit)->getDst()->getId()!=to_id) { |
| continue; |
| } |
| |
| Inst* ti = *iit; |
| U_32 ti_oc = ti->getOpcode(); |
| if (ti_oc == Op_TauCheckNull || ti_oc == Op_TauIsNonNull || ti_oc == Op_TauHasType) { |
| tau_inst = NULL; |
| SsaTmpOpnd* to = _opndManager.createSsaTmpOpnd(_typeManager.getTauType()); |
| if (ti_oc == Op_TauCheckNull) { |
| tau_inst = _instFactory.makeTauCheckNull(to,ob_opnd); |
| } |
| if (ti_oc == Op_TauIsNonNull) { |
| tau_inst = _instFactory.makeTauIsNonNull(to,ob_opnd); |
| } |
| if (ti_oc == Op_TauHasType) { |
| tau_inst = _instFactory.makeTauHasType(to,ob_opnd,ti->asTypeInst()->getTypeInfo()); |
| } |
| if (tau_inst != NULL) { |
| break; |
| } |
| } |
| } |
| if (tau_inst == NULL) { |
| continue; |
| } |
| if (verboseLog) { |
| os_sc << "---- tau_inst can throw " << tau_inst->getOperation().canThrow() << " "; |
| tau_inst->print(os_sc); os_sc << std::endl; |
| os_sc << std::endl; |
| } |
| assert(vc->getBCOffset()!=ILLEGAL_BC_MAPPING_VALUE); |
| tau_inst->setBCOffset(vc->getBCOffset()); |
| tau_inst->insertBefore(vc); |
| vc->setSrc(i1,tau_inst->getDst()); |
| if (tau_inst->getOperation().canThrow() == true) { |
| node_var1=fg.splitNodeAtInstruction(tau_inst,splitAfter,false, |
| _instFactory.makeLabel()); |
| fg.addEdge(tau_inst->getNode(),fg.getUnwindNode()); |
| } |
| } |
| |
| } |
| // adding newobj inst |
| SsaTmpOpnd* nob_opnd = _opndManager.createSsaTmpOpnd(ob_var_opnd->getType()); |
| Inst* newobj=_instFactory.makeNewObj(nob_opnd,ob_var_opnd->getType()); |
| newobj->insertBefore(ldobj); |
| newobj->setBCOffset(0); |
| // storing created newobj result in object var opnd |
| Inst* stvobj=_instFactory.makeStVar(ob_var_opnd,nob_opnd); |
| stvobj->insertBefore(ldobj); |
| // node with call inst after opt |
| node_var=fg.splitNodeAtInstruction(stvobj,splitAfter,false,_instFactory.makeLabel()); |
| // checking, if the object is created goto node_var node |
| SsaTmpOpnd* ob_opnd_as_flag = _opndManager.createSsaTmpOpnd(ob_var_opnd->getType()); |
| _instFactory.makeLdVar(ob_opnd_as_flag,ob_var_opnd)->insertBefore(newobj); |
| Inst* branch_inst = _instFactory.makeBranch(Cmp_NonZero, ob_opnd_as_flag->getType()->tag, |
| ob_opnd_as_flag, (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 object field initialization |
| ScObjFld* sco = NULL; |
| if (scObjFlds->size() > 0) { |
| Opnd* tau_op = _opndManager.createSsaTmpOpnd(_typeManager.getTauType()); |
| _instFactory.makeTauUnsafe(tau_op)->insertBefore(branch_inst); |
| for (ito = scObjFlds->begin( ); ito != scObjFlds->end( ); ito++ ){ |
| sco = (*ito); |
| if (sco->ls_insts->size()==0) { |
| continue; |
| } |
| Type* fl_type = NULL; |
| Type* 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(); |
| type = ii->getSrc(0)->getType(); |
| } else { |
| iadr=ii->getSrc(0)->getInst(); |
| fl_type = ii->getSrc(0)->getType()->asPtrType()->getPointedToType(); |
| type = ii->getDst()->getType(); |
| } |
| assert(iadr->getOpcode()==Op_LdFieldAddr); // only esc.objects may be optimized |
| bool compress = (fl_type->isCompressedReference() && |
| !type->isCompressedReference()); |
| Modifier compressMod = Modifier(compress ? AutoCompress_Yes |
| : AutoCompress_No); |
| Modifier mod = (compInterface.needWriteBarriers())? |
| (Modifier(Store_WriteBarrier)|compressMod) : (Modifier(Store_NoWriteBarrier)|compressMod); |
| |
| SsaTmpOpnd* fl_tmp_opnd_st = _opndManager.createSsaTmpOpnd(type); |
| Inst* ldflvar_inst = _instFactory.makeLdVar(fl_tmp_opnd_st, sco->fldVarOpnd); |
| if (sco->isFinalFld) { |
| ldflvar_inst->insertBefore(stvobj); // after newobj |
| } else { |
| ldflvar_inst->insertAfter(ldobj); // after ldvar obj_var_opnd |
| } |
| Opnd* dst = _opndManager.createSsaTmpOpnd(iadr->getDst()->getType()); |
| FieldDesc* fd = iadr->asFieldAccessInst()->getFieldDesc(); |
| Inst* ldfladr_inst = NULL; |
| if (sco->isFinalFld) { |
| ldfladr_inst = _instFactory.makeLdFieldAddr(dst,nob_opnd,fd); |
| ldfladr_inst->insertBefore(stvobj); // after newobj |
| } else { |
| ldfladr_inst = _instFactory.makeLdFieldAddr(dst,ob_opnd,fd); |
| ldfladr_inst->insertAfter(ldflvar_inst); // after ldvar ob_var_opnd |
| } |
| |
| Inst* nstind=_instFactory.makeTauStInd(mod,type->tag, |
| fl_tmp_opnd_st,dst,tau_op,tau_op,tau_op); |
| if (sco->isFinalFld) { |
| nstind->insertBefore(stvobj); |
| continue; |
| } else { |
| nstind->insertAfter(ldfladr_inst); |
| } |
| // updating non-final field var.opnds after call |
| if (node_after1 == NULL) { |
| node_after1=fg.createBlockNode(_instFactory.makeLabel()); |
| } |
| // loading field value |
| SsaTmpOpnd* fl_tmp_opnd_ld = _opndManager.createSsaTmpOpnd(type); |
| bool comprRefs = compressedReferencesArg |
| || (VMInterface::areReferencesCompressed()); |
| Modifier mod1 = comprRefs ? AutoCompress_Yes : AutoCompress_No; |
| Inst* ldf = _instFactory.makeTauLdInd(mod1,type->tag,fl_tmp_opnd_ld,dst, |
| tau_op,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 (node_after1 != NULL) { |
| if (verboseLog) { |
| os_sc << "!!!! to restore not final fields " << std::endl; |
| } |
| Node* node_call = node_var; |
| if (node_var1 != NULL) { |
| node_call = node_var1; |
| } |
| // next node after node with call inst |
| Node* node_after = node_call->getUnconditionalEdgeTarget(); |
| // inserting node with updating field var opnds |
| fg.removeEdge(node_call->getUnconditionalEdge()); |
| fg.addEdge(node_call,node_after1); |
| fg.addEdge(node_after1,node_after); |
| } |
| } |
| |
| node_obj1=fg.splitNodeAtInstruction(newobj,splitAfter,false, _instFactory.makeLabel()); |
| fg.addEdge(node_obj,dispatchNode); |
| |
| if (verboseLog) { |
| 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_var1 != NULL) { |
| FlowGraph::print(os_sc,node_var1); |
| } |
| 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 (shortLog) { |
| Node* node = reminst->getNode(); |
| os_sc <<"--rmInst done: CFGnode "; FlowGraph::printLabel(Log::out(), node); |
| os_sc << " "; reminst->print(os_sc); os_sc << std::endl; |
| } |
| if (reminst->getOperation().canThrow()==true) { |
| excedge = (Edge*)reminst->getNode()->getExceptionEdge(); |
| assert(excedge != NULL); |
| if (shortLog) { |
| os_sc <<"--rmEdge done: to "; FlowGraph::printLabel(Log::out(), excedge->getTargetNode()); os_sc << std::endl; |
| } |
| fg.removeEdge(excedge); |
| } |
| reminst->unlink(); |
| } else { |
| if (shortLog) { |
| os_sc <<"--rmInst null: CFGnode NULL "; reminst->print(os_sc); os_sc << std::endl; |
| } |
| } |
| } // removeInst(Inst* reminst) |
| |
| void |
| EscAnalyzer::fixMethodEndInsts(U_32 ob_id) { |
| Insts::iterator itmei; |
| InstFactory& _instFactory = irManager.getInstFactory(); |
| OpndManager& _opndManager = irManager.getOpndManager(); |
| for (itmei = methodEndInsts->begin( ); itmei != methodEndInsts->end( ); itmei++ ) { |
| Inst* mei = *itmei; |
| U_32 i = 0; |
| U_32 nsrc = mei->getNumSrcOperands(); |
| |
| if (nsrc == 0) |
| continue; |
| Opnd* o = mei->getSrc(i); |
| if (o->getId() != ob_id) |
| continue; |
| |
| if (verboseLog) { |
| 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 (verboseLog) { |
| mei->getPrevInst()->print(os_sc); os_sc << std::endl; |
| mei->print(os_sc); os_sc << std::endl; |
| os_sc << "++++ " << std::endl; |
| } |
| } |
| } // fixMethodEndInsts(U_32 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; |
| U_32 nsrc=inst->getNumSrcOperands(); |
| std::string text = " checkVVS "; |
| bool res = true; |
| |
| if (scannedObjs->size()!=0) { |
| if (checkScannedObjs(inst->getId())) { |
| if (verboseLog) { |
| os_sc << "instId " << inst->getId() |
| << " . . . returns false" << std::endl; |
| } |
| return false; |
| } |
| } |
| if (verboseLog) { |
| 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; |
| } |
| } |
| |
| if (inst->getOpcode()==Op_DirectCall || inst->getOpcode()==Op_IndirectMemoryCall) { |
| 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 ) { |
| return true; |
| } else { |
| return false; |
| } |
| } |
| if (inst->getOpcode() == Op_NewObj || inst->getOpcode() == Op_NewArray |
| || inst->getOpcode() == Op_NewMultiArray) { |
| return true; |
| } |
| if (inst->getOpcode() == Op_LdRef || inst->getOpcode() == Op_DefArg ) { |
| 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 (U_32 i=0; i<2; i++) { |
| inst1 = inst->getSrc(i)->getInst(); |
| res = checkVVarSrcs(inst1); |
| } |
| break; |
| default: |
| for (U_32 i=0; i<nsrc; i++) { |
| inst1 = inst->getSrc(i)->getInst(); |
| bool res1 = checkVVarSrcs(inst1); |
| res = res && res1; |
| } |
| } |
| scannedObjs->pop_back(); |
| if (verboseLog) { |
| os_sc << " 1 returns " << res << std::endl; |
| } |
| 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(U_32 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 (verboseLog) { |
| os_sc << " ** "; (*iit)->print(os_sc); os_sc << std::endl; |
| } |
| Inst* inst = (*iit); |
| U_32 opcode = inst->getOpcode(); |
| 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 (verboseLog) { |
| 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 || opcode == Op_TauCheckNull || opcode == Op_TauHasType) { |
| if (inst->getOperation().canThrow()==true) { |
| excedge = (Edge*)inst->getNode()->getExceptionEdge(); |
| if (verboseLog) { |
| os_sc <<"-- exc edge to "; |
| ((Inst*)(excedge->getTargetNode()->getLabelInst()))->print(os_sc); |
| os_sc << std::endl; |
| } |
| } |
| removeInst(inst); |
| } |
| } |
| } // fixCheckInsts(U_32 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 (verboseLog) { |
| os_sc << "########################" << std::endl; |
| printCnGNode(onode,os_sc); os_sc << std::endl; |
| } |
| scObjFlds->clear(); |
| collectStLdInsts(onode, scObjFlds); |
| if (scObjFlds->size() != 0) { |
| if (verboseLog) { |
| os_sc << " used fields: " << scObjFlds->size() << " final fields exist: "; |
| } |
| for (ito = scObjFlds->begin( ); ito != scObjFlds->end( ); ito++ ){ |
| sco = (*ito); |
| if (verboseLog) { |
| os_sc << sco->isFinalFld << " "; |
| } |
| if (sco->isFinalFld) { |
| do_fsc = true; |
| } |
| if (verboseLog) { |
| os_sc << " field usage : " << sco->ls_insts->size(); |
| } |
| } |
| if (verboseLog) { |
| os_sc << std::endl; |
| } |
| } |
| if (verboseLog) { |
| 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; |
| Type* fl_type1 = NULL; |
| Inst* ii = sco->ls_insts->front(); |
| Inst* iadr = NULL; |
| if (ii->getOpcode()==Op_TauStInd) { |
| iadr=ii->getSrc(1)->getInst(); |
| fl_type1 = ii->getSrc(1)->getType()->asPtrType()->getPointedToType(); |
| fl_type = ii->getSrc(0)->getType(); |
| } else { |
| iadr=ii->getSrc(0)->getInst(); |
| fl_type1 = ii->getSrc(0)->getType()->asPtrType()->getPointedToType(); |
| fl_type = ii->getDst()->getType(); |
| } |
| VarOpnd* fl_var_opnd = _opndManager.createVarOpnd(fl_type, false); |
| sco->fldVarOpnd = fl_var_opnd; |
| if (verboseLog) { |
| os_sc<<" PoitedType "; fl_type1->print(os_sc); os_sc <<std::endl; |
| os_sc<<" OperandType "; fl_type->print(os_sc); os_sc <<std::endl; |
| } |
| scalarizeOFldUsage(sco); |
| if (verboseLog) { |
| 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; |
| } |
| bool comprRefs = compressedReferencesArg |
| || (VMInterface::areReferencesCompressed()); |
| Modifier mod1 = comprRefs ? AutoCompress_Yes : AutoCompress_No; |
| 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(mod1,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 (verboseLog) { |
| 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) |
| |
| static void logMethod(MethodPtrType* mpt) { |
| mpt->print(Log::out()); Log::out() << std::endl; |
| if (mpt->isUnresolvedMethodPtrType()) { |
| Log::out() << " isUnresolved: true" << std::endl; |
| } else { |
| MethodDesc* mdesc = mpt->getMethodDesc(); |
| logMethod(mdesc); |
| } |
| } |
| |
| static void logMethod(MethodDesc* mdesc) { |
| Log::out() << " isStatic: " << mdesc->isStatic() << std::endl; |
| Log::out() << " isFinal: " << mdesc->isFinal() << std::endl; |
| Log::out() << "---------------" << std::endl; |
| Log::out() << " NumParams: " << mdesc->getNumParams()<< std::endl; |
| Log::out() << " isInstance: " << mdesc->isInstance() << std::endl; |
| Log::out() << " isVirtual: " << mdesc->isVirtual() << std::endl; |
| Log::out() << " isAbstract: " << mdesc->isAbstract() << std::endl; |
| Log::out() << " isInstanceInitializer: " << mdesc->isInstanceInitializer() << std::endl; |
| } |
| |
| static bool isVMHelperCall(Inst* inst, VM_RT_SUPPORT id) { |
| VMHelperCallInst* callInst = inst->asVMHelperCallInst(); |
| if (callInst==NULL) { |
| return false; |
| } |
| return callInst->getVMHelperId() == id; |
| } |
| |
| } //namespace Jitrino |
| |
| |
| |
| |
| |
| |
| |
| |
| |