| /* |
| * 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 |
| * |
| */ |
| |
| #ifndef _ESCANALYSIS_H_ |
| #define _ESCANALYSIS_H_ |
| |
| #include "Stl.h" |
| #include "optpass.h" |
| #include "FlowGraph.h" |
| #include "irmanager.h" |
| #include "mkernel.h" |
| |
| namespace Jitrino { |
| |
| /** |
| * Performs escape analysis for the compiled method. |
| * Creates data connection graph, sets states (local, argument escaped, global escaped) |
| * for objects created in compiled method, runs escape analysis related optimizations: |
| * - monitor elimination optimization; |
| * - scalar replacement optimization. |
| * Saves information about method arguments and return value states for future usage. |
| */ |
| |
| class EscAnalyzer { |
| |
| public: |
| /** |
| * Creates EscAnalyzer class for compiled method. |
| * @param mm - memory manager, |
| * @param argSource - session action, |
| * @param irm - compiled method IR manager. |
| */ |
| EscAnalyzer(MemoryManager& mm, SessionAction* argSource, IRManager& irm); |
| |
| /** |
| * Performs escape analysis and runs escape analysis related optimizations. |
| */ |
| void doAnalysis(); |
| |
| // read from command line to output debug information |
| U_32 allProps; |
| |
| private: |
| /** |
| * Creates EscAnalyzer class for callee method escape analysis. |
| * @param parent - parent (caller method) EscAnalyzer class |
| * @param irm - compiled method IR manager. |
| */ |
| EscAnalyzer(EscAnalyzer* parent, IRManager& irm); |
| |
| // initial level to start callee method escape analysis |
| static const int maxMethodExamLevel_default = 0; |
| |
| // Connection Graph Structure |
| // CnG node types |
| enum CnGNodeTypes { |
| NT_OBJECT = 8, // Op_LdRef,Op_NewObj,Op_NewArray,Op_NewMultiArray |
| NT_DEFARG = NT_OBJECT+1, // formal parameter - Op_DefArg |
| NT_RETVAL = 16, // Op_DirectCall,Op_IndirectMemoryCall-returned by method |
| NT_CATCHVAL = NT_RETVAL+1, // catched value |
| NT_LDOBJ = 32, // Op_LdConstant,Op_TauLdInd,Op_LdVar, |
| // Op_TauStaticCast,Op_TauCast |
| NT_INTPTR = NT_LDOBJ+1, // Op_SaveRet |
| NT_VARVAL = NT_LDOBJ+2, // Op_StVar,Op_Phi |
| NT_ARRELEM = NT_LDOBJ+3, // Op_LdArrayBaseAddr,Op_AddScaledIndex |
| NT_REF = NT_LDOBJ+4, // reference value - Op_LdFieldAddr, |
| // Op_LdStaticAddr, Op_TauCast, Op_TauStaticCast |
| NT_STFLD = 64, // Op_LdStaticAddr |
| NT_INSTFLD = NT_STFLD+1, // Op_LdFieldAddr |
| NT_ACTARG = 128, // Op_DirectCall,Op_IndirectMemoryCall |
| NT_EXITVAL = 256, // returned value - Op_Return |
| NT_THRVAL = NT_EXITVAL+1, // thrown value - Op_Throw |
| NT_LDVAL = 512, // Op_TauLdInd, Op_TauStInd |
| NT_OBJS = NT_OBJECT|NT_RETVAL|NT_LDOBJ //for findCnGNode_op |
| }; |
| // CnG node reference types |
| static const U_32 NR_PRIM = 0; |
| static const U_32 NR_REF = 1; |
| static const U_32 NR_ARR = 2; |
| static const U_32 NR_REFARR = 3; |
| // CnG edge types |
| static const U_32 ET_POINT = 1; // Op_TauLdInd (loaded value) |
| static const U_32 ET_DEFER = 2; |
| static const U_32 ET_FIELD = 3; // Op_LdFieldAddr (object field), Op_AddScaledIndex |
| // CG node states |
| static const U_32 GLOBAL_ESCAPE = 1; |
| static const U_32 ARG_ESCAPE = 2; |
| static const U_32 NO_ESCAPE = 3; |
| static const U_32 ESC_MASK = 3; |
| static const U_32 BIT_MASK = 56; |
| static const U_32 LOOP_CREATED = 8; |
| static const U_32 OUT_ESCAPED = 16; |
| static const U_32 VIRTUAL_CALL = 32; |
| |
| |
| struct CnGNode; |
| struct CnGRef { |
| CnGNode* cngNodeTo; |
| U_32 edgeType; |
| Inst* edgeInst; |
| }; |
| |
| typedef StlList<CnGRef*> CnGRefs; |
| typedef StlList<Inst*> Insts; |
| typedef StlList<U_32> NodeMDs; |
| |
| // connection graph node structure |
| struct CnGNode { |
| U_32 cngNodeId; // CnG node id |
| U_32 opndId; // opnd id (0 for NT_ACTARG) |
| void* refObj; // MethodDesc* for NT_ACTARG, Inst* for fields, Opnd* for others |
| U_32 nodeType; // CnG node types |
| U_32 nodeRefType; // CnG node reference types |
| U_32 instrId; |
| CnGNode* lNode; // ldind from lNode for ldflda & ldsflda |
| U_32 state; // escape state |
| NodeMDs* nodeMDs; // list of NT_ACTARG nodes |
| Inst* nInst; // ref to inst |
| U_32 argNumber; // number of arg for NT_DEFARG & NT_ACTARG (0 for others) |
| CnGRefs* outEdges; // cngNode out edges |
| }; |
| |
| struct MemberIdent { |
| char* parentName; |
| char* name; |
| char* signature; |
| }; |
| |
| struct InstFld; |
| typedef StlList<InstFld*> InstFlds; |
| |
| struct InstFld { |
| MemberIdent* fldIdent; |
| U_32 state; |
| InstFlds* instFlds; // contained instance fields |
| }; |
| |
| struct ParamInfo { |
| U_32 paramNumber; |
| U_32 state; |
| InstFlds* instFlds; // contained instance fields |
| }; |
| |
| typedef StlList<ParamInfo*> ParamInfos; |
| |
| // structure of saved by EA information about compiled method |
| struct CalleeMethodInfo { |
| MemberIdent* methodIdent; |
| U_32 numberOfArgs; |
| U_32 properties; // native, final, virtual ... |
| ParamInfos* paramInfos; |
| U_32 retValueState; |
| bool mon_on_this; |
| }; |
| |
| // list of saved by EA information about compiled methods |
| typedef StlList<CalleeMethodInfo*> CalleeMethodInfos; |
| |
| // connection graph edge structure |
| struct CnGEdge { |
| CnGNode* cngNodeFrom; |
| CnGRefs* refList; |
| }; |
| |
| // list of connection graph nodes definition |
| typedef StlList<CnGNode*> CnGNodes; |
| // list of connection graph edges definition |
| typedef StlList<CnGEdge*> CnGEdges; |
| // list of object Ids definition |
| typedef StlList<U_32> ObjIds; |
| |
| |
| static CalleeMethodInfos* calleeMethodInfos; |
| static Mutex calleeMethodInfosLock; |
| |
| // variables to read command line options |
| const char* debug_method; |
| bool do_sync_removal; |
| bool do_sync_removal_vc; |
| bool do_sync_removal_sm; |
| bool do_scalar_repl; |
| bool do_esc_scalar_repl; |
| bool do_scalar_repl_only_final_fields_in_use; |
| bool do_scalar_repl_final_fields; |
| const char* execCountMultiplier_string; |
| double ec_mult; |
| bool print_scinfo; |
| bool compressedReferencesArg; // for makeTauLdInd |
| |
| TranslatorAction* translatorAction; |
| |
| MemoryManager& eaMemManager; |
| IRManager& irManager; |
| MethodDesc& mh; // analyzed method header |
| CompilationInterface &compInterface; |
| |
| // list of connection graph nodes |
| CnGNodes* cngNodes; |
| // list of connection graph edges |
| CnGEdges* cngEdges; |
| // list of instructions for edge creation |
| Insts* exam2Insts; |
| |
| // maximum level to analyze callee methods (from command line or default set) |
| U_32 maxMethodExamLevel; |
| // set level for escape analysis |
| U_32 method_ea_level; |
| |
| U_32 lastCnGNodeId; |
| U_32 curMDNode; |
| int defArgNumber; |
| U_32 initNodeType; // type of initial scanned node |
| |
| // lists to help do CFG scan |
| ObjIds *scannedObjs; |
| ObjIds *scannedObjsRev; |
| ObjIds *scannedInsts; |
| ObjIds *scannedSucNodes; |
| |
| // format 32 0 operand used by the optimizations |
| SsaTmpOpnd* i32_0; |
| // format 32 1 operand used by the optimizations |
| SsaTmpOpnd* i32_1; |
| |
| // list of Op_MethodEnd instructions (for scalar replacement optimization) |
| Insts* methodEndInsts; |
| // list of Op_Branch and Op_TauCheckNull instructions (for scalar replacement optimization) |
| Insts* checkInsts; |
| |
| bool shortLog; |
| bool verboseLog; |
| // common method for both EscAnalyzer constructors |
| void init(); |
| // output escape analysis flags |
| void showFlags(std::ostream& os); |
| |
| /** |
| * Scans specified CFG node instructions to create CnG nodes. |
| * Adds some instructions to exam2Instrs list to create CnG edges later. |
| * @param node - control flow graph node. |
| */ |
| void instrExam(Node* node); |
| |
| /** |
| * Scans instructions from exam2Instrs list to create CnG edges. |
| */ |
| void instrExam2(); |
| |
| /** |
| * Creates new CnG node for specified instruction and adds it to cngNodes list. |
| * @param inst - instruction, |
| * @param type - operand type, |
| * @param ntype - CnG node type. |
| * @return created CnGnode. |
| */ |
| CnGNode* addCnGNode(Inst* inst, Type* type, U_32 ntype); |
| |
| /** |
| * Creates new CnG node for specified instruction dst operand. |
| * @param inst - instruction, |
| * @param type - operand type, |
| * @param ntype - CnG node type. |
| * @return created CnGnode. |
| */ |
| CnGNode* addCnGNode_op(Inst* inst, Type* type, U_32 ntype); |
| |
| /** |
| * Creates new CnG node for specified call instruction argument. |
| * @param inst - instruction, |
| * @param mpt - callee method description, |
| * @param ntype - CnG node type, |
| * @param narg - method argument. |
| * @return created CnGnode. |
| */ |
| CnGNode* addCnGNode_mp(Inst* inst, MethodPtrType* mpt, U_32 ntype, U_32 narg); |
| |
| /** |
| * Creates new CnG node for specified return or throw instruction. |
| * @param inst - instruction, |
| * @param ntype - CnG node type. |
| * @return created CnGnode. |
| */ |
| CnGNode* addCnGNode_ex(Inst* inst, U_32 ntype); |
| |
| /** |
| * Creates new field CnG node for specified instruction. |
| * @param inst - instruction, |
| * @param ntype - CnG node type. |
| * @return created CnGnode. |
| */ |
| CnGNode* addCnGNode_fl(Inst* inst, U_32 ntype); |
| |
| /** |
| * Finds CnG node for specified operand Id. |
| * @param nId - operand Id. |
| * @return found CnGnode, or <code>NULL</code>. |
| */ |
| CnGNode* findCnGNode_op(U_32 nId); |
| |
| /** |
| * Finds CnG node for specified CnG node Id. |
| * @param nId - CnG node Id. |
| * @return found CnGnode, or <code>NULL</code>. |
| */ |
| CnGNode* findCnGNode_id(U_32 nId); |
| |
| /** |
| * Finds CnG node for specified instruction Id. |
| * @param nId - instruction Id. |
| * @return found CnGnode, or <code>NULL</code>. |
| */ |
| CnGNode* findCnGNode_in(U_32 nId); |
| |
| /** |
| * Finds NT_ACTARG CnG node for specified instruction Id and argument number. |
| * @param iId - instruction Id, |
| * @param aId - argument number. |
| * @return found CnGnode, or <code>NULL</code>. |
| */ |
| CnGNode* findCnGNode_mp(U_32 iId, U_32 aId); |
| |
| /** |
| * Finds field CnG node for specified instruction and CnG node type. |
| * @param inst - instruction, |
| * @param ntype - CnG node type. |
| * @return found CnGnode, or <code>NULL</code>. |
| */ |
| CnGNode* findCnGNode_fl(Inst* inst, U_32 ntype); |
| |
| /** |
| * Creates new CnG edge for specified instruction, adds it to cngEdges and |
| * cgnfrom->outEdges lists. |
| * @param cgnfrom - CnG node from, |
| * @param cgnto - CnG node to, |
| * @param etype - edge type, |
| * @param inst - instruction. |
| * @return created CnGnode. |
| */ |
| void addEdge(CnGNode* cgnfrom, CnGNode* cgnto, U_32 etype, Inst* inst); |
| |
| /** |
| * Sets escape state for method created objects. |
| */ |
| void setCreatedObjectStates(); |
| |
| /** |
| * Scans CnG nodes beginning with specified node to set |
| * GLOBAL_ESCAPE or VIRTUAL_CALL states. |
| * @param cgnfrom - CnG node to begin scan, |
| * @param check_var_src - sign to check variable operands. |
| */ |
| void scanCnGNodeRefsGE(CnGNode* cgn, bool check_var_src); |
| |
| /** |
| * Scans CnG nodes beginning with specified node to set |
| * ARG_ESCAPE states. |
| * @param cgnfrom - CnG node to begin scan, |
| * @param check_var_src - sign to check variable operands. |
| */ |
| void scanCnGNodeRefsAE(CnGNode* cgn, bool check_var_src); |
| |
| /** |
| * Scans connection graph nodes beginning with specified not global escaped node to set |
| * corresponding state to array elements and fields values. |
| * @param node - connection graph node to begin scan. |
| */ |
| void checkSubobjectStates(CnGNode* node); |
| |
| /** |
| * Finds specified method escape analysis information in the common repository and compiles |
| * the method if it is required and possible. |
| * @param md - method description, |
| * @param inst - method call instruction. |
| * @return method info, if it was found, NULL - otherwise. |
| */ |
| CalleeMethodInfo* findMethodInfo(MethodDesc* md,Inst* inst); |
| |
| /** |
| * Finds specified method escape analysis information in the common repository. |
| * @param ch1 - method package name, |
| * @param ch2 - method name, |
| * @param ch3 - method signature. |
| * @return method info, if it was found, NULL - otherwise. |
| */ |
| CalleeMethodInfo* getMethodInfo(const char* ch1,const char* ch2,const char* ch3); |
| |
| /** |
| * Runs escape analysis for direct call method. |
| * @param call - direct call instruction. |
| */ |
| void scanCalleeMethod(Inst* call); |
| |
| /** |
| * Runs translator session for callee method. |
| * @param inlineCC - compilation interface. |
| */ |
| void runTranslatorSession(CompilationContext& inlineCC); |
| |
| /** |
| * Runs optimizations for callee method. |
| * @param irManager - IR manager. |
| */ |
| void optimizeTranslatedCode(IRManager& irManager); |
| |
| /** |
| * Saves escape analysis method information into common repository. |
| */ |
| void saveScannedMethodInfo(); |
| |
| /** |
| * Returns specified method parameter state. |
| * @param mi - escape analysis method information, |
| * @param np - parameter number. |
| * @return specified parameter state. |
| */ |
| U_32 getMethodParamState(CalleeMethodInfo* mi, U_32 np); |
| |
| /** |
| * Collects instructions creating objects that are not GLOBAL_ESCAPE. |
| */ |
| void markNotEscInsts(); |
| |
| /** |
| * Performs variable operands fixup after done optimizations. |
| * @param irManager - IR manager. |
| */ |
| void eaFixupVars(IRManager& irm); |
| |
| /** |
| * Outputs connection graph nodes information into the specified log. |
| * @param text - output information naming, |
| * @param os - log. |
| */ |
| void printCnGNodes(const char* text,::std::ostream& os); |
| |
| /** |
| * Outputs connection graph node information into the specified log. |
| * @param cgn - connection graph node, |
| * @param os - log. |
| */ |
| void printCnGNode(CnGNode* cgn,::std::ostream& os); |
| |
| /** |
| * Outputs method name information into the specified log. |
| * @param inst - call instruction, |
| * @param os - log stream |
| */ |
| void printCallMethodName(Inst* inst, ::std::ostream& os); |
| |
| /** |
| * Creates string representing CnG node type. |
| * @param cgn - connection graph node. |
| * @return srting representing CnG node type. |
| */ |
| std::string nodeTypeToString(CnGNode* cgn); |
| |
| /** |
| * Outputs connection graph edges information into the specified log. |
| * @param text - output information naming, |
| * @param os - log. |
| */ |
| void printCnGEdges(const char* text,::std::ostream& os); |
| |
| /** |
| * Creates string representing CnG edge type. |
| * @param cgn - connection graph node. |
| * @return srting representing CnG edge type. |
| */ |
| std::string edgeTypeToString(CnGRef* edr); |
| |
| /** |
| * Outputs information about reference objects created in analyzed method into the specified log. |
| * @param os - log. |
| */ |
| void printRefInfo(::std::ostream& os); |
| |
| /** |
| * Outputs information about CnG node with all nodes it refers to. |
| * @param cgn - connection graph node, |
| * @param text - text printed before CnG node information, |
| * @param os - log. |
| */ |
| void printCnGNodeRefs(CnGNode* cgn, std::string text,::std::ostream& os); |
| |
| /** |
| * Outputs origin operands of specified instruction operands that aren't tau operand |
| * into the specified log. |
| * @param inst - instruction, |
| * @param text - text to print before the instruction, |
| * @param os - log. |
| */ |
| void lObjectHistory(Inst* inst,std::string text,::std::ostream& os); |
| |
| /** |
| * Outputs information about objects created in analyzed method into the specified log. |
| * @param os - log. |
| */ |
| void printCreatedObjectsInfo(::std::ostream& os); |
| |
| /** |
| * Outputs common information about created objects into log file. |
| */ |
| void createdObjectInfo(); |
| |
| /** |
| * Prints origin operands of specified instruction. |
| * @param inst - specified instruction, |
| * @param all - if <code>true</code> for all source operands of the instruction, |
| * if <code>false</code> for main source operand of some instructions, |
| * @param text - text to print before the instruction. |
| */ |
| void printOriginObjects(Inst* inst, bool all, std::string text=" "); |
| |
| /** |
| * Prints escape analysis method information for specified parameter. |
| * @param mi - method info from common repository. |
| */ |
| void printMethodInfo(CalleeMethodInfo* mi); |
| |
| /** |
| * Outputs information about instruction kind into the specified log. |
| * @param inst - instruction, |
| * @param os - log. |
| */ |
| void what_inst(Inst* inst,::std::ostream& os); |
| |
| /** |
| * Outputs debug information about the specified type into the specified log. |
| * @param type - reference type, |
| * @param os - log. |
| */ |
| void ref_type_info(Type* type,::std::ostream& os); |
| |
| /** |
| * Outputs debug information about the specified instruction into the specified log. |
| * @param inst - instruction, |
| * @param os - log. |
| */ |
| void debug_inst_info(Inst* inst,::std::ostream& os); |
| |
| /** |
| * Outputs debug information about the specified operand into the specified log. |
| * @param opnd - operand, |
| * @param os - log. |
| */ |
| void debug_opnd_info(Opnd* opnd,::std::ostream& os); |
| |
| |
| bool checkScanned(ObjIds* ids, U_32 id) { |
| ObjIds::iterator it; |
| if (ids == NULL) { |
| return false; |
| } |
| for (it = ids->begin( ); it != ids->end( ); it++ ) { |
| if ((*it)==id) { |
| return true; |
| } |
| } |
| return false; |
| } |
| bool checkScannedObjs(U_32 id) {return checkScanned(scannedObjs, id);} |
| bool checkScannedObjsRev(U_32 id) {return checkScanned(scannedObjsRev, id);} |
| bool checkScannedInsts(U_32 id) {return checkScanned(scannedInsts, id);} |
| bool checkScannedSucNodes(U_32 id) {return checkScanned(scannedSucNodes, id);} |
| |
| U_32 getEscState(CnGNode* n) { |
| return (n->state)&ESC_MASK; |
| } |
| void setEscState(CnGNode* n, U_32 st) { |
| n->state = ((n->state)&BIT_MASK)+st; |
| } |
| U_32 getFullState(CnGNode* n) { |
| return n->state; |
| } |
| void setFullState(CnGNode* n, U_32 st) { |
| n->state = st; |
| } |
| U_32 getLoopCreated(CnGNode* n) { |
| return (n->state)&LOOP_CREATED; |
| } |
| void setLoopCreated(CnGNode* n) { |
| n->state = n->state|LOOP_CREATED; |
| } |
| void remLoopCreated(CnGNode* n) { |
| n->state = (n->state|LOOP_CREATED)^LOOP_CREATED; |
| } |
| U_32 getOutEscaped(CnGNode* n) { |
| return (n->state)&OUT_ESCAPED; |
| } |
| void setOutEscaped(CnGNode* n) { |
| n->state = n->state|OUT_ESCAPED; |
| } |
| void remOutEscaped(CnGNode* n) { |
| n->state = (n->state|OUT_ESCAPED)^OUT_ESCAPED; |
| } |
| U_32 getVirtualCall(CnGNode* n) { |
| return (n->state)&VIRTUAL_CALL; |
| } |
| void setVirtualCall(CnGNode* n) { |
| n->state = n->state|VIRTUAL_CALL; |
| } |
| void remVirtualCall(CnGNode* n) { |
| n->state = (n->state|VIRTUAL_CALL)^VIRTUAL_CALL; |
| } |
| void printState(CnGNode* n,::std::ostream& os=Log::out()) { |
| os << getEscState(n) << " (" << (getFullState(n)>>3) << ")"; |
| } |
| void printState(U_32 st,::std::ostream& os=Log::out()) { |
| os << (st&ESC_MASK) << " (" << (st>>3) << ")"; |
| } |
| bool isGlobalState(U_32 state) { |
| if ((state&ESC_MASK)==GLOBAL_ESCAPE||(state&VIRTUAL_CALL)!=0) |
| return true; |
| return false; |
| } |
| bool isStateNeedGEFix(U_32 state, U_32 nType) { |
| if ((state&ESC_MASK)==GLOBAL_ESCAPE) |
| return false; |
| if ((state&OUT_ESCAPED)!=0 && initNodeType != NT_STFLD) |
| return false; |
| if ((state&OUT_ESCAPED)!=0 && initNodeType == NT_DEFARG && nType != NT_DEFARG) |
| return false; |
| return true; |
| } |
| |
| // Monitors elimination optimization |
| |
| struct MonUnit { |
| U_32 opndId; |
| Insts* monInsts; |
| Insts* icallInsts; |
| }; |
| typedef StlList<MonUnit*> MonInstUnits; |
| // list to collect info about monitor instruction operands |
| MonInstUnits* monitorInstUnits ; |
| |
| /** |
| * Adds monitor instruction to monitorInstUnits. |
| * @param inst - monitor instruction. |
| */ |
| void addMonInst(Inst* inst); |
| |
| /** |
| * Finds opndId specified monitor unit in monitorInstUnits. |
| * @param opndId - monitor instruction operand Id. |
| * @return <code>MonUnit</code>, if found, or <code>NULL</code> otherwise. |
| */ |
| MonUnit* findMonUnit(U_32 opndId); |
| |
| /** |
| * Adds call instruction to the specified monitor unit. |
| * @param mu - monitor unit, |
| * @param inst - call instruction. |
| */ |
| void addMonUnitVCall(MonUnit* mu, Inst* inst); |
| |
| /** |
| * Checks, that method contains monitor instructions with parameter |
| * which is <code>this</code> or subobject of this. |
| * @return <code>true</code>, if such monitors exist, or <code>false</code> otherwise. |
| */ |
| bool checkMonitorsOnThis(); |
| |
| /** |
| * Performs monitors elimination optimization. |
| */ |
| void scanSyncInsts(); |
| |
| /** |
| * Marks (in CFG nodes bitset) nodes that are 'locked' by monitor instructions. |
| * @param bs - CFG nodes bitset, |
| * @param syncInsts - list of monitor instruction for the same operand. |
| */ |
| void markLockedNodes(BitSet* bs, Insts* syncInsts); |
| |
| /** |
| * Marks (in CFG nodes bitset) nodes that are 'locked' by monitor instructions. |
| * @param node - next CFG node to search monexit instruction, |
| * @param bs - CFG nodes bitset, |
| * @param moninstop - monitor instruction operand, |
| * @return <code>true</code>, if such monexit was found, or <code>false</code> otherwise. |
| */ |
| bool markLockedNodes2(Node* node, BitSet* bs, Opnd* moninstop); |
| |
| /** |
| * Checks instruction source operand states for specified instruction. |
| * @param inst - specified instruction, |
| * @param st - instruction target operand state. |
| * @return <code>GLOBAL_ESCAPE</code>, if any of source operand state is <code>GLOBAL_ESCAPE</code>, |
| * <code>ARG_ESCAPE</code>, if any of source operand state or st is <code>ARG_ESCAPE</code>, |
| * <code>NO_ESCAPE</code> otherwise. |
| */ |
| U_32 checkState(Inst* inst,U_32 st); |
| |
| /** |
| * Checks if CnGNode operand is GLOBAL_ESCAPED while monitor instructions are executed. |
| * @param node - specified operand CnGNode, |
| * @param syncInsts - list of monitor instructions for specified operand. |
| * @return <code>true</code>, specified operand is global, when monitor instruction are executed, |
| * <code>false</code>, otherwise. |
| */ |
| bool checkSencEscState(CnGNode* node,Insts* syncInsts); |
| |
| /** |
| * Collects all reachable in FlowGraph nodes from the specified node to scannedSucNodes list. |
| * @param node - FlowGraph node, |
| * @param syncInsts - instruction target operand state. |
| */ |
| void collectSuccessors(Node* node); |
| |
| /** |
| * Inserts flag for specified monitor unit. Flag is set to 0 after operand creation instruction. |
| * Flag is set to 1 before call instruction from vcInsts list. |
| * Inserts flag check before monitor instruction from monInsts list. |
| * If flag is equal to 0, monitor instruction isn't executed. |
| * @param mu - monitor unit, |
| * @param bs - CFG nodes bitset (with marked nodes for specified monitor unit). |
| */ |
| void fixMonitorInstsVCalls(MonUnit* mu, BitSet* bs); |
| |
| /** |
| * Inserts flag check before monitor instruction. |
| * If flag = 0 monitor instruction isn't executed. |
| * @param syncInsts - monitor instruction list, |
| * @param chk - value to check with (0 or 1), |
| * @param muflag - monitor flag operand (VarOpnd* or SsaTmpOpnd*). |
| */ |
| void insertFlagCheck(Insts* syncInsts, Opnd* muflag, U_32 chk); |
| |
| /** |
| * Removes monitor instructions from the specified monitor instruction list. |
| * @param syncInsts - monitor instruction list. |
| */ |
| void removeMonitorInsts(Insts* syncInsts); |
| |
| /** |
| * Removes flow graph node. |
| * @param node - flow graph node. |
| */ |
| void removeNode(Node* node); |
| |
| /** |
| * Performs monitors elimination optimization for specified monitor instructions with |
| * method <code>this</code> argument. |
| * @param syncInsts - monitor instruction list. |
| */ |
| void fixSyncMethodMonitorInsts(Insts* syncInsts); |
| |
| /** |
| * Inserts ReadJitHelperCall instruction to read state of method <code>this</code> argument |
| * after first instruction in entry block. |
| * @return <code>this</code> argument state |
| * 0 - <code>this</code> argument is thread local, |
| * 1 - <code>this</code> argument is thread global. |
| */ |
| Opnd* insertReadJitHelperCall(); |
| |
| /** |
| * Checks <code>this</code> argument of direct call synchronized methods. |
| * If the argument doesn't escape callee method, and actual argument isn't global, |
| * calls 'insertSaveJitHelperCall' to transfer <code>this</code> argument state |
| * to callee method. |
| */ |
| void checkCallSyncMethod(); |
| |
| /** |
| * Inserts SaveJitHelperCall instruction to store state of method <code>this</code> argument |
| * before the specified instruction. |
| * @param inst_before - instruction to insert SaveJitHelperCall before, |
| * @param stVal - stored value. |
| */ |
| void insertSaveJitHelperCall(Inst* inst_before, SsaTmpOpnd* stVal); |
| |
| /** |
| * Creates i32_0 or i32_1 SsaTmpOpnd (in accordance with value: 0 or 1) |
| * if it wasn't created before. |
| * Inserts ldc0 or ldc1 instruction after first instruction in entry Node, |
| * if SsaTmpOpnd was created. |
| * @param value - 0 or 1. |
| * @return i32_0, if value = 0 |
| * i32_1, if value = 1 |
| */ |
| SsaTmpOpnd* insertLdConst(U_32 value); |
| |
| |
| |
| // Scalar replacement optimization |
| |
| struct ScObjFld { |
| VarOpnd* fldVarOpnd; |
| Insts* ls_insts; |
| FieldDesc* fd; |
| bool isFinalFld; |
| }; |
| // list to collect scalarized object candidates |
| typedef StlList<ScObjFld*> ScObjFlds; |
| |
| // output stream for scalar replacement optimization |
| std::ostream& os_sc; |
| |
| /** |
| * Performs scalar replacement optimization for local objects |
| * (class instances and arrays). |
| */ |
| void scanLocalObjects(); |
| |
| /** |
| * Performs scalar replacement optimization for method escaped class instances. |
| */ |
| void scanEscapedObjects(); |
| |
| /** |
| * Performs scalar replacement optimization for local objects from the specified list. |
| * @param loids - list of local objects CnG nodes Ids, |
| */ |
| void doLOScalarReplacement(ObjIds* loids); |
| |
| /** |
| * Performs scalar replacement optimization for method escaped objects from the specified list. |
| * @param loids - list of optimized objects CnG nodes Ids. |
| */ |
| void doEOScalarReplacement(ObjIds* loids); |
| |
| /** |
| * Collects (using connection graph) information of onode object fields usage. |
| * @param onode - connection graph node fields usage of which is collected |
| * @param scObjFlds - list to collect onode field's usage. |
| */ |
| void collectStLdInsts(CnGNode* onode, ScObjFlds* scObjFlds); |
| |
| /** |
| * Collects (using connection graph) call instructions which use optimized object |
| * as a parameter. |
| * @param n - optimized object connection graph node Id, |
| * @param vc_insts - list of call instructions, |
| * @param vcids - list of call instructions ids. |
| */ |
| void collectCallInsts(U_32 n, Insts* vc_insts, ObjIds* vcids); |
| |
| /** |
| * Performs scalar replacement optimization for optimized object field usage. |
| * @param scfld - optimized object scalarizable field. |
| */ |
| void scalarizeOFldUsage(ScObjFld* scfld); |
| |
| /** |
| * Checks if an object from the specified list can be removed and its fields/elements scalarized. |
| * If an object cannot be optimized it is removed from the list. |
| * @param lnoids - list of new object CnG nodes Ids, |
| * @param lloids - list of load object CnG nodes Ids, |
| * @param check_loc - if <code>true</code> checks for local objects, |
| * if <code>false</code> checks for virtual call escaped objects. |
| */ |
| void checkOpndUsage(ObjIds* lnoids, ObjIds* lloids, bool check_loc); |
| |
| /** |
| * Checks if a tau operand may be removed/replaced. |
| * @param tau_inst - object CnG nodes Ids. |
| * @return <code>true</code> if tau operand may be removed; |
| * <code>false<code> otherwise. |
| */ |
| bool checkTauOpnd(Inst* tau_inst); |
| |
| /** |
| * Checks if an object can be removed and its fields/elements scalarized. |
| * @param lobjid - object CnG nodes Ids. |
| * @return <code>true</code> if an object is used only in ldflda or ldbase instructions; |
| * <code>false<code> otherwise. |
| */ |
| bool checkOpndUsage(U_32 lobjid); |
| |
| /** |
| * Performs checks for CnGNode operand using connection graph. |
| * @param scnode - CnG node of optimized operand |
| * @param check_loc - if <code>true</code> checks for local objects, |
| * if <code>false</code> checks for method call escaped objects. |
| * @return CnGNode* for operand that may be optimized; |
| * <code>NULL<code> otherwise. |
| */ |
| CnGNode* checkCnGtoScalarize(CnGNode* scnode, bool check_loc); |
| |
| /** |
| * Checks if there is a path in CFG from node where object is created by a nob_inst instruction |
| * to EXIT node and this object is not escaped to any method call on this path. |
| * @param nob_inst - object creation instruction. |
| * @return <code>execCount</code> of this path execution; |
| * <code>0<code> otherwise. |
| */ |
| double checkLocalPath(Inst* nob_inst); |
| |
| /** |
| * Checks if there is a path in CFG from node where object created by a nob_inst instruction |
| * to EXIT node and this object is not escaped to any method call. |
| * @param n - CFG node to scan, |
| * @param obId - escaped optimized object Id, |
| * @param cExecCount - current execCount. |
| * @return <code>execCount</code> the most value of <code>execCount</code> and |
| * checkNextNodes execution for next after n node. |
| */ |
| double checkNextNodes(Node* n, U_32 obId, double cExecCount); |
| |
| /** |
| * Checks flag and creates object before call instruction (if it was not created yet). |
| * @param vc_insts - list of call instructions optimized object is escaped to, |
| * @param objs - list of optimized object fields, |
| * @param ob_var_opnd - varOpnd replacing optimized object, |
| * @param oid - escaped optimized object Id. |
| */ |
| void restoreEOCreation(Insts* vc_insts, ScObjFlds* objs, VarOpnd* ob_var_opnd, U_32 oid); |
| |
| /** |
| * Removes specified instruction from ControlFlowGraph. |
| * If instruction can throw exception removes corresponding CFGEdge. |
| * @param reminst - removed instruction. |
| */ |
| void removeInst(Inst* reminst); |
| |
| /** |
| * Replaces first source operand of Op_MethodEnd instruction by NULL |
| * for scalar replacement optimized object. |
| * @param ob_id - optimized object Id. |
| */ |
| void fixMethodEndInsts(U_32 ob_id); |
| |
| /** |
| * Finds (using connection graph) load varOpnd that should be optimized with |
| * new object operand. |
| * @param vval - CnG node of target stvar instruction varOpnd. |
| * @return CnGNode* - found optimized load varOpnd CnG node |
| * <code>NULL</code> otherwise. |
| */ |
| CnGNode* getLObj(CnGNode* vval); |
| |
| /** |
| * Checks that all sources of optimized load varOpnd aren't null and |
| * satisfy to specified conditions. |
| * @param inst - ldvar instruction created optimized load varOpnd. |
| * @return <code>true</code> if satisfied; |
| * <code>false<code> otherwise. |
| */ |
| bool checkVVarSrcs(Inst* inst); |
| |
| /** |
| * Checks that optimized object type satisfied to specified types. |
| * @param otn - object type name. |
| * @return <code>true</code> if satisfied; |
| * <code>false<code> otherwise. |
| */ |
| bool checkObjectType(const char* otn); |
| |
| /** |
| * Checks that all load varOpnd fields are in new object field usage list. |
| * @param nscObjFlds - list of used fields of optimized new object, |
| * @param lscObjFlds - list of used fields of optimized load varOpnd. |
| * @return <code>true</code> if list of new object used field contains all |
| * load varOpnd used field; |
| * <code>false<code> otherwise. |
| */ |
| bool checkObjFlds(ScObjFlds* nscObjFlds, ScObjFlds* lscObjFlds); |
| |
| /** |
| * Removes check instructions for optimized load varOpnd. |
| * @param ob_id - optimized load variable operand Id. |
| */ |
| void fixCheckInsts(U_32 opId); |
| |
| /** |
| * Checks (using connection graph) if CnGNode operand has final fields and scalarizes them. |
| * @param onode - CnG node of optimized operand, |
| * @param scObjFlds - list to collect onode operand field usage. |
| */ |
| void checkToScalarizeFinalFiels(CnGNode* onode, ScObjFlds* scObjFlds); |
| |
| |
| void instrExam_processLdFieldAddr(Inst* inst); |
| void instrExam2_processLdFieldAddr(Inst* inst); |
| static void getLdFieldAddrInfo(Inst* inst, Type*& type, U_32& nType); |
| |
| }; |
| |
| } //namespace Jitrino |
| |
| #endif // _ESCANALYSIS_H_ |