Index: trunk/build/custom/msvc_2003/jitrino/jitrino.vcproj =================================================================== --- trunk/build/custom/msvc_2003/jitrino/jitrino.vcproj (revision 567544) +++ trunk/build/custom/msvc_2003/jitrino/jitrino.vcproj (working copy) @@ -350,6 +350,12 @@ RelativePath="..\..\..\..\vm\jitrino\src\optimizer\tailduplicator.h"> + + + + visited_nodes(irManager.getMemoryManager(), flowGraph.getMaxNodeId(), false); + StlVector pseudo_insts(irManager.getMemoryManager(), 10); + LoopTree * loop_tree = irManager.getLoopTree(); + Nodes::const_iterator node_iter; + bool restore_ssa = false; + + loop_tree->rebuild(false); + + for(node_iter = nodes.begin(); node_iter != nodes.end(); ++node_iter) { + Node * throw_node = *node_iter; + Inst * throw_inst = (Inst *)throw_node->getLastInst(); + + if (throw_inst->getOpcode() != Op_Throw) continue; + + Opnd * throw_opnd = throw_inst->getSrc(0); + Type * throw_type = throw_opnd->getType(); + + pseudo_insts.clear(); + + Node * dispatch_node = throw_node->getExceptionEdgeTarget(); + Node * catch_node = findExceptionHandler(throw_type, dispatch_node, pseudo_insts); + + if (catch_node) { + assert(catch_node->isCatchBlock()); + // Found target block. + Node * target_node = catch_node; + if (catch_node->getSecondInst() == NULL) { + target_node = catch_node->getUnconditionalEdgeTarget(); + } + + if (Log::isEnabled()) { + Log::out() << "Trying to elimination "; + throw_inst->print(Log::out()); + Log::out() << std::endl; + } + + + // Avoid jumps inside loop. + Node * throw_loop_header = loop_tree->getLoopHeader(throw_node, false); + Node * target_loop_header = loop_tree->getLoopHeader(target_node, false); + if (// Target node inside loop && + target_loop_header != NULL && + // Throw node is outside the same loop || Target node is loop header + (target_loop_header != throw_loop_header || target_node == target_loop_header)) { + + if (Log::isEnabled()) { + Log::out() << "FAILED: Avoid jump inside loop from node ID " << throw_node->getId() + << " to node ID " << target_node->getId() << std::endl; + } + continue; + } + + Inst * catch_inst = (Inst *)target_node->getSecondInst(); + while (catch_inst->getOpcode() != Op_Catch) { + catch_inst = (Inst*)catch_inst->next(); + } + Opnd * catch_opnd = catch_inst->getDst(); + VarOpnd * dst_var = NULL; + Inst * st_inst = NULL; + // Detect true target node. + if (visited_nodes[target_node->getId()]) { + st_inst = (Inst *)target_node->getLastInst(); + dst_var = st_inst->getDst()->asVarOpnd(); + target_node = target_node->getUnconditionalEdgeTarget(); + } else { + // Store exception operand in variable. + Opnd * new_catch_opnd = opndManager.createSsaTmpOpnd(catch_opnd->getType()); + catch_inst->setDst(new_catch_opnd); + dst_var = opndManager.createVarOpnd(catch_opnd->getType(), false); + st_inst = instFactory.makeStVar(dst_var, new_catch_opnd); + target_node->appendInst(st_inst, catch_inst); + // Mark the node as visited. + visited_nodes[target_node->getId()] = true; + // Split target node if required. + if (target_node->getInstCount() > 2) { + target_node = flowGraph.splitNodeAtInstruction(st_inst, true, false, instFactory.makeLabel()); + } else { + target_node = target_node->getUnconditionalEdgeTarget(); + } + target_node->prependInst(instFactory.makeLdVar(catch_opnd, dst_var)); + } + + // Replace "throw" wtih "stVar" instruction. + throw_inst->unlink(); + throw_node->appendInst(instFactory.makeStVar(dst_var, throw_opnd)); + + // Add direct jump. + flowGraph.addEdge(throw_node, target_node); + + // Add pseudo instructions from exeption path. + if (pseudo_insts.size() > 0) { + Node * pseudo_node = flowGraph.spliceBlockOnEdge( + throw_node->getUnconditionalEdge(), instFactory.makeLabel()); + + Inst * last_phi_inst = NULL; + for(StlVector::iterator it = pseudo_insts.begin(); it != pseudo_insts.end(); it++) { + Inst * inst = *it; + Inst * new_inst = NULL; + if (inst->isMethodMarker()) { + MethodMarkerInst * marker_inst = (MethodMarkerInst *)inst; + new_inst = instFactory.makeMethodMarker(marker_inst->isMethodEntryMarker() + ? MethodMarkerInst::Entry : MethodMarkerInst::Exit, marker_inst->getMethodDesc()); + pseudo_node->appendInst(new_inst); + } else if (inst->isPhi()) { + // Replace destination operand. + Opnd * orig_dst = inst->getDst(); + VarOpnd * var = orig_dst->asSsaVarOpnd()->getVar(); + Opnd * dst1 = opndManager.createSsaVarOpnd(var); + inst->setDst(dst1); + // Create phi instruction to stick source operands on new path. + uint32 num_opnds = inst->getNumSrcOperands(); + Opnd** opnds = new (irManager.getMemoryManager()) Opnd*[num_opnds]; + for (uint32 i = 0; i < num_opnds; ++i) { + opnds[i] = inst->getSrc(i); + } + Opnd * dst2 = opndManager.createSsaVarOpnd(var); + new_inst = instFactory.makePhi(dst2, num_opnds, opnds); + // Phi is a header critical instruction thus it must go in the beginning. + if (last_phi_inst == NULL) { + pseudo_node->prependInst(new_inst); + } else { + pseudo_node->appendInst(new_inst, last_phi_inst); + } + last_phi_inst = new_inst; + // Create one more phi to stick destination operands. + Opnd * dst_opnds[] = {dst1, dst2}; + new_inst = instFactory.makePhi(orig_dst, 2, dst_opnds); + target_node->prependInst(new_inst); + } else { + assert("Unexcpected type of instruction in dispatch node."); + } + } + } + + // Rebuild loop tree after modifications. + loop_tree->rebuild(false); + restore_ssa = true; + + if (Log::isEnabled()) { + Log::out() << "SUCCEED: Inserting direct jump from node ID " << throw_node->getId() + << " to node ID " << target_node->getId() << std::endl; + } + } + } + + if (restore_ssa) { + OptPass::computeDominators(irManager); + DominatorTree* dominatorTree = irManager.getDominatorTree(); + + DomFrontier frontier(irManager.getNestedMemoryManager(), *dominatorTree, &flowGraph); + SSABuilder ssaBuilder(opndManager, instFactory, frontier, &flowGraph, irManager.getOptimizerFlags()); + bool phiInserted = ssaBuilder.fixupVars(&flowGraph, irManager.getMethodDesc()); + irManager.setInSsa(true); + if (phiInserted) + irManager.setSsaUpdated(); + } +} + +Node * ThrowInstEliminator::findExceptionHandler(Type * exceptionType, Node * dispatch_node, StlVector & pseudo_insts) { + const Edges & catch_eges = dispatch_node->getOutEdges(); + Edges::const_iterator edge_iter; + + assert(dispatch_node != NULL); + + // Scan dispatch node for possible method end markers. + Inst * inst = (Inst *)dispatch_node->getSecondInst(); + while (inst != NULL) { + pseudo_insts.push_back(inst); + inst = inst->getNextInst(); + } + + for(edge_iter = catch_eges.begin(); edge_iter != catch_eges.end(); ++edge_iter) { + Edge * catch_edge = *edge_iter; + Node * catch_node = catch_edge->getTargetNode(); + + if (!catch_node->isBlockNode()) continue; + + CatchLabelInst * catch_label_inst = + ((Inst *)catch_node->getFirstInst())->asCatchLabelInst(); + Type * catch_type = catch_label_inst->getExceptionType(); + if (irManager.getTypeManager().isSubTypeOf(exceptionType, catch_type)) { + return catch_node; + } + } + + // Exception handler was not found. + // Go to next dispatch node. + dispatch_node = dispatch_node->getExceptionEdgeTarget(); + + if (dispatch_node && dispatch_node->isDispatchNode()) { + return findExceptionHandler(exceptionType, dispatch_node, pseudo_insts); + } + + return NULL; +} + +} //namespace Jitrino \ No newline at end of file Index: trunk/vm/jitrino/src/optimizer/throwopt.h =================================================================== --- trunk/vm/jitrino/src/optimizer/throwopt.h (revision 0) +++ trunk/vm/jitrino/src/optimizer/throwopt.h (revision 0) @@ -0,0 +1,49 @@ +/* + * 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, Evgueni Brevnov + * @version $Revision: 1.1 $ + * + */ + +#ifndef _THROWOPT_H_ +#define _THROWOPT_H_ + +#include "Stl.h" +#include "optpass.h" +#include "LoopTree.h" +#include "irmanager.h" + +namespace Jitrino { + +class ThrowInstEliminator { +public: + ThrowInstEliminator(IRManager& irm); + void eliminateThrowInst(); +private: + Node * findExceptionHandler(Type * exceptionType, Node * dispatch_node, StlVector & exit_markers); + + IRManager& irManager; + ControlFlowGraph& flowGraph; + InstFactory& instFactory; + OpndManager& opndManager; +}; + +} //namespace Jitrino + +#endif // _THROWOPT_H_