Index: vm/jitrino/src/codegenerator/ipf/IpfCodeLayouter.cpp =================================================================== --- vm/jitrino/src/codegenerator/ipf/IpfCodeLayouter.cpp (revision 526661) +++ vm/jitrino/src/codegenerator/ipf/IpfCodeLayouter.cpp (working copy) @@ -45,6 +45,7 @@ CodeLayouter::CodeLayouter(Cfg &cfg) : mm(cfg.getMM()), cfg(cfg), + opndManager(cfg.getOpndManager()), chains(mm), visitedNodes(mm) { } @@ -107,7 +108,7 @@ IPF_LOG << " branch inst is " << IrPrinter::toString(branchInst); if (addr2node.find(addr) == addr2node.end()) { // this call has not been moved in outstanding node - callNode = new(mm) BbNode(mm, cfg.getNextNodeId(), 0); // create new node + callNode = new(mm) BbNode(mm, opndManager->getNextNodeId(), 0); // create new node callInst = new(mm) Inst(mm, INST_BRL13, CMPLT_BTYPE_CALL, cfg.getOpndManager()->getP0()); for (uint16 i=1; iaddOpnd(opnds[i]); callNode->addInst(callInst); // create and add call instruction @@ -399,7 +400,7 @@ void CodeLayouter::setBranchTargets() { - BbNode *node = (BbNode*) cfg.getEnterNode(); + BbNode *node = cfg.getEnterNode(); for(; node != NULL; node = node->getLayoutSucc()) { IPF_LOG << " node" << left << setw(3) << node->getId(); @@ -477,7 +478,7 @@ // create new node for unconditional branch on through edge target node // branch instruction will be inserted in fixUnconditionalBranch method - BbNode *branchNode = new(mm) BbNode(mm, cfg.getNextNodeId(), fallThroughNode->getExecCounter()); + BbNode *branchNode = new(mm) BbNode(mm, opndManager->getNextNodeId(), fallThroughNode->getExecCounter()); branchNode->setLayoutSucc(layoutSuccNode); // layout successor of current node becomes layoute successor of new node node->setLayoutSucc(branchNode); // the new node becomes layout successor of current node @@ -537,7 +538,7 @@ // Add branch to through edge target Opnd *p0 = cfg.getOpndManager()->getP0(); NodeRef *targetNode = cfg.getOpndManager()->newNodeRef(target); - node->addInst(new(mm) Inst(mm, INST_BR, CMPLT_WH_SPTK, CMPLT_PH_MANY, p0, targetNode)); + node->addInst(new(mm) Inst(mm, INST_BR, CMPLT_WH_SPTK, CMPLT_PH_FEW, p0, targetNode)); throughEdge->setEdgeKind(EDGE_BRANCH); IPF_LOG << " branch on node" << target->getId() << " added" << endl; Index: vm/jitrino/src/codegenerator/ipf/IpfCfg.cpp =================================================================== --- vm/jitrino/src/codegenerator/ipf/IpfCfg.cpp (revision 526661) +++ vm/jitrino/src/codegenerator/ipf/IpfCfg.cpp (working copy) @@ -17,6 +17,7 @@ /** * @author Intel, Konstantin M. Anisimov, Igor V. Chebykin + * @version $Revision: 1.2 $ * */ @@ -216,7 +217,6 @@ Cfg::Cfg(MemoryManager &mm, CompilationInterface &compilationInterface): mm(mm), compilationInterface(compilationInterface), - maxNodeId(0), enterNode(NULL), exitNode(NULL), searchResult(mm), @@ -229,13 +229,13 @@ NodeVector& Cfg::search(SearchKind searchKind) { - if(lastSearchKind == searchKind) return searchResult; + if (lastSearchKind == searchKind) return searchResult; lastSearchKind = searchKind; NodeSet visitedNodes(mm); searchResult.clear(); - switch(searchKind) { + switch (searchKind) { case SEARCH_DIRECT_ORDER : makeDirectOrdered(exitNode, visitedNodes); break; case SEARCH_POST_ORDER : makePostOrdered(enterNode, visitedNodes); break; case SEARCH_LAYOUT_ORDER : makeLayoutOrdered(); break; @@ -254,12 +254,12 @@ visitedNodes.insert(node); // mark node visited EdgeVector& inEdges = node->getInEdges(); // get inEdges - for(uint32 i=0; igetSource(); // get pred node - if(visitedNodes.count(pred) == 1) continue; // if it is already visited - ignore + for (uint32 i=0; igetSource(); // get pred node + if (visitedNodes.count(pred) == 1) continue; // if it is already visited - ignore makeDirectOrdered(pred, visitedNodes); // we have found unvisited pred - reenter } - searchResult.push_back(node); // all succs have been visited - place node in searchResult vector + searchResult.push_back(node); // all preds have been visited - place node in searchResult vector } //----------------------------------------------------------------------------------------// @@ -270,9 +270,9 @@ visitedNodes.insert(node); // mark node visited EdgeVector& outEdges = node->getOutEdges(); // get outEdges - for(uint32 i=0; igetTarget(); // get succ node - if(visitedNodes.count(succ) == 1) continue; // if it is already visited - ignore + for (uint32 i=0; igetTarget(); // get succ node + if (visitedNodes.count(succ) == 1) continue; // if it is already visited - ignore makePostOrdered(succ, visitedNodes); // we have found unvisited succ - reenter } searchResult.push_back(node); // all succs have been visited - place node in searchResult vector @@ -282,8 +282,8 @@ void Cfg::makeLayoutOrdered() { - BbNode *node = (BbNode *)getEnterNode(); - while(node != NULL) { + BbNode *node = getEnterNode(); + while (node != NULL) { searchResult.push_back(node); node = node->getLayoutSucc(); } @@ -291,3 +291,4 @@ } // IPF } // Jitrino + Index: vm/jitrino/src/codegenerator/ipf/include/IpfLiveManager.h =================================================================== --- vm/jitrino/src/codegenerator/ipf/include/IpfLiveManager.h (revision 0) +++ vm/jitrino/src/codegenerator/ipf/include/IpfLiveManager.h (revision 0) @@ -0,0 +1,112 @@ +/* + * 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, Konstantin M. Anisimov, Igor V. Chebykin + * @version $Revision: 1.1 $ + * + */ + +#ifndef IPFLIVEMANAGER_H_ +#define IPFLIVEMANAGER_H_ + +#include "IpfCfg.h" + +using namespace std; + +namespace Jitrino { +namespace IPF { + +//========================================================================================// +// QpNode +//========================================================================================// + +class QpNode { +public: + QpNode(QpNode*, QpMask); + void initLiveMask(); + void initCompMask(); + QpNode* getPredNode() { return predNode; } + QpMask getNodeMask() { return nodeMask; } + QpMask getCompMask() { return compMask; } + QpMask getLiveMask() { return liveMask; } + void setCompNode(QpNode *node) { compNode = node; } + void setNodeMask(QpMask mask) { nodeMask = mask; } + void orNodeMask(QpMask mask) { nodeMask |= mask; } + +protected: + QpNode *predNode; // predecessor in QpTree tree + QpNode *compNode; // qpNode that complements current one (NULL if there is no complement) + QpMask nodeMask; // predicates alive in current predicate space + QpMask compMask; // mask of compNode (to speed up "getCompMask" method) + QpMask liveMask; // mask of prdicate spaces interfering with current (all + // predicates except complementing ones) +}; + +//========================================================================================// +// QpTree +//========================================================================================// + +class QpTree { +public: + QpTree(Cfg&); + void makeQpTree(InstVector&); + QpNode* findQpNode(Opnd*); + void removeQpNode(Opnd*); + void printQpTree(); + +protected: + QpNode* makeQpNode(QpNode*, Opnd*); + void printQpNode(QpMap::iterator, uint16); + bool isDefOnePred(Inst*); + bool isDefTwoPreds(Inst*); + bool isDefComps(Inst*); + + Cfg &cfg; + MemoryManager &mm; + QpMap qpMap; // map containing qpNodes for current node + QpMask slot; // current available position in mask + RegOpnd *p0; // opnd representing p0 +}; + +//========================================================================================// +// LiveManager +//========================================================================================// + +class LiveManager { +public: + LiveManager(Cfg&); + void init(Node*); + void def(Inst*); + void use(Inst*); + QpMask getLiveMask(RegOpnd*); + void printQpTree() { qpTree.printQpTree(); } + RegOpndSet& getLiveSet() { return liveSet; } + +protected: + void useOpnd(QpNode*, RegOpnd*); + bool defOpnd(QpNode*, RegOpnd*); + + Cfg &cfg; + QpTree qpTree; // tree definind relations between qualifying predicates in node + RegOpndSet liveSet; // current liveSet used in liveness analysis (DCE, register allocator ...) +}; + +} // IPF +} // Jitrino + +#endif /*IPFLIVEMANAGER_H_*/ Index: vm/jitrino/src/codegenerator/ipf/include/IpfOpndManager.h =================================================================== --- vm/jitrino/src/codegenerator/ipf/include/IpfOpndManager.h (revision 526661) +++ vm/jitrino/src/codegenerator/ipf/include/IpfOpndManager.h (working copy) @@ -35,6 +35,7 @@ class Opnd; class RegOpnd; +class Cfg; //========================================================================================// // RegStack @@ -138,10 +139,10 @@ class StackInfo { public: StackInfo(); - int32 rpBak; // num of gr or stack offset containing return pointer (e.g. r33) - int32 prBak; // num of gr or stack offset containing predicate registers (e.g. r34) - int32 pfsBak; // num of gr or stack offset containing AR.PFS (e.g. r35) - int32 unatBak; // num of gr or stack offset containing AR.UNAT (e.g. r36) + int32 rpBak; // gr num or stack offset containing return pointer (e.g. r33) + int32 prBak; // gr num or stack offset containing predicate registers (e.g. r34) + int32 pfsBak; // gr num or stack offset containing AR.PFS (e.g. r35) + int32 unatBak; // gr num or stack offset containing AR.UNAT (e.g. r36) int32 savedBase; // mem stack offset of first saved gr (bytes) uint32 savedGrMask; // mask of preserved grs saved on stack uint32 savedFrMask; // mask of preserved frs saved on stack @@ -155,47 +156,49 @@ class OpndManager : public RegStack, public MemStack, public StackInfo { public: - OpndManager(MemoryManager&, CompilationInterface&); + OpndManager(MemoryManager&, CompilationInterface&); //----------------------------------------------------------------------------// // Opnd constructors //----------------------------------------------------------------------------// - Opnd *newOpnd(OpndKind = OPND_INVALID); - RegOpnd *newRegOpnd(OpndKind, DataKind, int32 = LOCATION_INVALID); - Opnd *newImm(int64 = 0); - ConstantRef *newConstantRef(Constant*, DataKind = DATA_CONST_REF); - NodeRef *newNodeRef(BbNode* = NULL); - MethodRef *newMethodRef(MethodDesc* = NULL); + Opnd *newOpnd(OpndKind = OPND_INVALID); + RegOpnd *newRegOpnd(OpndKind, DataKind, int32 = LOCATION_INVALID); + Opnd *newImm(int64 = 0); + ConstantRef *newConstantRef(Constant*, DataKind = DATA_CONST_REF); + NodeRef *newNodeRef(BbNode* = NULL); + MethodRef *newMethodRef(MethodDesc* = NULL); + Opnd *newInArg(OpndKind, DataKind, uint32); + uint16 getFpArgsNum(); //----------------------------------------------------------------------------// // set / get methods //----------------------------------------------------------------------------// - RegOpnd *getR0(); - RegOpnd *getR0(RegOpnd*); - RegOpnd *getF0(); - RegOpnd *getF1(); + RegOpnd *getR0(); + RegOpnd *getR0(RegOpnd*); + RegOpnd *getF0(); + RegOpnd *getF1(); - RegOpnd *getP0(); - RegOpnd *getB0(); - RegOpnd *getR12(); - RegOpnd *getR8(); - RegOpnd *getF8(); - RegOpnd *getTau(); + RegOpnd *getP0(); + RegOpnd *getB0(); + RegOpnd *getR12(); + RegOpnd *getR8(); + RegOpnd *getF8(); + RegOpnd *getTau(); - void setContainCall(bool containCall_) { containCall = containCall_; } - bool getContainCall() { return containCall; } - - uint getNumOpnds() { return maxOpndId; } + void setContainCall(bool containCall_) { containCall = containCall_; } + bool getContainCall() { return containCall; } + uint16 getNextNodeId() { return maxNodeId++; } + BbNode *getPrologNode() { return prologNode; } //----------------------------------------------------------------------------// // Reg allocation support //----------------------------------------------------------------------------// - int32 newLocation(OpndKind, DataKind, RegBitSet, bool); - int32 newScratchReg(OpndKind, RegBitSet&); - int32 newPreservReg(OpndKind, RegBitSet&); + int32 newLocation(OpndKind, DataKind, RegBitSet, bool); + int32 newScratchReg(OpndKind, RegBitSet&); + int32 newPreservReg(OpndKind, RegBitSet&); //----------------------------------------------------------------------------// // Compressed references @@ -214,27 +217,32 @@ // Misc //----------------------------------------------------------------------------// - int64 getElemBaseOffset(); - void printStackInfo(); - void saveThisArg(); - void initSavedBase(); - void initMemStackSize(); + void insertProlog(Cfg&); + int64 getElemBaseOffset(); + void printStackInfo(); + void saveThisArg(); + void initSavedBase(); + void initMemStackSize(); + RegOpndVector& getInArgs() { return inArgs; } protected: MemoryManager &mm; CompilationInterface &compilationInterface; - int32 maxOpndId; // used for creating new opnds + uint16 maxOpndId; // used for creating new opnds + uint16 maxNodeId; // used for creating new nodes + RegOpndVector inArgs; // input args vector + BbNode *prologNode; - RegOpnd *r0; // 0 (8 bytes unsigned) - RegOpnd *f0; // 0.0 - RegOpnd *f1; // 1.0 - RegOpnd *p0; // true - RegOpnd *b0; // return address - RegOpnd *r12; // stack pointer - RegOpnd *r8; // return value (general) - RegOpnd *f8; // return value (floating point) - RegOpnd *tau; // opnd ignored + RegOpnd *r0; // 0 (8 bytes unsigned) + RegOpnd *f0; // 0.0 + RegOpnd *f1; // 1.0 + RegOpnd *p0; // true + RegOpnd *b0; // return address + RegOpnd *r12; // stack pointer + RegOpnd *r8; // return value (general) + RegOpnd *f8; // return value (floating point) + RegOpnd *tau; // opnd ignored RegOpnd *heapBase; // Reg opnd containing base for references decompression Opnd *heapBaseImm; // Imm opnd containing base for references decompression Index: vm/jitrino/src/codegenerator/ipf/include/IpfInstrumentator.h =================================================================== --- vm/jitrino/src/codegenerator/ipf/include/IpfInstrumentator.h (revision 0) +++ vm/jitrino/src/codegenerator/ipf/include/IpfInstrumentator.h (revision 0) @@ -0,0 +1,58 @@ +/* + * 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, Konstantin M. Anisimov, Igor V. Chebykin + * @version $Revision: 1.1 $ + * + */ + +#ifndef IPFINSTRUMENTATOR_H_ +#define IPFINSTRUMENTATOR_H_ + +#include "IpfCfg.h" +#include "IpfOpndManager.h" +#include "DrlVMInterface.h" + +namespace Jitrino { +namespace IPF { + +//=======================================================================================// +// Instrumentator +//========================================================================================// + +class Instrumentator { +public: + Instrumentator(Cfg&); + void instrument(); + static void methodStart(Method_Handle); + static void methodEnd(Method_Handle); + +protected: + void instrumentStart(); + void instrumentEnd(); + void genNativeCall(uint64, InstVector&); + + MemoryManager &mm; + OpndManager *opndManager; + Cfg &cfg; +}; + +} // IPF +} // Jitrino + +#endif /*IPFINSTRUMENTATOR_H_*/ Index: vm/jitrino/src/codegenerator/ipf/include/IpfCodeLayouter.h =================================================================== --- vm/jitrino/src/codegenerator/ipf/include/IpfCodeLayouter.h (revision 526661) +++ vm/jitrino/src/codegenerator/ipf/include/IpfCodeLayouter.h (working copy) @@ -67,6 +67,7 @@ MemoryManager &mm; Cfg &cfg; + OpndManager *opndManager; ChainList chains; NodeSet visitedNodes; }; Index: vm/jitrino/src/codegenerator/ipf/include/IpfCfg.h =================================================================== --- vm/jitrino/src/codegenerator/ipf/include/IpfCfg.h (revision 526661) +++ vm/jitrino/src/codegenerator/ipf/include/IpfCfg.h (working copy) @@ -137,7 +137,7 @@ public: Opnd(uint32, OpndKind=OPND_INVALID, DataKind=DATA_INVALID, int64=0); - uint32 getId() { return id; } + uint16 getId() { return id; } OpndKind getOpndKind() { return opndKind; } DataKind getDataKind() { return dataKind; } void setValue(int64 value_) { value = value_; } @@ -147,19 +147,20 @@ bool isGReg() { return IpfType::isGReg(opndKind); } bool isFReg() { return IpfType::isFReg(opndKind); } bool isImm() { return IpfType::isImm(opndKind); } + bool isQp() { return opndKind == OPND_P_REG; } bool isFloating() { return IpfType::isFloating(dataKind); } bool isSigned() { return IpfType::isSigned(dataKind); } int16 getSize() { return IpfType::getSize(dataKind); } bool isWritable(); bool isConstant(); bool isMem(); + bool isImm(int); - bool isFoldableImm(int16 size) { return isFoldableImm(value, size); } - bool isImm(int); + bool isFoldableImm(int16 size) { return isFoldableImm(value, size); } static bool isFoldableImm(int64 value, int16 size); protected: - uint32 id; + uint16 id; OpndKind opndKind; DataKind dataKind; int64 value; @@ -176,13 +177,18 @@ void setLocation(int32 value_) { value = value_; } int32 getLocation() { return value; } + QpMask getQpMask() { return qpMask; } + void andQpMask(QpMask mask) { qpMask &= mask; } + void orQpMask(QpMask mask) { qpMask |= mask; } + bool isAlive(QpMask mask) { return mask & qpMask; } + void incSpillCost(uint32 spillCost_) { spillCost += spillCost_; } uint32 getSpillCost() { return spillCost; } RegOpndSet &getDepOpnds() { return depOpnds; } void insertDepOpnds(RegOpndSet &opnds) { depOpnds.insert(opnds.begin(), opnds.end()); } void insertDepOpnd(RegOpnd*); void setCrossCallSite(bool crossCallSite_) { crossCallSite = crossCallSite_; } - bool getCrossCallSite() { return crossCallSite; } + bool isCrossCallSite() { return crossCallSite; } Int2OpndMap &getCoalesceCands() { return coalesceCands; } void addCoalesceCand(uint32 execCnt, RegOpnd *opnd) { coalesceCands.insert(make_pair(execCnt, opnd)); } @@ -190,6 +196,7 @@ virtual ~RegOpnd() {} protected: + QpMask qpMask; // mask of predicate spaces opnd alive in // These fields are for register allocation algorithm uint32 spillCost; // number of opnd uses RegOpndSet depOpnds; // opnds which can not be placed in the same reg with the opnd @@ -358,29 +365,31 @@ Node *getDispatchNode(); void mergeOutLiveSets(RegOpndSet &resultSet); + uint16 getId() { return id; } void setExecCounter(uint32 execCounter_) { execCounter = execCounter_; } uint32 getExecCounter() { return execCounter; } + void setNodeKind(NodeKind kind_) { nodeKind = kind_; } + NodeKind getNodeKind() { return nodeKind; } EdgeVector &getInEdges() { return inEdges; } EdgeVector &getOutEdges() { return outEdges; } - void setNodeKind(NodeKind kind_) { nodeKind = kind_; } - NodeKind getNodeKind() { return nodeKind; } - void setId(uint32 id_) { id = id_; } - uint32 getId() { return id; } void setLiveSet(RegOpndSet& liveSet_) { liveSet = liveSet_; } + void setLoopHeader(Node *loopHeader_) { loopHeader = loopHeader_; } + Node *getLoopHeader() { return loopHeader; } RegOpndSet &getLiveSet() { return liveSet; } void clearLiveSet() { liveSet.clear(); } - void setLoopHeader(Node *loopHeader_) { loopHeader = loopHeader_; } - Node *getLoopHeader() { return loopHeader; } + void setVisited(bool visited_) { visited = visited_; } + bool isVisited() { return visited; } bool isBb() { return nodeKind == NODE_BB; } protected: - uint32 id; // node unique Id + uint16 id; // node unique Id uint32 execCounter; // profile info (how many times the node executes) NodeKind nodeKind; // EdgeVector inEdges; // in edges list EdgeVector outEdges; // out edges list Node *loopHeader; // header of loop containing this node, if NULL - node is not in loop RegOpndSet liveSet; // set of opnds alive on node enter + bool visited; // flag used in node iterating algorithms (live analysis) }; //========================================================================================// @@ -393,10 +402,10 @@ void addInst(Inst *inst) { insts.push_back(inst); } void removeInst(Inst *inst) { insts.erase(find(insts.begin(),insts.end(),inst)); } InstVector &getInsts() { return insts; } + void setLayoutSucc(BbNode *layoutSucc_) { layoutSucc = layoutSucc_; } + BbNode *getLayoutSucc() { return layoutSucc; } void setAddress(uint64 address_) { address = address_; } uint64 getAddress() { return address; } - void setLayoutSucc(BbNode *layoutSucc_) { layoutSucc = layoutSucc_; } - BbNode *getLayoutSucc() { return layoutSucc; } uint64 getInstAddr(Inst *inst) { return ((uint64)address + inst->getAddr()); } protected: @@ -414,16 +423,14 @@ Cfg(MemoryManager &mm, CompilationInterface &compilationInterface); NodeVector &search(SearchKind searchKind); - MemoryManager &getMM() { return mm; } - CompilationInterface &getCompilationInterface() { return compilationInterface; } - uint16 getNextNodeId() { return maxNodeId++; } - uint16 getMaxNodeId() { return maxNodeId; } - void setEnterNode(Node *enterNode_) { enterNode = enterNode_; } - void setExitNode(Node *exitNode_) { exitNode = exitNode_; } - Node *getEnterNode() { return enterNode; } - Node *getExitNode() { return exitNode; } - OpndManager *getOpndManager() { return opndManager; } - MethodDesc *getMethodDesc() { return compilationInterface.getMethodToCompile(); } + MemoryManager &getMM() { return mm; } + CompilationInterface &getCompilationInterface() { return compilationInterface; } + void setEnterNode(BbNode *node) { enterNode = node; } + void setExitNode(BbNode *node) { exitNode = node; } + BbNode *getEnterNode() { return enterNode; } + BbNode *getExitNode() { return exitNode; } + OpndManager *getOpndManager() { return opndManager; } + MethodDesc *getMethodDesc() { return compilationInterface.getMethodToCompile(); } protected: void makePostOrdered(Node *node, NodeSet &visitedNodes); @@ -433,10 +440,9 @@ MemoryManager &mm; CompilationInterface &compilationInterface; - uint16 maxNodeId; OpndManager *opndManager; - Node *enterNode; - Node *exitNode; + BbNode *enterNode; + BbNode *exitNode; NodeVector searchResult; SearchKind lastSearchKind; }; Index: vm/jitrino/src/codegenerator/ipf/include/IpfLiveAnalyzer.h =================================================================== --- vm/jitrino/src/codegenerator/ipf/include/IpfLiveAnalyzer.h (revision 526661) +++ vm/jitrino/src/codegenerator/ipf/include/IpfLiveAnalyzer.h (working copy) @@ -24,6 +24,7 @@ #define IPFLIVEANALYZER_H_ #include "IpfCfg.h" +#include "IpfLiveManager.h" using namespace std; @@ -36,18 +37,22 @@ class LiveAnalyzer { public: - LiveAnalyzer(Cfg&); - void makeLiveSets(bool); + LiveAnalyzer(Cfg&); + void analyze(); + void dce(); + void verify(); - static void updateLiveSet(RegOpndSet&, Inst*); - static void defOpnds(RegOpndSet&, Inst*); - static void useOpnds(RegOpndSet&, Inst*); - protected: - bool analyzeNode(Node*); + bool analyzeNode(Node*); + void pushPreds(Node*); + bool isInstDead(Inst*); - Cfg &cfg; - bool verify; + Cfg &cfg; + MemoryManager &mm; + NodeVector workSet; // nodes to be iterated during liveSets calculation or dce + LiveManager liveManager; // Live Manager evaluates current live set from inst to inst + RegOpndSet &liveSet; // reference on current live set in liveManager + bool dceFlag; // make dce if flag is on }; } // IPF Index: vm/jitrino/src/codegenerator/ipf/include/IpfCodeSelector.h =================================================================== --- vm/jitrino/src/codegenerator/ipf/include/IpfCodeSelector.h (revision 526661) +++ vm/jitrino/src/codegenerator/ipf/include/IpfCodeSelector.h (working copy) @@ -103,6 +103,7 @@ NodeVector &nodes; OpndVector &opnds; CompilationInterface &compilationInterface; + OpndManager *opndManager; }; //========================================================================================// @@ -390,7 +391,6 @@ OpndVector &opnds; CompilationInterface &compilationInterface; OpndManager *opndManager; - int32 numFpInArgs; RegOpnd *p0; }; Index: vm/jitrino/src/codegenerator/ipf/include/IpfIrPrinter.h =================================================================== --- vm/jitrino/src/codegenerator/ipf/include/IpfIrPrinter.h (revision 526661) +++ vm/jitrino/src/codegenerator/ipf/include/IpfIrPrinter.h (working copy) @@ -27,6 +27,7 @@ #include #include #include "IpfCfg.h" +#include "IpfLiveManager.h" namespace Jitrino { namespace IPF { @@ -42,8 +43,10 @@ void printLayoutDot(char*); void printAsm(ostream&); + static string toString(MethodDesc*); static string toString(Inst*); static string toString(Opnd*); + static string toString(QpNode*); static string toString(OpndSet&); static string toString(RegOpndSet&); static string toString(OpndVector&); @@ -54,6 +57,7 @@ static string toString(EdgeKind); static string toString(OpndKind); static string toString(DataKind); + static string boolString(uint64, uint16=16); protected: void printEdgeDot(Edge*); @@ -67,6 +71,7 @@ Cfg &cfg; ostream *os; // output stream ofstream *ofs; // file output stream + char logDir[500]; }; } // IPF Index: vm/jitrino/src/codegenerator/ipf/include/IpfRuntimeSupport.h =================================================================== --- vm/jitrino/src/codegenerator/ipf/include/IpfRuntimeSupport.h (revision 526661) +++ vm/jitrino/src/codegenerator/ipf/include/IpfRuntimeSupport.h (working copy) @@ -108,7 +108,8 @@ // Exception registration void registerExceptionHandlers(); - void makeRegion(Byte* startAddr, Byte* endAddr, Node* dispatchNode); + void makeRegion(BbNode*, BbNode*, Node*); + void inserFakeLastNode(NodeVector&); RegionVector tryRegions; @@ -116,7 +117,7 @@ StackInfo *makeStackInfo(); // Build root set and extend bases live range - void newSafePoint(BbNode*, Inst*, RegOpndSet&); + void newSafePoint(BbNode*, Inst*, RegOpndSet&, QpMask); void defMptr(BbNode*, Inst*); void mergeBase(BbNode*, Inst*, RegOpnd*, RegOpnd*); void replaceBase(Inst*, Opnd*, Opnd*); Index: vm/jitrino/src/codegenerator/ipf/include/IpfCodeGenerator.h =================================================================== --- vm/jitrino/src/codegenerator/ipf/include/IpfCodeGenerator.h (revision 526661) +++ vm/jitrino/src/codegenerator/ipf/include/IpfCodeGenerator.h (working copy) @@ -43,8 +43,9 @@ protected: CompilationInterface *compilationInterface; MethodDesc *methodDesc; + Cfg *cfg; -}; +}; } // IPF } // Jitrino Index: vm/jitrino/src/codegenerator/ipf/include/IpfType.h =================================================================== --- vm/jitrino/src/codegenerator/ipf/include/IpfType.h (revision 526661) +++ vm/jitrino/src/codegenerator/ipf/include/IpfType.h (working copy) @@ -54,6 +54,7 @@ class BbNode; class Edge; class Cfg; +class QpNode; //========================================================================================// // Defines @@ -100,16 +101,18 @@ #define ROOT_SET_HEADER_SIZE 4 // header size in root set info block #define SAFE_POINT_HEADER_SIZE 12 // header size in safe points info block -#define LOG_ON 1 // Log for Code Generator is on -#define VERIFY_ON 1 // verification for Code Generator is on +#define MAX_QP_MASK 0xffffffffffffffff // max value of predicate mask used in LiveManager + +#define LOG_ON 0 // Log for Code Generator is on +#define VERIFY_ON 0 // verification for Code Generator is on #define LOG_OUT Log::out() -#define STAT_ON 0 // Log for statistic +#define STAT_ON 0 // Log for statistic #define IPF_ERROR "ERROR in file " << __FILE__ << " line " << __LINE__ << " " #define IPF_LOG if (LOG_ON) LOG_OUT #define IPF_STAT if (STAT_ON) LOG_OUT #define IPF_ERR cerr << IPF_ERROR -#define IPF_ASSERT(condition) if (VERIFY_ON && !(condition)) { IPF_ERR << (#condition) << endl; } +#define IPF_ASSERT(condition) if (LOG_ON && !(condition)) { IPF_ERR << (#condition) << endl; } extern bool ipfLogIsOn; extern bool ipfVerifyIsOn; @@ -191,22 +194,22 @@ // Typedefs //========================================================================================// -typedef StlVector< Opnd* > OpndVector; -typedef StlVector< RegOpnd* > RegOpndVector; -typedef StlVector< Inst* > InstVector; -typedef StlVector< Node* > NodeVector; -typedef StlVector< Edge* > EdgeVector; -typedef StlVector< uint32 > Uint32Vector; -typedef StlList< Inst* > InstList; -typedef StlList< Node* > NodeList; -typedef StlList< Edge* > EdgeList; -typedef StlSet< Opnd* > OpndSet; -typedef StlSet< RegOpnd* > RegOpndSet; -typedef StlSet< Node* > NodeSet; -typedef StlMap< RegOpnd*, RegOpnd* > RegOpnd2RegOpndMap; -typedef StlMap< Inst*, RegOpndSet > Inst2RegOpndSetMap; -typedef StlMap< uint64, RegOpndSet > Uint642RegOpndSetMap; -typedef bitset< NUM_G_REG > RegBitSet; +typedef StlVector< Opnd* > OpndVector; +typedef StlVector< RegOpnd* > RegOpndVector; +typedef StlVector< Inst* > InstVector; +typedef StlVector< Node* > NodeVector; +typedef StlVector< Edge* > EdgeVector; +typedef StlVector< uint32 > Uint32Vector; +typedef StlList< Inst* > InstList; +typedef StlList< Node* > NodeList; +typedef StlList< Edge* > EdgeList; +typedef StlSet< Opnd* > OpndSet; +typedef StlSet< RegOpnd* > RegOpndSet; +typedef StlSet< Node* > NodeSet; +typedef StlMap< RegOpnd*, RegOpnd* > RegOpnd2RegOpndMap; +typedef StlMap< Inst*, RegOpndSet > Inst2RegOpndSetMap; +typedef StlMap< uint64, RegOpndSet > Uint642RegOpndSetMap; +typedef bitset< NUM_G_REG > RegBitSet; typedef StlMultiMap > Int2OpndMap; typedef NodeVector::iterator NodeIterator; @@ -223,12 +226,15 @@ typedef Uint642RegOpndSetMap::iterator Uint642RegOpndSetMapIterator; typedef NodeList Chain; -typedef StlList< Chain* > ChainList; +typedef StlList< Chain* > ChainList; typedef StlMultiMap< uint32, Chain*, greater < uint32 > > ChainMap; typedef Chain::iterator ChainIterator; typedef ChainList::iterator ChainListIterator; typedef ChainMap::iterator ChainMapIterator; +typedef StlMultiMap QpMap; +typedef uint64 QpMask; + //========================================================================================// // IpfType //========================================================================================// Index: vm/jitrino/src/codegenerator/ipf/include/IpfRegisterAllocator.h =================================================================== --- vm/jitrino/src/codegenerator/ipf/include/IpfRegisterAllocator.h (revision 526661) +++ vm/jitrino/src/codegenerator/ipf/include/IpfRegisterAllocator.h (working copy) @@ -24,6 +24,7 @@ #define IPFREGISTERALLOCATOR_H_ #include "IpfCfg.h" +#include "IpfLiveManager.h" namespace Jitrino { namespace IPF { @@ -43,8 +44,8 @@ void assignLocations(); void assignLocation(RegOpnd*); - void updateAllocSet(Opnd*, uint32); - void checkCallSite(Inst*); + void updateAllocSet(Opnd*, uint32, QpMask); + void checkCallSite(Inst*, QpMask); void checkCoalescing(uint32, Inst*); void removeSameRegMoves(); @@ -52,8 +53,9 @@ MemoryManager &mm; Cfg &cfg; OpndManager *opndManager; + LiveManager liveManager; RegOpndSet allocSet; // set of all opnds that need allocation - RegOpndSet liveSet; // set of opnds alive in current node (buildInterferenceMatrix) + RegOpndSet &liveSet; // set of opnds alive in current node }; } // IPF Index: vm/jitrino/src/codegenerator/ipf/IpfLiveAnalyzer.cpp =================================================================== --- vm/jitrino/src/codegenerator/ipf/IpfLiveAnalyzer.cpp (revision 526661) +++ vm/jitrino/src/codegenerator/ipf/IpfLiveAnalyzer.cpp (working copy) @@ -17,6 +17,7 @@ /** * @author Intel, Konstantin M. Anisimov, Igor V. Chebykin + * @version $Revision: 1.2 $ * */ @@ -31,139 +32,152 @@ // LiveAnalyzer //========================================================================================// -LiveAnalyzer::LiveAnalyzer(Cfg &cfg_) : cfg(cfg_) { } +LiveAnalyzer::LiveAnalyzer(Cfg &cfg) : + cfg(cfg), + mm(cfg.getMM()), + workSet(mm), + liveManager(cfg), + liveSet(liveManager.getLiveSet()), + dceFlag(false) { +} //----------------------------------------------------------------------------------------// -void LiveAnalyzer::makeLiveSets(bool verify_) { +void LiveAnalyzer::analyze() { -// IPF_LOG << endl; - verify = verify_; - NodeVector &nodes = cfg.search(SEARCH_POST_ORDER); // get postordered node list + NodeVector &nodes = cfg.search(SEARCH_POST_ORDER); // get postordered node list + for (int16 i=nodes.size()-1; i>=0; i--) { // iterate nodes + Node *node = nodes[i]; // + node->setVisited(false); // mark node unvisited + if (dceFlag == false) node->clearLiveSet(); // clear node's live set + workSet.push_back(node); // put node in workSet (reverse order) + } - // clear live sets for all nodes - if (!verify) { - for(uint16 i=0; iclearLiveSet(); + while (workSet.size() > 0) { // while there is node to analyze + Node *node = workSet.back(); // get last workSet node + node->setVisited(true); // mark the node visited + workSet.pop_back(); // remove the node from workSet + if (analyzeNode(node) == false) { // node's live set has changed - live sets of predecessor need evaluation + pushPreds(node); // put predecessors in workSet } } - // make new live sets for all nodes - bool flag = true; - while (flag == true) { - flag = false; - for(uint16 i=0; igetLiveSet(); - node->mergeOutLiveSets(currLiveSet); // put in the live set merged live sets of successors + IPF_LOG << endl << " Dead code:" << endl; + dceFlag = true; + analyze(); + dceFlag = false; +} + +//----------------------------------------------------------------------------------------// +// check if node's liveSets coincide with calculated ones +// check if liveSet of Enter node is empty (except inArgs including implicit arg b0) -// if (LOG_ON) { -// IPF_LOG << " node" << node->getId() << " successors:"; -// EdgeVector &edges = node->getOutEdges(); -// for (uint16 i=0; igetTarget(); -// Node *loopHeader = succ->getLoopHeader(); -// IPF_LOG << " " << succ->getId(); -// if (loopHeader != NULL) IPF_LOG << "(" << loopHeader->getId() << ")"; -// } -// IPF_LOG << " exit live set: " << IrPrinter::toString(currLiveSet) << endl; -// } - - // If node is not BB - currLiveSet is not going to change - if(node->getNodeKind() != NODE_BB) { -// IPF_LOG << " node is not BB - live set is not changed" << endl; - if (oldLiveSet == currLiveSet) return true; // if live set has not changed - nothing to do - - node->setLiveSet(currLiveSet); // Set currLiveSet for the current node - return false; // and continue - } - - InstVector &insts = ((BbNode *)node)->getInsts(); - InstIterator currInst = insts.end()-1; - InstIterator firstInst = insts.begin()-1; +void LiveAnalyzer::verify() { - for(; currInst>firstInst; currInst--) { - updateLiveSet(currLiveSet, *currInst); + NodeVector &nodes = cfg.search(SEARCH_POST_ORDER); // get nodes postorder + + for (uint16 i=0; igetId() << endl; // throw error message + } } - if (oldLiveSet == currLiveSet) return true; // if live set has not changed - nothing to do - if (verify) { - IPF_LOG << "ERROR node" << node->getId() << endl; - IPF_LOG << " old live set: " << IrPrinter::toString(oldLiveSet) << endl; - IPF_LOG << " new live set: " << IrPrinter::toString(currLiveSet) << endl; + RegOpndSet enterLiveSet = cfg.getEnterNode()->getLiveSet(); // get liveSet of Enter node + RegOpndVector &inArgs = cfg.getOpndManager()->getInArgs(); // get inArgs + for (uint16 i=0; igetB0()); // remove b0 from enterLiveSet + if (enterLiveSet.size() == 0) return; // if enterLiveSet is empty - Ok + + IPF_ERR << " size " << enterLiveSet.size() << endl; + for (RegOpndSet::iterator it=enterLiveSet.begin(); it!=enterLiveSet.end(); it++) { + IPF_ERR << " alive opnd on method enter " << IrPrinter::toString(*it) + << " " << IrPrinter::toString(cfg.getMethodDesc()) << endl; } - node->setLiveSet(currLiveSet); // set currLiveSet for the current node - return false; } //----------------------------------------------------------------------------------------// -// Remove dst and insert qp and src opnds in live set. -// If qp is not "p0" do not remove dst opnd from live set, -// because if the inst is not executed dst opnd will stay alive +// recalculate live set for the node +// if it has not changed - return true, else - return false -void LiveAnalyzer::updateLiveSet(RegOpndSet &liveSet, Inst *inst) { +bool LiveAnalyzer::analyzeNode(Node *node) { - OpndVector &opnds = inst->getOpnds(); // get instruction's opnds - uint16 numDst = inst->getNumDst(); // number of dst opnds (qp has index 0) - bool isP0 = (opnds[0]->getValue() == 0); // is instruction qp is p0 + liveManager.init(node); // init LiveManager with current node + if (LOG_ON) { + IPF_LOG << endl << " Qp Tree for node" << node->getId() << endl; + liveManager.printQpTree(); + } + + RegOpndSet &oldLiveSet = node->getLiveSet(); // get current node live set (on node enter) + if (node->getNodeKind() != NODE_BB) { // liveSet is not going to change + if (oldLiveSet == liveSet) return true; // if live set has not changed - nothing to do + node->setLiveSet(liveSet); // set liveSet for the current node + return false; // live set of the node has changed + } - // remove dst opnds from live set - for(uint16 i=1; isP0 && i<=numDst; i++) { - if (opnds[i]->isWritable()) liveSet.erase((RegOpnd *)opnds[i]); + InstVector &insts = ((BbNode *)node)->getInsts(); + for(int16 i=insts.size()-1; i>=0; i--) { // iterate through node insts postorder + Inst *inst = insts[i]; // + if (dceFlag && isInstDead(inst)) { // if dce is activated and inst is dead + IPF_LOG << " node" << setw(3) << left << node->getId(); + IPF_LOG << IrPrinter::toString(inst) << endl; + insts.erase(insts.begin()+i); // remove inst from InstVector of current node + liveManager.def(inst); // change liveSet according with inst def + } else { // + liveManager.def(inst); // change liveSet according with inst def + liveManager.use(inst); // change liveSet according with inst use + } } - // insert qp opnd in live set - if (opnds[0]->isWritable()) liveSet.insert((RegOpnd *)opnds[0]); - - // insert src opnds in live set - for(uint16 i=numDst+1; iisWritable()) liveSet.insert((RegOpnd *)opnds[i]); - } -} + if (oldLiveSet == liveSet) return true; // if live set has not changed - nothing to do + node->setLiveSet(liveSet); // set liveSet for the current node + return false; // live set of the node has changed +} //----------------------------------------------------------------------------------------// -// Remove dst opnds from live set. -// If qp is not "p0" do not remove dst opnd from live set, -// because if the inst is not executed dst opnd will stay alive +// push all predecessors of the node in workSet (ignore preds which are in workSet already) -void LiveAnalyzer::defOpnds(RegOpndSet &liveSet, Inst *inst) { +void LiveAnalyzer::pushPreds(Node *node) { - OpndVector &opnds = inst->getOpnds(); // get instruction's opnds - uint16 numDst = inst->getNumDst(); // number of dst opnds (qp has index 0) - bool isP0 = (opnds[0]->getValue() == 0); // is instruction qp is p0 - - // remove dst opnds from live set - for(uint16 i=1; isP0 && i<=numDst; i++) { - if (opnds[i]->isWritable()) liveSet.erase((RegOpnd *)opnds[i]); + EdgeVector &edges = node->getInEdges(); // get in edges + for (uint16 i=0; igetSource(); // get predecessor + if (pred->isVisited() == false) continue; // if predecessor is in workSet - ignore + workSet.push_back(pred); // push predecessor in workSet + pred->setVisited(false); // mark it unvisited } -} +} //----------------------------------------------------------------------------------------// -// Insert qp and src opnds in live set. +// Check if instruction can be removed from inst vector. +// Do not remove instruction having "side effects" (like "call") -void LiveAnalyzer::useOpnds(RegOpndSet &liveSet, Inst *inst) { +bool LiveAnalyzer::isInstDead(Inst *inst) { + + if (inst->isCall()) return false; // "call" inst is never dead + if (inst->getInstCode() == INST_ALLOC) return false; // "alloc" inst is never dead - OpndVector &opnds = inst->getOpnds(); // get instruction's opnds - uint16 numDst = inst->getNumDst(); // number of dst opnds (qp has index 0) + uint16 numDst = inst->getNumDst(); // get num of dst opnds + if (numDst == 0) return false; // if there is no dst opnds - ignore - // insert qp opnd in live set - if (opnds[0]->isWritable()) liveSet.insert((RegOpnd *)opnds[0]); - - // insert src opnds in live set - for(uint16 i=numDst+1; iisWritable()) liveSet.insert((RegOpnd *)opnds[i]); - } -} + OpndVector &opnds = inst->getOpnds(); // get inst opnds + RegOpnd *qp = (RegOpnd *)opnds[0]; // get qp of the inst + QpMask mask = liveManager.getLiveMask(qp); // get mask for this qp space + for (uint16 i=1; iisAlive(mask)) return false; // if dst is alive - inst is alive + } + return true; // there is no alive dst opnd - inst is dead +} } // IPF } // Jitrino Index: vm/jitrino/src/codegenerator/ipf/IpfInstCodeSelector.cpp =================================================================== --- vm/jitrino/src/codegenerator/ipf/IpfInstCodeSelector.cpp (revision 526661) +++ vm/jitrino/src/codegenerator/ipf/IpfInstCodeSelector.cpp (working copy) @@ -53,7 +53,6 @@ compilationInterface(compilationInterface_) { opndManager = cfg.getOpndManager(); - numFpInArgs = 0; p0 = opndManager->getP0(); } @@ -689,7 +688,7 @@ CG_OpndHandle *IpfInstCodeSelector::convToInt(ConvertToIntOp::Types opType, bool isSigned, - bool isZeroExtend, + bool isZeroExtend, ConvertToIntOp::OverflowMod ovfMod, Type *dstType, CG_OpndHandle *src_) { @@ -968,25 +967,21 @@ CG_OpndHandle *IpfInstCodeSelector::defArg(uint32 inArgPosition, Type *type) { - DataKind dataKind = toDataKind(type->tag); - OpndKind opndKind = toOpndKind(type->tag); - int32 location = LOCATION_INVALID; - bool isFp = type->isFloatingPoint(); - if (inArgPosition < MAX_REG_ARG) { - if (isFp) location = F_INARG_BASE + numFpInArgs++; - else location = opndManager->newInReg(inArgPosition); - } else { - location = opndManager->newInSlot(inArgPosition); // location is area local offset - } + OpndKind opndKind = toOpndKind(type->tag); + DataKind dataKind = toDataKind(type->tag); - RegOpnd *arg = opndManager->newRegOpnd(opndKind, dataKind, location); + Opnd *arg = opndManager->newInArg(opndKind, dataKind, inArgPosition); IPF_LOG << " defArg " << IrPrinter::toString(arg) << " " << type->getName() << endl; - if (isFp) { - RegOpnd *newarg = opndManager->newRegOpnd(opndKind, dataKind); - addNewInst(INST_MOV, p0, newarg, arg); // if fp arg crosses call site + if (arg->isFloating()) { + BbNode *prologNode = opndManager->getPrologNode(); + RegOpnd *newarg = opndManager->newRegOpnd(opndKind, dataKind); + Inst *inst = new(mm) Inst(mm, INST_MOV, p0, newarg, arg); + prologNode->addInst(inst); arg = newarg; // it will be moved on preserved reg + + IPF_LOG << " " << IrPrinter::toString(inst) << endl; } return arg; Index: vm/jitrino/src/codegenerator/ipf/IpfCodeSelector.cpp =================================================================== --- vm/jitrino/src/codegenerator/ipf/IpfCodeSelector.cpp (revision 526661) +++ vm/jitrino/src/codegenerator/ipf/IpfCodeSelector.cpp (working copy) @@ -120,7 +120,8 @@ cfg(cfg), nodes(nodes), opnds(opnds), - compilationInterface(compilationInterface) { + compilationInterface(compilationInterface), + opndManager(cfg.getOpndManager()) { } //----------------------------------------------------------------------------------------// @@ -129,7 +130,7 @@ uint32 numOutEdges, double cnt) { - Node *node = new(mm) Node(mm, cfg.getNextNodeId(), (uint32) cnt, NODE_DISPATCH); + Node *node = new(mm) Node(mm, opndManager->getNextNodeId(), (uint32) cnt, NODE_DISPATCH); nodes.push_back(node); IPF_LOG << endl << " Generate Dispatch node" << node->getId() << endl; @@ -144,7 +145,7 @@ BlockCodeSelector &codeSelector, double cnt) { - BbNode *node = new(mm) BbNode(mm, cfg.getNextNodeId(), (uint32)cnt); + BbNode *node = new(mm) BbNode(mm, opndManager->getNextNodeId(), (uint32)cnt); nodes.push_back(node); if(blockKind == Prolog) cfg.setEnterNode(node); @@ -162,7 +163,7 @@ uint32 numOutEdges, double cnt) { - Node *node = new(mm) Node(mm, cfg.getNextNodeId(), (uint32) cnt, NODE_UNWIND); + Node *node = new(mm) Node(mm, opndManager->getNextNodeId(), (uint32) cnt, NODE_UNWIND); nodes.push_back(node); IPF_LOG << endl << " Generate Unwind node" << node->getId() << endl; @@ -173,7 +174,7 @@ uint32 IpfCfgCodeSelector::genExitNode(uint32 numInEdges, double cnt) { - BbNode *node = new(mm) BbNode(mm, cfg.getNextNodeId(), (uint32) cnt); + BbNode *node = new(mm) BbNode(mm, opndManager->getNextNodeId(), (uint32) cnt); nodes.push_back(node); cfg.setExitNode(node); @@ -265,6 +266,7 @@ } //--------------------------------------------------------------------------------// +// edge from try region to dispatch node void IpfCfgCodeSelector::genExceptionEdge(uint32 tailNodeId, uint32 headNodeId, @@ -273,13 +275,14 @@ Node *tailNode = nodes[tailNodeId]; Node *headNode = nodes[headNodeId]; - IPF_LOG << " Generate Exception edge node" << tailNodeId; - IPF_LOG << " -> node" << headNodeId << endl; + IPF_LOG << " Generate Exception edge node" << tailNode->getId(); + IPF_LOG << " -> node" << headNode->getId() << endl; Edge *edge = new(mm) Edge(tailNode, headNode, prob, EDGE_DISPATCH); edge->insert(); } //----------------------------------------------------------------------------------------// +// edge from dispatch node to exception handler void IpfCfgCodeSelector::genCatchEdge(uint32 tailNodeId, uint32 headNodeId, Index: vm/jitrino/src/codegenerator/ipf/IpfIrPrinter.cpp =================================================================== --- vm/jitrino/src/codegenerator/ipf/IpfIrPrinter.cpp (revision 526661) +++ vm/jitrino/src/codegenerator/ipf/IpfIrPrinter.cpp (working copy) @@ -21,6 +21,8 @@ */ #include "IpfIrPrinter.h" +#include "CompilationContext.h" +#include "PMFAction.h" namespace Jitrino { namespace IPF { @@ -39,12 +41,24 @@ mm(cfg_.getMM()), cfg(cfg_), ofs(NULL) { + + if (Log::isEnabled() == false) return; + + CompilationContext *cc = CompilationContext::getCurrentContext(); + SessionAction *session = cc->getCurrentSessionAction(); + LogStream &logStream = session->log(LogStream::CT); + strcpy(logDir, logStream.getFileName()); + int len = strlen(logDir); + logDir[len - 6] = 0; } //----------------------------------------------------------------------------------------// -void IrPrinter::printLayoutDot(char *logName) { +void IrPrinter::printLayoutDot(char *logFile) { + char logName[500]; + strcpy(logName, logDir); + strcat(logName, logFile); ofs = new(mm) ofstream(logName); BbNode *node = (BbNode *)cfg.getEnterNode(); @@ -66,8 +80,11 @@ //----------------------------------------------------------------------------------------// -void IrPrinter::printCfgDot(char *logName) { +void IrPrinter::printCfgDot(char *logFile) { + char logName[500]; + strcpy(logName, logDir); + strcat(logName, logFile); ofs = new(mm) ofstream(logName); NodeVector &nodes = cfg.search(SEARCH_POST_ORDER); @@ -90,7 +107,7 @@ os = &os_; - BbNode *node = (BbNode *)cfg.getEnterNode(); + BbNode *node = cfg.getEnterNode(); *os << endl; *os << "----------- Code dump ----------------------------------------" << endl; @@ -164,7 +181,6 @@ *ofs << " fontpath=\"c:\\winnt\\fonts\";" << ::std::endl; *ofs << " node [shape=record,fontname=\"Courier\",fontsize=9];" << ::std::endl; *ofs << " edge [fontname=\"Courier\",fontsize=9];" << ::std::endl; - } //----------------------------------------------------------------------------------------// @@ -327,6 +343,15 @@ //----------------------------------------------------------------------------------------// +string IrPrinter::toString(QpNode *qpNode) { + ostringstream oss; + oss << "mask: " << boolString(qpNode->getNodeMask()) << " comp: " << boolString(qpNode->getCompMask()); + oss << " dead: " << boolString(qpNode->getLiveMask()); + return oss.str(); +} + +//----------------------------------------------------------------------------------------// + string IrPrinter::toString(OpndSet &opndSet) { ostringstream oss; @@ -402,6 +427,21 @@ //----------------------------------------------------------------------------------------// +string IrPrinter::toString(MethodDesc *methodDesc) { + + ostringstream oss; + + if (methodDesc->getParentType() != NULL) { + oss << methodDesc->getParentType()->getName() << "."; + } + oss << methodDesc->getName(); + oss << methodDesc->getSignatureString(); + + return oss.str(); +} + +//----------------------------------------------------------------------------------------// + string IrPrinter::toString(NodeKind nodeKind) { string s; @@ -487,5 +527,17 @@ return s; } +//----------------------------------------------------------------------------// + +string IrPrinter::boolString(uint64 mask, uint16 size) { + uint64 m = 1 << size - 1; + ostringstream oss; + for (int i=0; i>= 1) { + if (mask & m) oss << "1"; + else oss << "0"; + } + return oss.str(); +} + } // IPF } // Jitrino Index: vm/jitrino/src/codegenerator/ipf/IpfEncoder.cpp =================================================================== --- vm/jitrino/src/codegenerator/ipf/IpfEncoder.cpp (revision 526661) +++ vm/jitrino/src/codegenerator/ipf/IpfEncoder.cpp (working copy) @@ -17,7 +17,7 @@ /** * @author Intel, Konstantin M. Anisimov, Igor V. Chebykin - * @version $Revision$ + * @version $Revision: 1.2 $ * */ @@ -1688,9 +1688,7 @@ p[1] |= s[2] << 23; // write to callAddr - VMInterface::rewriteCodeBlock((Byte *)callAddr, - (Byte *)p, - IPF_BUNDLE_SIZE); + VMInterface::rewriteCodeBlock((Byte *)callAddr, (Byte *)p, IPF_BUNDLE_SIZE); // IPF_LOG << "Patch brl.call to 0x" << hex // << (uint64)methodAddr << " at 0x" << (uint64)callAddr << "\n" Index: vm/jitrino/src/codegenerator/ipf/IpfRuntimeSupport.cpp =================================================================== --- vm/jitrino/src/codegenerator/ipf/IpfRuntimeSupport.cpp (revision 526661) +++ vm/jitrino/src/codegenerator/ipf/IpfRuntimeSupport.cpp (working copy) @@ -124,35 +124,34 @@ void RuntimeSupport::registerExceptionHandlers() { - Node *dispatchNode = cfg.getEnterNode()->getDispatchNode(); NodeVector &nodes = cfg.search(SEARCH_LAYOUT_ORDER); - Byte *startAddr = (Byte *)((BbNode *)cfg.getEnterNode())->getAddress(); + BbNode *regionStart = (BbNode *)nodes[0]; + Node *dispatchNode = regionStart->getDispatchNode(); + + inserFakeLastNode(nodes); + for (uint16 i=1; igetNodeKind() != NODE_BB) continue; // ignore non BB node + BbNode *node = (BbNode *)nodes[i]; - for(uint16 i=1; igetNodeKind() != NODE_BB) continue; // ignore non BB node + if (dispatchNode != node->getDispatchNode()) { // if current node protected by another dispatch + makeRegion(regionStart, node, dispatchNode); // create new try region + regionStart = node; // current node is first node of new region (if any) + dispatchNode = node->getDispatchNode(); // current dispatch protects new region + } + } - if(dispatchNode != nodes[i]->getDispatchNode()) { - Byte *endAddr = (Byte *)(((BbNode *)nodes[i])->getAddress()); - Node *lastNode = nodes[i-1]; + makeRegion(regionStart, (BbNode *)nodes.back(), dispatchNode); // create new try region - IPF_LOG << " region detected, last node is BB" << lastNode->getId() << endl; - - makeRegion(startAddr, endAddr, dispatchNode); - startAddr = (Byte *)((BbNode *)nodes[i])->getAddress(); - dispatchNode = nodes[i]->getDispatchNode(); - } - } MethodDesc* md = compilationInterface.getMethodToCompile(); md->setNumExceptionHandler(tryRegions.size()); - - IPF_LOG << " region registration:" << endl; - if(tryRegions.size() == 0) { + IPF_LOG << endl << " region registration:" << endl; + if (tryRegions.size() == 0) { IPF_LOG << " no catch handlers detected" << endl; return; } IPF_LOG << " start end handler exception objIsDead" << endl; - for(uint16 i=0; isetExceptionHandlerInfo(i, tryRegions[i]->startAddr, tryRegions[i]->endAddr, @@ -170,39 +169,65 @@ //----------------------------------------------------------------------------------------// -void RuntimeSupport::makeRegion(Byte *startAddr, Byte *endAddr, Node *dispatchNode) { +void RuntimeSupport::makeRegion(BbNode *regionStart, BbNode *regionEnd, Node *dispatchNode) { - if(dispatchNode == NULL) { - IPF_LOG << " there is no dispatch node - region is not created" << endl; - return; - } + if (dispatchNode == NULL) return; // it is not a try region - if(dispatchNode->getNodeKind() != NODE_DISPATCH) return; + IPF_LOG << " try region detected: node" << regionStart->getId() << " - node" << regionEnd->getId(); - IPF_LOG << " dispatch node is BB" << dispatchNode->getId() << endl; - EdgeVector& outEdges = dispatchNode->getOutEdges(); // get out edges + if (dispatchNode->getNodeKind() != NODE_DISPATCH) { + IPF_LOG << ", there is no catch block" << endl; + return; + } + + IPF_LOG << ", dispatch: node" << dispatchNode->getId(); + + Byte *startAddr = (Byte *)regionStart->getAddress(); + Byte *endAddr = (Byte *)regionEnd->getAddress(); + EdgeVector &outEdges = dispatchNode->getOutEdges(); // get out edges sort(outEdges.begin(), outEdges.end(), greaterPriority); // sort them by Priority - for(uint16 i=0; igetEdgeKind() == EDGE_EXCEPTION) { + for (uint16 i=0; igetEdgeKind() == EDGE_EXCEPTION) { - Byte *handlerAddr = (Byte *)((BbNode *)outEdges[i]->getTarget())->getAddress(); - ObjectType *exceptionType = (ObjectType *)((ExceptionEdge *)outEdges[i])->getExceptionType(); + BbNode *handlerNode = (BbNode *)edge->getTarget(); + Byte *handlerAddr = (Byte *)handlerNode->getAddress(); + ObjectType *exceptionType = (ObjectType *)((ExceptionEdge *)edge)->getExceptionType(); TryRegion *region = new(mm) TryRegion(startAddr, endAddr, handlerAddr, exceptionType, false); tryRegions.push_back(region); - IPF_LOG << " region created for handler BB" << outEdges[i]->getTarget()->getId(); - IPF_LOG << " priority: " << ((ExceptionEdge *)outEdges[i])->getPriority(); - IPF_LOG << " " << exceptionType->getName() << endl; + IPF_LOG << ", handler: node" << handlerNode->getId(); + IPF_LOG << ", priority: " << ((ExceptionEdge *)edge)->getPriority(); + IPF_LOG << ", " << exceptionType->getName() << endl; } - if(outEdges[i]->getEdgeKind() == EDGE_DISPATCH) { - makeRegion(startAddr, endAddr, outEdges[i]->getTarget()); + if (edge->getEdgeKind() == EDGE_DISPATCH) { + makeRegion(regionStart, regionEnd, edge->getTarget()); } } } //----------------------------------------------------------------------------------------// + +void RuntimeSupport::inserFakeLastNode(NodeVector &nodes) { + + BbNode *lastNode = (BbNode *)nodes.back(); + InstVector &insts = lastNode->getInsts(); + uint64 address = 0; + + if (insts.size() < 1) address = lastNode->getAddress(); + else address = lastNode->getInstAddr(insts.back()); + + uint64 mask = 0xfffffffffffffff0; + address = (address & mask) + 0x10; + + BbNode *node = new(mm) BbNode(mm, 0, 0); + node->setAddress(address); + nodes.push_back(node); +} + +//----------------------------------------------------------------------------------------// // Make info block which will be used in stack unwind routine //----------------------------------------------------------------------------------------// @@ -260,17 +285,17 @@ void RuntimeSupport::buildRootSet() { - NodeVector &nodes = cfg.search(SEARCH_POST_ORDER); - RegOpndSet liveSet(mm); + LiveManager liveManager(cfg); + RegOpndSet &liveSet = liveManager.getLiveSet(); + NodeVector &nodes = cfg.search(SEARCH_POST_ORDER); for (uint16 i=0; iisBb() == false) continue; // non BB node - ignore - liveSet.clear(); // clear live set - nodes[i]->mergeOutLiveSets(liveSet); // put in the live set merged live sets of successors + BbNode *node = (BbNode *)nodes[i]; + liveManager.init(node); - BbNode *node = (BbNode *)nodes[i]; InstVector &insts = node->getInsts(); InstIterator currInst = insts.end()-1; InstIterator firstInst = insts.begin()-1; @@ -278,24 +303,26 @@ for (; currInst>firstInst; currInst--) { Inst *inst = *currInst; - LiveAnalyzer::defOpnds(liveSet, inst); // update liveSet for currInst - if (Encoder::isBranchCallInst(inst)) { // if currInst is "call" (only safe point we have) - newSafePoint(node, inst, liveSet); // insert (safe point->liveSet) pair in sp2LiveSet - } - LiveAnalyzer::useOpnds(liveSet, inst); // update liveSet for currInst + liveManager.def(inst); // update liveSet for currInst + if (inst->isCall()) { // if inst is "call" (only safe point we have) + RegOpnd *qp = (RegOpnd *)inst->getOpnd(0); + QpMask mask = liveManager.getLiveMask(qp); + newSafePoint(node, inst, liveSet, mask); // insert (safe point->liveSet) pair in sp2LiveSet + } // + liveManager.use(inst); // update liveSet for currInst defMptr(node, inst); // build mptr->base dependency for currInst } } if (LOG_ON) { - IPF_LOG << endl << " Build mptr to base map" << endl; + IPF_LOG << endl << " Build mptr to base map" << endl; for (MptrDefMapIterator it=mptr2def.begin(); it!=mptr2def.end(); it++) { IPF_LOG << " " << IrPrinter::toString(it->first) << "->"; IPF_LOG << IrPrinter::toString(it->second.base) << endl; } } - IPF_LOG << endl << " Safe point list" << endl; + IPF_LOG << endl << " Safe point list" << endl; // set mptr->base relations (vector SafePoint.alivePtrs will contain base after each mptr) // and extend bases live ranges for (uint16 i=0; i alive mptrs&bases) // - extend base live ranges -void RuntimeSupport::newSafePoint(BbNode *node, Inst *spInst, RegOpndSet &liveSet) { +void RuntimeSupport::newSafePoint(BbNode *node, Inst *spInst, RegOpndSet &liveSet, QpMask mask) { safePoints.push_back(SafePoint(mm, node, spInst)); // create record for current safe point RegOpndVector &ptrs = safePoints.back().alivePtrs; // get vector for mptrs and bases alive on the safe point for (RegOpndSetIterator it=liveSet.begin(); it!=liveSet.end(); it++) { RegOpnd *opnd = *it; + if (opnd->isAlive(mask) == false) continue; if (opnd->getDataKind() == DATA_MPTR) { ptrs.push_back(opnd); ptrs.push_back(NULL); @@ -418,7 +446,7 @@ void RuntimeSupport::insertBases(Inst *inst, RegOpndVector &ptrs) { - IPF_LOG << " alive pointers:"; + IPF_LOG << " alive pointers:"; for (uint16 i=0; igetDataKind() == DATA_MPTR) { @@ -444,7 +472,7 @@ void RuntimeSupport::makeRootSetInfo(Uint32Vector &info) { - IPF_LOG << " Safe points list:" << endl; + IPF_LOG << " Safe points list:" << endl; for (uint16 i=0; igetMethodToCompile(); IrPrinter irPrinter(*cfg); - if(LOG_ON) { - const char *methodName = methodDesc->getName(); - const char *methodTypeName = (methodDesc->getParentType()!=NULL - ? methodDesc->getParentType()->getName() - : ""); - const char * methodSignature = methodDesc->getSignatureString(); - - IPF_LOG << endl << methodTypeName << "." << methodName << methodSignature << endl; - } - - //compilationInterface->lockMethodData(); - + IPF_LOG << endl << IrPrinter::toString(methodDesc) << endl; IPF_LOG << endl << "=========== Stage: Code Selector =============================" << endl; IpfMethodCodeSelector ipfMethodCodeSelector(*cfg, *compilationInterface); methodCodeSelector->selectCode(ipfMethodCodeSelector); methodDesc = ipfMethodCodeSelector.getMethodDesc(); - cfg->getOpndManager()->initCompBases((BbNode *)cfg->getEnterNode()); + cfg->getOpndManager()->insertProlog(*cfg); cfg->getOpndManager()->saveThisArg(); - if(LOG_ON) irPrinter.printCfgDot("/cs.dot"); + if(LOG_ON) irPrinter.printCfgDot("cs.dot"); - IPF_LOG << endl << "=========== Stage: Code Instrumentation ======================" << endl; +// IPF_LOG << endl << "=========== Stage: Code Instrumentation ======================" << endl; // Instrumentator instrumentator(*cfg); // instrumentator.instrument(); IPF_LOG << endl << "=========== Stage: Code Layouter =============================" << endl; CodeLayouter codeLayouter(*cfg); codeLayouter.layout(); - if(LOG_ON) irPrinter.printCfgDot("/cl.dot"); + if(LOG_ON) irPrinter.printCfgDot("cl.dot"); if(LOG_ON) irPrinter.printAsm(LOG_OUT); - IPF_LOG << endl << "=========== Stage: Liveness analyzis =========================" << endl; + IPF_LOG << endl << "=========== Stage: Liveness analysis =========================" << endl; LiveAnalyzer liveAnalyzer(*cfg); - liveAnalyzer.makeLiveSets(false); + liveAnalyzer.analyze(); + liveAnalyzer.dce(); - IPF_LOG << endl << "=========== Stage: Dead Code Eliminator ======================" << endl; - Dce dce(*cfg); - dce.eliminate(); - liveAnalyzer.makeLiveSets(false); - IPF_LOG << endl << "=========== Stage: Build GC Root Set =========================" << endl; RuntimeSupport runtimeSupport(*cfg, *compilationInterface); runtimeSupport.buildRootSet(); @@ -139,8 +123,6 @@ IPF_LOG << endl << "=========== Stage: Make Runtime Info =========================" << endl; runtimeSupport.makeRuntimeInfo(); - - //compilationInterface->unlockMethodData(); if(ret) IPF_LOG << endl << "=========== Compilation Successful ===========================" << endl; else IPF_LOG << endl << "=========== Compilation Failed ===============================" << endl; Index: vm/jitrino/src/codegenerator/ipf/IpfRegisterAllocator.cpp =================================================================== --- vm/jitrino/src/codegenerator/ipf/IpfRegisterAllocator.cpp (revision 526661) +++ vm/jitrino/src/codegenerator/ipf/IpfRegisterAllocator.cpp (working copy) @@ -23,7 +23,6 @@ #include "IpfRegisterAllocator.h" #include "IpfIrPrinter.h" #include "IpfOpndManager.h" -#include "IpfLiveAnalyzer.h" #include namespace Jitrino { @@ -38,10 +37,10 @@ RegisterAllocator::RegisterAllocator(Cfg &cfg) : mm(cfg.getMM()), cfg(cfg), + opndManager(cfg.getOpndManager()), + liveManager(cfg), allocSet(mm), - liveSet(mm) { - - opndManager = cfg.getOpndManager(); + liveSet(liveManager.getLiveSet()) { } //----------------------------------------------------------------------------------------// @@ -52,7 +51,7 @@ buildInterferenceMatrix(); removeSelfDep(); - IPF_LOG << endl << " Assign Locations" << endl; + IPF_LOG << endl << " Assign Locations (# - cross call site)" << endl; assignLocations(); IPF_LOG << endl << " Remove Usless \"mov\" Instructions" << endl; @@ -68,12 +67,11 @@ NodeVector &nodes = cfg.search(SEARCH_POST_ORDER); for(uint16 i=0; iisBb() == false) continue; // ignore non BB nodes + if(nodes[i]->isBb() == false) continue; // ignore non BB nodes - liveSet.clear(); // clear live set - nodes[i]->mergeOutLiveSets(liveSet); // put in the live set merged live sets of successors + BbNode *node = (BbNode *)nodes[i]; + liveManager.init(node); - BbNode *node = (BbNode *)nodes[i]; uint32 execCounter = node->getExecCounter(); InstIterator currInst = node->getInsts().end()-1; InstIterator firstInst = node->getInsts().begin()-1; @@ -81,21 +79,23 @@ for (; currInst>firstInst; currInst--) { Inst *inst = *currInst; - uint16 numDst = inst->getNumDst(); // number of dst opnds (qp has index 0) - OpndVector& opnds = inst->getOpnds(); // get inst's opnds + uint16 numDst = inst->getNumDst(); // number of dst opnds (qp has index 0) + OpndVector& opnds = inst->getOpnds(); // get inst's opnds + RegOpnd *qp = (RegOpnd *) opnds[0]; + QpMask mask = liveManager.getLiveMask(qp); checkCoalescing(execCounter, inst); - LiveAnalyzer::defOpnds(liveSet, inst); // remove dst opnds from live set - checkCallSite(inst); // if currInst is "call" - all alive opnds cross call site - for(uint16 i=1; i<=numDst; i++) { // for each dst opnd - updateAllocSet(opnds[i], execCounter); // insert in allocSet and add live set in dep list + liveManager.def(inst); // remove dst opnds from live set + checkCallSite(inst, mask); // if currInst is "call" - all alive opnds cross call site + for(uint16 i=1; i<=numDst; i++) { // for each dst opnd + updateAllocSet(opnds[i], execCounter, mask); // insert in allocSet and add live set in dep list } - LiveAnalyzer::useOpnds(liveSet, inst); // add src opnds in live set - updateAllocSet(opnds[0], execCounter); // insert in allocSet pq opnd and add alive qps in dep list - for (uint16 i=numDst+1; igetDepOpnds().erase(*it); } - if(LOG_ON) { - IPF_LOG << endl << " Opnd dependensies " << endl; - for(RegOpndSetIterator it=allocSet.begin(); it!=allocSet.end(); it++) { + if (LOG_ON) { + IPF_LOG << endl << " Opnd dependensies" << endl; + for (RegOpndSetIterator it=allocSet.begin(); it!=allocSet.end(); it++) { RegOpnd *opnd = *it; - IPF_LOG << " " << setw(4) << left << IrPrinter::toString(opnd) << " depends on: "; - IPF_LOG << IrPrinter::toString(opnd->getDepOpnds()) << endl; + IPF_LOG << " " << setw(4) << left << IrPrinter::toString(opnd); + IPF_LOG << " depends on: " << IrPrinter::toString(opnd->getDepOpnds()) << endl; } } } @@ -155,7 +155,8 @@ RegOpnd *opnd = opndVector[i]; if (opnd->getLocation() != LOCATION_INVALID) continue; // opnd has already had location - IPF_LOG << " " << left << setw(5) << IrPrinter::toString(opnd); + IPF_LOG << " " << left << setw(5) << IrPrinter::toString(opnd); + IPF_LOG << (opnd->isCrossCallSite() ? "#" : " "); assignLocation(opnd); // assign location for current opnd IPF_LOG << " after assignment " << left << setw(5) << IrPrinter::toString(opnd); IPF_LOG << " spill cost: " << opnd->getSpillCost() << endl; @@ -163,8 +164,7 @@ } //----------------------------------------------------------------------------------------// -// remove useless move insts: -// mov r8 = r8 +// remove useless move insts. Like this "mov r8 = r8" void RegisterAllocator::removeSameRegMoves() { @@ -183,7 +183,7 @@ if (dst->getValue() != src->getValue()) { it++; continue; } // if opnds allocated on different regs - ignore it = insts.erase(it); - IPF_LOG << " node" << left << setw(4) << node->getId() << IrPrinter::toString(inst) << endl; + IPF_LOG << " node" << left << setw(4) << node->getId() << IrPrinter::toString(inst) << endl; } } } @@ -195,11 +195,10 @@ OpndKind opndKind = target->getOpndKind(); DataKind dataKind = target->getDataKind(); - bool isPreserved = target->getCrossCallSite(); + bool isPreserved = target->isCrossCallSite(); - // build mask of used regs (already assigned opnds) - RegBitSet usedMask; - RegOpndSet &depOpnds = target->getDepOpnds(); + RegBitSet usedMask; // mask of regs which already used by dep opnds + RegOpndSet &depOpnds = target->getDepOpnds(); // target can not be assigned on reg used by depOpnds for (RegOpndSet::iterator it=depOpnds.begin(); it!=depOpnds.end(); it++) { RegOpnd *opnd = *it; int32 location = opnd->getLocation(); // get location of dep opnd @@ -207,25 +206,24 @@ usedMask[location] = true; // mark reg busy } - // try to find opnd to coalesce on - Int2OpndMap &coalesceCands = target->getCoalesceCands(); + Int2OpndMap &coalesceCands = target->getCoalesceCands(); // opnds used in inst like: move target = opnd for (Int2OpndMap::iterator it=coalesceCands.begin(); it!=coalesceCands.end(); it++) { - RegOpnd *opnd = it->second; - int32 location = opnd->getValue(); - if (location > NUM_G_REG) continue; - if (isPreserved && (opnd->getCrossCallSite()==false)) continue; - if (usedMask[location] == true) continue; - target->setLocation(location); + RegOpnd *cls = it->second; + int32 location = cls->getValue(); // get location of coalesce candidate + if (location > NUM_G_REG) continue; // opnd is not allocated (or allocated on stack) + if (isPreserved && !cls->isCrossCallSite()) continue; // target must be preserved, but cls is scratch + if (usedMask[location] == true) continue; // target can not be allocated on cls location + target->setLocation(location); // assign target new location return; } int32 location = opndManager->newLocation(opndKind, dataKind, usedMask, isPreserved); - target->setLocation(location); // set location + target->setLocation(location); // assign target new location } //----------------------------------------------------------------------------------------// -void RegisterAllocator::updateAllocSet(Opnd *cand_, uint32 execCounter) { +void RegisterAllocator::updateAllocSet(Opnd *cand_, uint32 execCounter, QpMask mask) { if (cand_->isReg() == false) return; // imm - it does not need allocation if (cand_->isMem() == true) return; // mem stack - it does not need allocation @@ -238,6 +236,7 @@ // add current live set in opnd dep list (they must be placed on different regs) for (RegOpndSetIterator it=liveSet.begin(); it!=liveSet.end(); it++) { RegOpnd *opnd = *it; + if (opnd->isAlive(mask) == false) continue; cand->insertDepOpnd(opnd); // cand depends on curr opnd from live set opnd->insertDepOpnd(cand); // curr opnd from live set depends on cand } @@ -246,15 +245,13 @@ //----------------------------------------------------------------------------------------// // Check if current inst is "call" and mark all opnds in liveSet as crossing call site -void RegisterAllocator::checkCallSite(Inst *inst) { +void RegisterAllocator::checkCallSite(Inst *inst, QpMask mask) { - if(Encoder::isBranchCallInst(inst) == false) return; // opnd does not crass call site - - IPF_LOG << " these opnds cross call site: "; - IPF_LOG << IrPrinter::toString(liveSet) << endl; - - for(RegOpndSetIterator it=liveSet.begin(); it!=liveSet.end(); it++) { - (*it)->setCrossCallSite(true); + if(inst->isCall() == false) return; // it is not call site + for(RegOpndSet::iterator it=liveSet.begin(); it!=liveSet.end(); it++) { + RegOpnd *opnd = *it; + if (opnd->isAlive(mask) == false) continue; + opnd->setCrossCallSite(true); } } Index: vm/jitrino/src/codegenerator/ipf/IpfLiveManager.cpp =================================================================== --- vm/jitrino/src/codegenerator/ipf/IpfLiveManager.cpp (revision 0) +++ vm/jitrino/src/codegenerator/ipf/IpfLiveManager.cpp (revision 0) @@ -0,0 +1,332 @@ +/* + * 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, Konstantin M. Anisimov, Igor V. Chebykin + * @version $Revision: 1.1 $ + * + */ + +#include "IpfLiveAnalyzer.h" +#include "IpfIrPrinter.h" +#include "IpfOpndManager.h" + +namespace Jitrino { +namespace IPF { + +//========================================================================================// +// QpNode +//========================================================================================// + +QpNode::QpNode(QpNode *predNode, QpMask nodeMask) : + predNode(predNode), + compNode(NULL), + nodeMask(nodeMask), + compMask(0), + liveMask(0) { + + QpNode *qpNode = predNode; + while (qpNode != NULL) { // iterate through all predecessors of the node + qpNode->orNodeMask(nodeMask); // add bits of this nodeMask in predecessor's nodeMasks + qpNode = qpNode->getPredNode(); // get next predecessor + } +} + +//----------------------------------------------------------------------------------------// +// make mask of all predicate spaces interfering with current one. These are all spaces +// except complementing ones + +void QpNode::initLiveMask() { + + QpNode *qpNode = this; + liveMask = 0; + while (qpNode != NULL) { + QpMask mask = qpNode->getCompMask(); // get nodeMask of complemening to current space + if (mask != MAX_QP_MASK) liveMask |= mask; // if there is complementing space (is not MAX_QP_MASK) - add masks + qpNode = qpNode->getPredNode(); // get next predecessor + } // + liveMask = ~liveMask; // this qpNode interfere with all others except complementing ones +} + +//----------------------------------------------------------------------------------------// +// if qpNode has complement node - get its nodeMask (just to speed up "getCompMask" method) +// else - set all ones in compMask + +void QpNode::initCompMask() { + + if (compNode == NULL) compMask = MAX_QP_MASK; + else compMask = compNode->getNodeMask(); +} + +//========================================================================================// +// QpTree +//========================================================================================// + +QpTree::QpTree(Cfg &cfg) : + cfg(cfg), + mm(cfg.getMM()), + qpMap(mm), + slot(0), + p0(cfg.getOpndManager()->getP0()) { + + qpMap.insert( make_pair(p0, new(mm) QpNode(NULL, MAX_QP_MASK)) ); // make root qpNode +} + +//----------------------------------------------------------------------------------------// +// build qpMap determining qp->qpNode relations. If qp is defined several times - the tree +// contains several entryes corresponding to the qp. + +void QpTree::makeQpTree(InstVector &insts) { + + IPF_ASSERT(qpMap.size() == 1); + + slot = 1; // init slot (position in mask) + for (InstVector::iterator it=insts.begin(); it!=insts.end(); it++) { + Inst *inst = *it; // iterate insts + + if (isDefOnePred(inst)) { // if inst defs one predicate opnd + OpndVector &opnds = inst->getOpnds(); // get opnds of the inst + QpNode *qpNode = findQpNode(opnds[0]); // inst qp is predecessor for predicates defined in the inst + makeQpNode(qpNode, opnds[2]); // make qpNode for the predicate opnd (it is always second one) + continue; + } + + if (isDefTwoPreds(inst)) { // if inst defs two predicate opnds + OpndVector &opnds = inst->getOpnds(); // get opnds of the inst + QpNode *qpNode = findQpNode(opnds[0]); // inst qp is predecessor for predicates defined in the inst + QpNode *p1Node = makeQpNode(qpNode, opnds[1]); // make qpNode for first predicate opnd + QpNode *p2Node = makeQpNode(qpNode, opnds[2]); // make qpNode for second predicate opnd + + if (isDefComps(inst) == false) continue; // inst does not define mutually complemen predicates - continue + if (p1Node != NULL) p1Node->setCompNode(p2Node); // p2Node complements p1Node + if (p2Node != NULL) p2Node->setCompNode(p1Node); // p1Node complements p2Node + } + } + + for (QpMap::iterator it=qpMap.begin(); it!=qpMap.end(); it++) { + QpNode *qpNode = it->second; // iterate all qpNodes in the tree + qpNode->initCompMask(); // set comp mask (to speed up getCompMask) + } + + for (QpMap::iterator it=qpMap.begin(); it!=qpMap.end(); it++) { + QpNode *qpNode = it->second; // iterate all qpNodes in the tree + qpNode->initLiveMask(); // set live masks (predicate spaces which do not complement) + } +} + +//----------------------------------------------------------------------------------------// +// find qpNode corresponding to "qp" from qpMap. There are can be several nodes +// corresponding to one qp. We should return least recent inserted one + +QpNode* QpTree::findQpNode(Opnd *qp) { + + QpMap::iterator it = qpMap.upper_bound(qp); + return (--it)->second; +} + +//----------------------------------------------------------------------------------------// +// remove qpNode corresponding to "qp" from qpMap. There are can be several nodes +// corresponding to one qp. We should remove least recent inserted one + +void QpTree::removeQpNode(Opnd *qp) { + + QpMap::iterator it = qpMap.upper_bound(qp); // find in qpMap last node corresponding to "qp" + qpMap.erase(--it); // remove the node from the tree +} + +//----------------------------------------------------------------------------------------// + +void QpTree::printQpTree() { + + QpMap::iterator it = qpMap.upper_bound(p0); + printQpNode(--it, 0); +} + +//----------------------------------------------------------------------------------------// + +QpNode* QpTree::makeQpNode(QpNode *predNode, Opnd *qp) { + + if (qp == p0) return NULL; // node for p0 has been created in constructor + slot <<= 1; // get next empty slot (position in mask) + QpNode *qpNode = new(mm) QpNode(predNode, slot); // create qpNode + qpMap.insert( make_pair(qp, qpNode) ); // insert the qpNode in qpTree + return qpNode; +} + +//----------------------------------------------------------------------------------------// + +void QpTree::printQpNode(QpMap::iterator nodeIt, uint16 level) { + + QpNode *predNode = nodeIt->second; + Opnd *qp = nodeIt->first; + IPF_LOG << " " << IrPrinter::toString(predNode); + for (uint16 i=0; isecond; + if (qpNode->getPredNode() != predNode) continue; + printQpNode(it, level+1); + } +} + +//----------------------------------------------------------------------------------------// +// return true if the inst defines one pred opnd + +bool QpTree::isDefOnePred(Inst *inst) { + + switch (inst->getInstCode()) { + case INST_FRCPA : + case INST_FPRCPA : + case INST_FRSQRTA : + case INST_FPRSQRTA : return true; + default : return false; + } +} + +//----------------------------------------------------------------------------------------// +// return true if the inst defines two pred opnds + +bool QpTree::isDefTwoPreds(Inst *inst) { + + switch (inst->getInstCode()) { + case INST_CMP : + case INST_CMP4 : + case INST_FCMP : + case INST_TBIT : + case INST_TNAT : + case INST_FCLASS : return true; + default : return false; + } +} + +//----------------------------------------------------------------------------------------// +// return true if the inst defines two mutually complement preds + +bool QpTree::isDefComps(Inst *inst) { + + InstCode instCode = inst->getInstCode(); + if (instCode == INST_FCMP || instCode == INST_FCLASS) return true; + if (instCode == INST_TBIT || instCode == INST_TNAT) return true; + + CompVector &comps = inst->getComps(); + if (comps.size() < 2) return true; + if (comps[1] == CMPLT_CMP_CTYPE_NONE) return true; + if (comps[1] == CMPLT_CMP_CTYPE_UNC) return true; + return false; +} + +//========================================================================================// +// LiveManager +//========================================================================================// + +LiveManager::LiveManager(Cfg &cfg) : + cfg(cfg), + qpTree(cfg), + liveSet(cfg.getMM()) { +} + +//----------------------------------------------------------------------------------------// + +void LiveManager::init(Node *node) { + + liveSet.clear(); // clear live set + node->mergeOutLiveSets(liveSet); // all opnds alive in successors are alive in current live set + + for (RegOpndSet::iterator it=liveSet.begin(); it!=liveSet.end(); it++) { + RegOpnd *opnd = *it; // + opnd->orQpMask(MAX_QP_MASK); // initially opnds alive in all pred spaces + } // + + if (node->getNodeKind() != NODE_BB) return; // if node is not BB - nothing to do + qpTree.makeQpTree(((BbNode *)node)->getInsts()); // make qpTree for current BB +} + +//----------------------------------------------------------------------------------------// +// add opnds used in the inst in liveSet. Or modify opnd's qpMask to reflect use under inst's qp + +void LiveManager::use(Inst *inst) { + + OpndVector &opnds = inst->getOpnds(); // get inst's opnds + RegOpnd *qp = (RegOpnd *)opnds[0]; // fist opnd is instruction qp + QpNode *qpNode = qpTree.findQpNode(qp); // find qpNode corresponding to the qp + + if (qp->isWritable()) { + qp->orQpMask(MAX_QP_MASK); // qp is alive in all pred spaces + liveSet.insert(qp); + } + + for (uint16 i=inst->getNumDst()+1; iisWritable() == false) continue; + useOpnd(qpNode, opnd); + liveSet.insert(opnd); + } +} + +//----------------------------------------------------------------------------------------// +// remove opnds defined in the inst from liveSet. Or modify opnd's qpMask to reflect def +// under inst's qp + +void LiveManager::def(Inst *inst) { + + OpndVector &opnds = inst->getOpnds(); + RegOpnd *qp = (RegOpnd *)opnds[0]; // fist opnd is instruction qp + QpNode *qpNode = qpTree.findQpNode(qp); + + for (uint16 i=1; i<=inst->getNumDst(); i++) { + RegOpnd *opnd = (RegOpnd *)opnds[i]; + if (opnd->isWritable() == false) continue; + if (defOpnd(qpNode, opnd) == false) continue; + liveSet.erase(opnd); + } +} + +//----------------------------------------------------------------------------------------// + +QpMask LiveManager::getLiveMask(RegOpnd *opnd) { + QpNode *qpNode = qpTree.findQpNode(opnd); + return qpNode->getLiveMask(); +} + +//----------------------------------------------------------------------------------------// + +void LiveManager::useOpnd(QpNode *qpNode, RegOpnd *opnd) { + + QpMask mask = qpNode->getNodeMask(); // get mask of predicates alive in space of the qpNode + opnd->orQpMask(mask); // add mask to current opnd qpMask +} + +//----------------------------------------------------------------------------------------// + +bool LiveManager::defOpnd(QpNode *qpNode, RegOpnd *opnd) { + + if (opnd->isQp()) qpTree.removeQpNode(opnd); // if we def predicate opnd - remove corresponding qpNode from qpTree + QpMask mask = opnd->getQpMask(); // get mask of pred spaces, the opnd alive in + if (mask == 0) return true; // if mask is zero - opnd is dead + + while ((mask & qpNode->getCompMask())==0) { // while opnd is dead in complement predicate space - propagate def up + qpNode = qpNode->getPredNode(); // get predecessor in qpTree + } // + + opnd->andQpMask(~(qpNode->getNodeMask())); // null bits corresponding the successors in opnd's qp mask + if (opnd->getQpMask()) return false; // opnd is alive in some predicate spaces + else return true; // opnd is dead +} + +} // IPF +} // Jitrino Index: vm/jitrino/src/codegenerator/ipf/IpfOpndManager.cpp =================================================================== --- vm/jitrino/src/codegenerator/ipf/IpfOpndManager.cpp (revision 526661) +++ vm/jitrino/src/codegenerator/ipf/IpfOpndManager.cpp (working copy) @@ -230,10 +230,13 @@ OpndManager::OpndManager(MemoryManager &mm, CompilationInterface &compilationInterface) : mm(mm), - compilationInterface(compilationInterface) { + compilationInterface(compilationInterface), + maxOpndId(0), + maxNodeId(0), + inArgs(mm) { - maxOpndId = 0; - + prologNode = new(mm) BbNode(mm, getNextNodeId(), 1); + r0 = NULL; f0 = NULL; f1 = NULL; @@ -293,6 +296,37 @@ //----------------------------------------------------------------------------------------// +Opnd *OpndManager::newInArg(OpndKind opndKind, DataKind dataKind, uint32 inArgPosition) { + + int32 location = LOCATION_INVALID; + bool isFp = IpfType::isFloating(dataKind); + + if (inArgPosition < MAX_REG_ARG) { + if (isFp) location = F_INARG_BASE + getFpArgsNum(); + else location = newInReg(inArgPosition); + } else { + location = newInSlot(inArgPosition); // location is area local offset + } + + RegOpnd *arg = newRegOpnd(opndKind, dataKind, location); + inArgs.push_back(arg); + + return arg; +} + +//----------------------------------------------------------------------------------------// + +uint16 OpndManager::getFpArgsNum() { + + uint16 fpArgsNum = 0; + for (uint16 i=0; iisFloating()) fpArgsNum ++; + } + return fpArgsNum; +} + +//----------------------------------------------------------------------------------------// + RegOpnd *OpndManager::getR0() { if(r0 ==NULL) r0 =newRegOpnd(OPND_G_REG, DATA_I64, 0); return r0; } RegOpnd *OpndManager::getF0() { if(f0 ==NULL) f0 =newRegOpnd(OPND_F_REG, DATA_F, 0); return f0; } RegOpnd *OpndManager::getF1() { if(f1 ==NULL) f1 =newRegOpnd(OPND_F_REG, DATA_F, 1); return f1; } @@ -340,7 +374,41 @@ } //----------------------------------------------------------------------------------------// +// def r32, r33, r8, r9 +// alloc pfsBak = 1, 93, 2, 0 # gen alloc (pfsBak can not be preserved gr) +// adds r12 = -stackSize, r12 # save SP +// adds stackAddr = offset, r12 # if pfsBak is stack opnd - spill pfs +// st8 [stackAddr] = pfsBak # +// mov scratch = unat # if we use preserved grs - spill unat +// adds stackAddr = offset, r12 # +// st8 [stackAddr] = scratch # +// adds stackAddr = offset, r12 # spill preserved grs +// st8.spill [stackAddr] = preservedGr # +// adds stackAddr = offset, r12 # spill preserved frs +// stf.spill [stackAddr] = preservedFr # +// mov brBak = preservedBr # save preserved brs +// mov prBak = pr # save preserved prs +// mov rpBak = b0 # save return poiner +// mov arg1 = r32 +// mov arg2 = r33 +// mov arg3 = r8 +// mov arg4 = r9 +// movl heapBase = heapBaseImm +// movl vtableBase = vtableBaseImm +void OpndManager::insertProlog(Cfg &cfg) { + + BbNode *enterNode = cfg.getEnterNode(); + Edge *edge = new(mm) Edge(prologNode, enterNode, 1.0, EDGE_THROUGH); + edge->insert(); + cfg.setEnterNode(prologNode); + cfg.search(SEARCH_UNDEF_ORDER); + + initCompBases(prologNode); +} + +//----------------------------------------------------------------------------------------// + void OpndManager::initCompBases(BbNode *enterNode) { uint64 baseValue = 0; @@ -350,27 +418,19 @@ if (heapBase != NULL) { baseValue = (uint64) VMInterface::getHeapBase(); - baseImm = newImm(baseValue); Inst *inst = new(mm) Inst(mm, INST_MOVL, p0, heapBase, baseImm); - insts.insert(insts.begin(), inst); - IPF_LOG << " HeapBase initialization code inserted" << endl; + insts.insert(insts.end(), inst); + IPF_LOG << " HeapBase saved on opnd " << IrPrinter::toString(heapBase) << endl; } - if (heapBaseImm != NULL) { - heapBaseImm->setValue((uint64)VMInterface::getHeapBase()); - } - + if (vtableBase != NULL) { baseValue = (uint64) VMInterface::getVTableBase(); - baseImm = newImm(baseValue); Inst *inst = new(mm) Inst(mm, INST_MOVL, p0, vtableBase, baseImm); - insts.insert(insts.begin(), inst); - IPF_LOG << " VtableBase initialization code inserted" << endl; + insts.insert(insts.end(), inst); + IPF_LOG << " VtableBase saved on opnd " << IrPrinter::toString(vtableBase) << endl; } - if (vtableBaseImm != NULL) { - vtableBaseImm->setValue((uint64)VMInterface::getVTableBase()); - } } //----------------------------------------------------------------------------------------// Index: vm/jitrino/src/codegenerator/ipf/IpfInstrumentator.cpp =================================================================== --- vm/jitrino/src/codegenerator/ipf/IpfInstrumentator.cpp (revision 0) +++ vm/jitrino/src/codegenerator/ipf/IpfInstrumentator.cpp (revision 0) @@ -0,0 +1,170 @@ +/* + * 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, Konstantin M. Anisimov, Igor V. Chebykin + * @version $Revision: 1.1 $ + * + */ + +#include "IpfInstrumentator.h" +#include "IpfIrPrinter.h" +#include "open/vm.h" +#include + +namespace Jitrino { +namespace IPF { + +//========================================================================================// +// IrPrinter +//========================================================================================// + +Instrumentator::Instrumentator(Cfg &cfg) : + mm(cfg.getMM()), + opndManager(cfg.getOpndManager()), + cfg(cfg) { +} + +//----------------------------------------------------------------------------------------// + +void Instrumentator::instrument() { + + instrumentStart(); + instrumentEnd(); + opndManager->setContainCall(true); +} + +//----------------------------------------------------------------------------------------// + +void Instrumentator::instrumentStart() { + + InstVector instCode(mm); + uint64 funcDescPtr = (uint64) Instrumentator::methodStart; // get function descriptor address + + genNativeCall(funcDescPtr, instCode); + + BbNode *enterNode = cfg.getEnterNode(); + InstVector &insts = enterNode->getInsts(); + insts.insert(insts.end(), instCode.begin(), instCode.end()); + IPF_LOG << endl << " Method start:" << endl << IrPrinter::toString(instCode); +} + +//----------------------------------------------------------------------------------------// + +void Instrumentator::instrumentEnd() { + + InstVector instCode(mm); + uint64 funcDescPtr = (uint64) Instrumentator::methodEnd; // get function descriptor address + genNativeCall(funcDescPtr, instCode); // gen call of "methodEnd" + + NodeVector &nodes = cfg.search(SEARCH_POST_ORDER); // get nodes + for(uint16 i=0; igetNodeKind() != NODE_BB) continue; // ignore non BB node + + BbNode *node = (BbNode *)nodes[i]; + InstVector &insts = node->getInsts(); // get node's insts + if (insts.size() == 0) continue; // + CompVector &comps = insts.back()->getComps(); // get last inst completers + if (comps.size()<1 || comps[0]!=CMPLT_BTYPE_RET) continue; // if the inst is not "ret" - ignore + +// MethodDesc *methodDesc = cfg.getMethodDesc(); +// Type *type = methodDesc->getMethodSig()->getReturnType(); +// +// if (type->isVoid()) { + insts.insert(insts.end()-1, instCode.begin(), instCode.end()); +// } else { +// insts.insert(insts.end()-2, instCode.begin(), instCode.end()); +// } + } + + IPF_LOG << endl << " Method end:" << endl << IrPrinter::toString(instCode); +} + +//----------------------------------------------------------------------------------------// + +void Instrumentator::genNativeCall(uint64 funcDescPtr, InstVector &insts) { + +/* + DrlVMMethodDesc *methodDesc = (DrlVMMethodDesc *) cfg.getMethodDesc(); + Method_Handle methodHandle = methodDesc->getDrlVMMethod(); + + Opnd *methodDescAddr = opndManager->newImm((uint64) methodHandle); + Opnd *p0 = opndManager->getP0(); + Opnd *r0 = opndManager->getR0(); + Opnd *b0 = opndManager->getB0(); + Opnd *r1 = opndManager->newRegOpnd(OPND_G_REG, DATA_U64, 1); + Opnd *funDescAddr = opndManager->newImm(funcDescPtr); + Opnd *globalPtrAddr = opndManager->newImm(funcDescPtr + 8); + Opnd *entryPointer = opndManager->newRegOpnd(OPND_G_REG, DATA_U64); + Opnd *globalPtrBak = opndManager->newRegOpnd(OPND_G_REG, DATA_U64); + Opnd *globalPtr = opndManager->newRegOpnd(OPND_G_REG, DATA_U64); + Opnd *callTgt = opndManager->newRegOpnd(OPND_B_REG, DATA_U64); + Opnd *callArg = opndManager->newRegOpnd(OPND_G_REG, DATA_U64, opndManager->newOutReg(0)); + + // load entry pointer + insts.push_back(new(mm) Inst(mm, INST_MOVL, p0, entryPointer, funDescAddr)); + insts.push_back(new(mm) Inst(mm, INST_LD, CMPLT_SZ_8, p0, entryPointer, entryPointer)); + + // save global pointer + insts.push_back(new(mm) Inst(mm, INST_MOV, p0, globalPtrBak, r1)); + + // load new global pointer + insts.push_back(new(mm) Inst(mm, INST_MOVL, p0, globalPtr, globalPtrAddr)); + insts.push_back(new(mm) Inst(mm, INST_LD, CMPLT_SZ_8, p0, r1, globalPtr)); + + // make call + insts.push_back(new(mm) Inst(mm, INST_MOVL, p0, callArg, methodDescAddr)); + insts.push_back(new(mm) Inst(mm, INST_MOV, p0, callTgt, entryPointer)); + insts.push_back(new(mm) Inst(mm, INST_BR13, CMPLT_BTYPE_CALL, p0, r0, b0, callTgt, callArg, r1)); + + // restore global pointer + insts.push_back(new(mm) Inst(mm, INST_MOV, p0, r1, globalPtrBak)); + insts.push_back(new(mm) Inst(mm, INST_USE, p0, r1)); + */ +} + +//----------------------------------------------------------------------------------------// + +void Instrumentator::methodStart(Method_Handle methodHandle) { + + ofstream rtLog; + rtLog.open("rt.log", ios::out | ios::app); + + rtLog << "Start "; + rtLog << class_get_name(method_get_class(methodHandle)); + rtLog << "." << method_get_name(methodHandle); + rtLog << method_get_descriptor(methodHandle) << endl; + rtLog.close(); +} + +//----------------------------------------------------------------------------------------// + +void Instrumentator::methodEnd(Method_Handle methodHandle) { + + ofstream rtLog; + rtLog.open("rt.log", ios::out | ios::app); + + rtLog << "End "; + rtLog << class_get_name(method_get_class(methodHandle)); + rtLog << "." << method_get_name(methodHandle); + rtLog << method_get_descriptor(methodHandle) << endl; + rtLog.close(); +} + +} // IPF +} // Jitrino