diff -ru vm/jitrino/src/optimizer/Inst.cpp vm/jitrino/src/optimizer/Inst.cpp --- vm/jitrino/src/optimizer/Inst.cpp 2006-10-09 07:10:36.000000000 +0400 +++ vm/jitrino/src/optimizer/Inst.cpp 2006-10-09 20:02:04.532592700 +0400 @@ -2552,7 +2552,7 @@ } Inst* InstFactory::makeInitType(Type* type) { - return makeTypeInst(Op_InitType, Modifier(), + return makeTypeInst(Op_InitType, Modifier(Exception_Sometimes), Type::Void, OpndManager::getNullOpnd(), type); } diff -ru vm/jitrino/src/optimizer/Opcode.cpp vm/jitrino/src/optimizer/Opcode.cpp --- vm/jitrino/src/optimizer/Opcode.cpp 2006-10-09 07:10:36.000000000 +0400 +++ vm/jitrino/src/optimizer/Opcode.cpp 2006-10-09 20:02:04.548218000 +0400 @@ -176,9 +176,9 @@ { Op_MonitorExitFence, true, MB::StoreOrSync, MK::None, "monexitfence", "monexitfence %0", }, // (opnd must be non-null) { Op_TauStaticCast, false, MB::Movable, MK::None, "staticcast", "staticcast %0,%d ((%1)) -) %l", }, // Compile-time assertion. Asserts that cast is legal. { Op_TauCast, false, MB::Check, MK::Exception, "cast ", "cast %0,%d ((%1)) -) %l", }, // CastException (suceeds if argument is null, returns casted object) - { Op_TauAsType, false, MB::Movable, MK::None, "astype", "astype %0,%d -) %l", }, // returns casted object if argument is an instance of, null otherwise + { Op_TauAsType, false, MB::Movable, MK::None, "astype", "astype %0,%d -) %l", }, // returns casted object if argument is an instance of, null otherwise { Op_TauInstanceOf, false, MB::Movable, MK::None, "instanceof", "instanceof %0,%d ((%1)) -) %l", }, // returns true if argument is an instance of type T, tau opnd isNonNull - { Op_InitType, true, MB::CSEable, MK::None, "inittype", "inittype %d", }, // REVIEW: can this throw an exception? + { Op_InitType, true, MB::CSEable, MK::Exception, "inittype", "inittype %d", }, // can throw a linking exception during class initialization { Op_Label, true, MB::None, MK::None, "label ", "%l:", }, // special label instructions for branch labels, finally, catch { Op_MethodEntry, true, MB::None, MK::None, "methodentry", "--- MethodEntry(%d): (%s)", }, // method entry label { Op_MethodEnd, true, MB::None, MK::None, "methodend", "+++ MethodEnd(%d) (%s)", }, // end of a method diff -ru vm/jitrino/src/optimizer/hashvaluenumberer.cpp vm/jitrino/src/optimizer/hashvaluenumberer.cpp --- vm/jitrino/src/optimizer/hashvaluenumberer.cpp 2006-10-09 07:10:36.000000000 +0400 +++ vm/jitrino/src/optimizer/hashvaluenumberer.cpp 2006-10-09 20:02:04.548218000 +0400 @@ -131,9 +131,9 @@ // then hash return dispatch(inst); } - Inst* caseAdd(Inst* inst) { return hashIfNoOverflow(inst); } - Inst* caseSub(Inst* inst) { return hashIfNoOverflow(inst); } - Inst* caseMul(Inst* inst) { return hashIfNoOverflow(inst); } + Inst* caseAdd(Inst* inst) { return hashIfNoException(inst); } + Inst* caseSub(Inst* inst) { return hashIfNoException(inst); } + Inst* caseMul(Inst* inst) { return hashIfNoException(inst); } Inst* caseTauDiv(Inst* inst) { return hashInst(inst, getKey(inst->getOperation(), inst->getSrc(0)->getId(), inst->getSrc(1)->getId())); } @@ -156,7 +156,7 @@ Inst* caseSelect(Inst* inst) { return hashInst(inst); } // conversion - Inst* caseConv(Inst* inst) { return hashIfNoOverflow(inst); } + Inst* caseConv(Inst* inst) { return hashIfNoException(inst); } // shifts Inst* caseShladd(Inst* inst) { return hashInst(inst); } @@ -792,7 +792,7 @@ } return inst; } - Inst* caseInitType(TypeInst* inst) { return hashInst(inst); } + Inst* caseInitType(TypeInst* inst) { return hashIfNoException(inst); } // labels @@ -1189,13 +1189,66 @@ return 0; } - // arithmetic operations should only be added if no exception can occur - Inst* hashIfNoOverflow(Inst* inst) { - if ((inst->getOverflowModifier() == Overflow_None) || - (inst->getExceptionModifier() == Exception_Never)) + bool thereIsAPath(Node* start, Node* finish, Node* commonAncestor) + { + assert(domTree.dominates(commonAncestor,start)); + assert(domTree.dominates(commonAncestor,finish)); + + const Edges &outedges = start->getOutEdges(); + typedef Edges::const_iterator EdgeIter; + EdgeIter eLast = outedges.end(); + for (EdgeIter eIter = outedges.begin(); eIter != eLast; eIter++) { + Edge* outEdge = *eIter; + Node* succBlock = outEdge->getTargetNode(); + + if( domTree.dominates(succBlock,start) ) + continue; // outEdge is a backedge. Skip it. + + if (finish == succBlock) { + return true; + } else if ( domTree.dominates(commonAncestor,succBlock) && + thereIsAPath(succBlock,finish,commonAncestor) ) + { + return true; + } + } + return false; + } + + Inst* hashIfNoException(Inst* inst) { + Modifier mod = inst->getModifier(); + if ((mod.hasOverflowModifier() && mod.getOverflowModifier() != Overflow_None) || + (mod.hasExceptionModifier() && mod.getExceptionModifier() != Exception_Never)) + { + Inst* optInst = lookupInst(inst); + if (!optInst) { + setHashToInst(inst, getKey(inst)); + return inst; + } else { + Node* block = inst->getNode(); + Node* optBlock = optInst->getNode(); + // we must ensure that optInst was successfully executed + // if there is a way [block]->[dispatch]->...->[optBlock] + // we should not consider optInst as successfully executed + // so inst can not be eliminated, but it should be added + // into hash table instead of optInst + Node* dispatch = optBlock->getEdgeTarget(Edge::Kind_Dispatch); + if ( dispatch && domTree.dominates(optBlock,dispatch) && + thereIsAPath(dispatch,block,optBlock)) + { + // do not optimize, just add to hash. + setHashToInst(inst, getKey(inst)); + return inst; + } else { + // everything is OK. Can optimize. + return optInst; + } + } + + } else { + // process inst as usual return hashInst(inst); - else - return lookupInst(inst); + } } Inst* lookupInst(Inst* inst) { @@ -1264,7 +1317,7 @@ IRManager& irManager; Inst* tauUnsafe; Opnd* tauPoint; - DominatorTree &domTree; + DominatorTree &domTree; MemoryOpt *memOpt; bool cse_final; ControlFlowGraph &fg; diff -ru vm/jitrino/src/optimizer/memoryopt.cpp vm/jitrino/src/optimizer/memoryopt.cpp --- vm/jitrino/src/optimizer/memoryopt.cpp 2006-10-09 07:10:36.000000000 +0400 +++ vm/jitrino/src/optimizer/memoryopt.cpp 2006-10-09 20:02:04.563843300 +0400 @@ -52,7 +52,11 @@ computeDominators(irm); DominatorTree* dominatorTree = irm.getDominatorTree(); assert(dominatorTree && dominatorTree->isValid()); + + computeLoops(irm); LoopTree* loopTree = irm.getLoopTree(); + assert(loopTree && loopTree->isValid()); + ControlFlowGraph& flowGraph = irm.getFlowGraph(); MemoryManager& memoryManager = irm.getNestedMemoryManager(); diff -ru vm/jitrino/src/translator/java/JavaFlowGraphBuilder.cpp vm/jitrino/src/translator/java/JavaFlowGraphBuilder.cpp --- vm/jitrino/src/translator/java/JavaFlowGraphBuilder.cpp 2006-10-09 07:10:36.000000000 +0400 +++ vm/jitrino/src/translator/java/JavaFlowGraphBuilder.cpp 2006-10-09 20:02:04.563843300 +0400 @@ -181,8 +181,8 @@ // // add an edge to handler entry node // - if (lastExceptionalInstSeen != NULL && !block->findTargetEdge(dispatch)) - fg->addEdge(block,dispatch); + if (lastExceptionalInstSeen != NULL) + addEdge(block,dispatch); return block; }