Index: vm/jitrino/config/em64t/server.emconf =================================================================== --- vm/jitrino/config/em64t/server.emconf (revision 514661) +++ vm/jitrino/config/em64t/server.emconf (working copy) @@ -62,7 +62,7 @@ -XDjit.SD2_OPT.path=opt_init,translator,optimizer,hir2lir,codegen --XDjit.SD2_OPT.path.optimizer=ssa,simplify,dce,uce,devirt_virtual,edge_annotate,unguard,devirt_intf,inline,uce,purge,simplify,dce,uce,so2-,simplify,dce,uce,hvn,dce,uce,dessa,statprof,peel,ssa,hvn,simplify,dce,uce,lower,dce,uce,memopt,reassoc,dce,uce,hvn,dce,uce,abcd,dce,uce,gcm,dessa,statprof,markglobals +-XDjit.SD2_OPT.path.optimizer=ssa,simplify,dce,uce,devirt_virtual,edge_annotate,unguard,devirt_intf,inline,uce,purge,simplify,dce,uce,tausimp,dce,uce,so2,simplify,dce,uce,hvn,dce,uce,dessa,statprof,peel,ssa,hvn,simplify,dce,uce,lower,dce,uce,memopt,reassoc,dce,uce,hvn,dce,uce,abcd,dce,uce,gcm,dessa,statprof,markglobals -XDjit.SD2_OPT.path.codegen=lock_method,bbp,gcpoints,cafl,dce1,i8l-,early_prop-,itrace-,native,constraints,dce2,regalloc,spillgen,layout,copy,rce-,stack,break-,iprof-,emitter!,si_insts,gcmap,info,unlock_method -XDjit.SD2_OPT.path.dce1=cg_dce -XDjit.SD2_OPT.path.dce2=cg_dce Index: vm/jitrino/config/ia32/server.emconf =================================================================== --- vm/jitrino/config/ia32/server.emconf (revision 514661) +++ vm/jitrino/config/ia32/server.emconf (working copy) @@ -63,7 +63,7 @@ -XDjit.SD2_OPT.path=opt_init,translator,optimizer,hir2lir,codegen --XDjit.SD2_OPT.path.optimizer=ssa,simplify,dce,uce,devirt_virtual,edge_annotate,unguard,devirt_intf,inline,uce,purge,simplify,dce,uce,lazyexc,so2-,simplify,dce,uce,inline_helpers,purge,simplify,uce,dce,dessa,statprof,peel,ssa,hvn,simplify,dce,uce,lower,dce,uce,memopt,reassoc,dce,uce,hvn,dce,uce,abcd,dce,uce,gcm,dessa,statprof,markglobals +-XDjit.SD2_OPT.path.optimizer=ssa,simplify,dce,uce,devirt_virtual,edge_annotate,unguard,devirt_intf,inline,uce,purge,simplify,dce,uce,lazyexc,tausimp,dce,uce,so2,simplify,dce,uce,inline_helpers,purge,simplify,uce,dce,dessa,statprof,peel,ssa,hvn,simplify,dce,uce,lower,dce,uce,memopt,reassoc,dce,uce,hvn,dce,uce,abcd,dce,uce,gcm,dessa,statprof,markglobals -XDjit.SD2_OPT.path.codegen=lock_method,bbp,btr,gcpoints,cafl,dce1,i8l,api_magic,early_prop,peephole,itrace-,native,constraints,dce2,regalloc,spillgen,layout,copy,rce+,stack,break-,iprof-,peephole,emitter!,si_insts,gcmap,info,unlock_method -XDjit.SD2_OPT.path.dce1=cg_dce -XDjit.SD2_OPT.path.dce2=cg_dce Index: vm/jitrino/src/optimizer/syncopt.h =================================================================== --- vm/jitrino/src/optimizer/syncopt.h (revision 514661) +++ vm/jitrino/src/optimizer/syncopt.h (working copy) @@ -25,6 +25,7 @@ #define _SYNC_OPT_H #include +#include "deadcodeeliminator.h" #include "open/types.h" #include "optpass.h" #include "Opcode.h" Index: vm/jitrino/src/optimizer/syncopt.cpp =================================================================== --- vm/jitrino/src/optimizer/syncopt.cpp (revision 514661) +++ vm/jitrino/src/optimizer/syncopt.cpp (working copy) @@ -2118,6 +2118,9 @@ SyncOpt2(IRManager& irm) : irManager(irm) {}; void runPass(); + void findClosestMonExits(Node* enterNode, Opnd* monObject, BitSet& monexits, BitSet& visited); + void eliminateMonExits(BitSet& monexits); + void sweepStraightCatchThrow(); void eliminateClosestMonExits(Node* enterNode, Opnd* monObject, int& nExits, BitSet& monexits); private: IRManager& irManager; @@ -2141,29 +2144,134 @@ for (Inst* inst = (Inst*)node->getFirstInst(); inst!=NULL; inst = inst->getNextInst()) { if (inst->getOpcode()== Op_TauMonitorEnter) { monenters.push_back(inst); + Opnd* predMonObject = inst->getSrc(0); + for (size_t i = 0; igetNode()==NULL) { + Inst* succ = monenters[i]; + Node* succNode = succ->getNode(); + if (succNode==NULL) { + // Skip monenters which have been already removed continue; } - Opnd* monObject = child->getSrc(0); - if ((monObject == inst->getSrc(0)) && domTree->dominates(inst->getNode(), child->getNode())) { - // Find a proper child to clean - int nExits = 0; - Node* enterNode = child->getNode(); - BitSet monexits(tmpMM,flowGraph.getMaxNodeId()); - - eliminateClosestMonExits(enterNode, monObject, nExits, monexits); - - assert(nExits > 0); - child->unlink(); + Opnd* succMonObject = succ->getSrc(0); + if ((succMonObject == predMonObject) && domTree->dominates(inst->getNode(), succ->getNode())) { + // Check if successor is nested into predecessor's monEnter/monExit. + // If there is at least one monExit from the list of closest monExits + // for both predecessor and successor is the same - the locks are nested. + BitSet visited(tmpMM, flowGraph.getMaxNodeId()); + BitSet predMonExits(tmpMM, flowGraph.getMaxNodeId()); + findClosestMonExits(node, predMonObject, predMonExits, visited); + assert(!predMonExits.isEmpty()); + visited.clear(); + BitSet succMonExits(tmpMM, flowGraph.getMaxNodeId()); + findClosestMonExits(succNode, predMonObject, succMonExits, visited); + assert(!succMonExits.isEmpty()); + if (!predMonExits.isDisjoint(succMonExits)) { + // The locks are nested - successor's lock may be removed + eliminateMonExits(succMonExits); + predMonExits.subtract(succMonExits); + succ->unlink(); + } } } } } } + DeadCodeEliminator dce(irManager); + dce.eliminateUnreachableCode(); + dce.eliminateDeadCode(false); + + sweepStraightCatchThrow(); + } + +void SyncOpt2::findClosestMonExits(Node* enterNode, Opnd* monObject, BitSet& monexits, BitSet& visited) { + ControlFlowGraph& flowGraph = irManager.getFlowGraph(); + const Edges& outEdges = enterNode->getOutEdges(); + visited.setBit(enterNode->getId()); + Edges::const_iterator eit; + Node* exitNode; + for (eit = outEdges.begin(); eit != outEdges.end(); ++eit) { + exitNode = (*eit)->getTargetNode(); + assert(exitNode != flowGraph.getExitNode()); + if ((exitNode == flowGraph.getUnwindNode()) || visited.getBit(exitNode->getId())) { + // Statements of a synchronized method potentially throwing exceptions may have an edge + // to the unwind node. In case if real exception is thrown - VM does monExit. + // So, our analysis should not go after unwind node. + continue; + } + Inst* exit = (Inst*)exitNode->getLastInst(); + if ((exit->getOpcode() == Op_TauMonitorExit) && (exit->getSrc(0) == monObject)) { + monexits.setBit(exitNode->getId()); + } else { + findClosestMonExits(exitNode, monObject, monexits, visited); + } + } } +void SyncOpt2::eliminateMonExits(BitSet& monexits) { + ControlFlowGraph& flowGraph = irManager.getFlowGraph(); + const Nodes& nodes = flowGraph.getNodes(); + for (Nodes::const_iterator it = nodes.begin(), end = nodes.end(); it!=end; ++it) { + Node* node = *it; + if (monexits.getBit(node->getId())) { + // Remove exception edge + Edge* excEdge = node->getExceptionEdge(); + assert(excEdge); + flowGraph.removeEdge(excEdge); + // remove monExit inst + Inst* exit = (Inst*)node->getLastInst(); + assert(exit->getOpcode() == Op_TauMonitorExit); + exit->unlink(); + } + } +} + +/** + * Simplify pattern 'dispatch 1 -> catch t1 -> throw t1 -> dispatch 2' to 'dispatch 2' + */ +void SyncOpt2::sweepStraightCatchThrow() { + ControlFlowGraph& flowGraph = irManager.getFlowGraph(); + const Nodes& nodes = flowGraph.getNodesPostOrder(); + for (Nodes::const_iterator it = nodes.begin(), end = nodes.end(); it!=end; ++it) { + // Dispatch node one + Node* node = *it; + if (!(node->isDispatchNode() && node->hasOnlyOneSuccEdge() && (node->getInDegree() > 0)) || (node == flowGraph.getUnwindNode())) continue; + + // Catch label node + Node* catchNode = node->getEdgeTarget(Edge::Kind_Catch); + if (!(catchNode->isCatchBlock() && catchNode->hasOnlyOneSuccEdge())) continue; + Inst* catchLabelInst = (Inst*)catchNode->getFirstInst(); + if (!catchLabelInst->isCatchLabel()) continue; + + Inst* catchInst = (Inst*)catchNode->getSecondInst(); + // If catch label and catch inst nodes are not merged then there is another edge + // to the catch inst node - so we can't remove this catch. + if (catchInst == NULL) continue; + assert(catchInst->getOpcode() == Op_Catch); + if (catchInst->getNextInst() != NULL) continue; + Opnd* excOpnd = catchInst->getDst(); + + // Throw node + Node* throwNode = catchNode->getUnconditionalEdgeTarget(); + Inst* throwInst = (Inst*)throwNode->getSecondInst(); + if ((throwInst->getOpcode() != Op_Throw) || (throwInst->getSrc(0) != excOpnd)) continue; + if (throwInst->getNextInst() != NULL) continue; + assert(throwNode->getExceptionEdge() != NULL); + + // Dispatch node two + Node* dispatchNode = throwNode->getExceptionEdgeTarget(); + assert(dispatchNode); + + // Re-target dispatch edges + const Edges& inEdges = node->getInEdges(); + while(!inEdges.empty()) { + Edge* currentEdge = inEdges.front(); + flowGraph.replaceEdgeTarget(currentEdge, dispatchNode); + } + + } +} + void SyncOpt2::eliminateClosestMonExits(Node* enterNode, Opnd* monObject, int& nExits, BitSet& monexits) { ControlFlowGraph& flowGraph = irManager.getFlowGraph(); const Edges& outEdges = enterNode->getOutEdges(); Index: vm/jitrino/src/optimizer/simplifytaus.cpp =================================================================== --- vm/jitrino/src/optimizer/simplifytaus.cpp (revision 514661) +++ vm/jitrino/src/optimizer/simplifytaus.cpp (working copy) @@ -597,7 +597,13 @@ case Op_TauStaticCast: { - assert(type); + // TauStaticCast does not guarantee that src is not null + if (type == 0) { + Opnd* srcOpnd = srcInst->getSrc(0); + assert(srcOpnd); + Opnd* result = findReplacement(srcOpnd, type, exactType); + return result; + } TypeInst *srcTypeInst = srcInst->asTypeInst(); assert(srcTypeInst); @@ -608,8 +614,10 @@ assert(tauOpnd->getType()->tag == Type::Tau); return tauOpnd; } else { - assert(0); - return 0; + Opnd* srcOpnd = srcInst->getSrc(0); + assert(srcOpnd); + Opnd* result = findReplacement(srcOpnd, type, exactType); + return result; } } Index: vm/jitrino/src/translator/java/JavaFlowGraphBuilder.cpp =================================================================== --- vm/jitrino/src/translator/java/JavaFlowGraphBuilder.cpp (revision 514661) +++ vm/jitrino/src/translator/java/JavaFlowGraphBuilder.cpp (working copy) @@ -195,9 +195,17 @@ // create edges between handler entry and each catch // CatchHandler * handlers = catchBlock->getHandlers(); + bool hasObjectHandler = false; for (;handlers != NULL; handlers = handlers->getNextHandler()) { fg->addEdge(entry,handlers->getLabelInst()->getNode()); + if (handlers->getExceptionType()->isSystemObject()) { + // There is catch for Object type + hasObjectHandler = true; + } } + // No other edges since all exceptions are caught + if (hasObjectHandler) return; + // edges for uncaught exception ExceptionInfo *nextBlock = NULL; for (nextBlock = catchBlock->getNextExceptionInfoAtOffset();