public NodeExecutor(ExecutionGraph graph, ClassManager classManager) { this.graph = graph; exceptionResolver = new ExceptionHandlerAddressResolver(classManager, graph.getMethod()); }
int resolve(String className, int address) { VirtualClass exceptionClass = classManager.getVirtualClass(className); return resolve(exceptionClass, address); }
int resolve(VirtualClass exceptionClass, int address) { int handlerAddress = findHandlerCodeAddress(exceptionClass, address, false); if (handlerAddress != -1) { return handlerAddress; } handlerAddress = findHandlerCodeAddress(exceptionClass, address, true); return handlerAddress; }
@Test public void simpleExceptionResolvedCorrectly() { int currentAddress = 1; int tryStartAddress = 1; int tryCodeUnits = 10; int handlerCodeAddress = 20; List<BuilderExceptionHandler> handlers = new LinkedList<BuilderExceptionHandler>(); handlers.add(buildHandler(handlerCodeAddress, exceptionClass1)); tryBlocks.add(buildTryBlock(tryStartAddress, tryCodeUnits, handlers)); ExceptionHandlerAddressResolver exceptionResolver = new ExceptionHandlerAddressResolver(classManager, METHOD); String name = exceptionClass1.getName(); int actual = exceptionResolver.resolve(name, currentAddress); assertEquals(handlerCodeAddress, actual); }
@Test public void overlappingTryBlocksWithMoreThanOneValidHandlerResolvesNearestAncestor() { int currentAddress = 2; int tryStartAddress1 = 1; int tryStartAddress2 = 2; int tryCodeUnits = 10; int handlerCodeAddress1 = 20; int handlerCodeAddress2 = 30; List<BuilderExceptionHandler> handlers1 = new LinkedList<BuilderExceptionHandler>(); handlers1.add(buildHandler(handlerCodeAddress1, exceptionClass1)); tryBlocks.add(buildTryBlock(tryStartAddress1, tryCodeUnits, handlers1)); List<BuilderExceptionHandler> handlers2 = new LinkedList<BuilderExceptionHandler>(); handlers2.add(buildHandler(handlerCodeAddress2, exceptionClass2)); tryBlocks.add(buildTryBlock(tryStartAddress2, tryCodeUnits, handlers2)); ExceptionHandlerAddressResolver exceptionResolver = new ExceptionHandlerAddressResolver(classManager, METHOD); int actual = exceptionResolver.resolve(EXCEPTION3, currentAddress); assertEquals(handlerCodeAddress2, actual); }
@Test public void overlappingTryBlocksWithOneValidHandler() { int currentAddress = 2; int tryStartAddress1 = 1; int tryStartAddress2 = 2; int tryCodeUnits = 10; int handlerCodeAddress1 = 20; int handlerCodeAddress2 = 30; List<BuilderExceptionHandler> handlers1 = new LinkedList<BuilderExceptionHandler>(); handlers1.add(buildHandler(handlerCodeAddress1, exceptionClass1)); tryBlocks.add(buildTryBlock(tryStartAddress1, tryCodeUnits, handlers1)); List<BuilderExceptionHandler> handlers2 = new LinkedList<BuilderExceptionHandler>(); handlers2.add(buildHandler(handlerCodeAddress2, exceptionClass2)); tryBlocks.add(buildTryBlock(tryStartAddress2, tryCodeUnits, handlers2)); ExceptionHandlerAddressResolver exceptionResolver = new ExceptionHandlerAddressResolver(classManager, METHOD); String name = exceptionClass1.getName(); int actual = exceptionResolver.resolve(name, currentAddress); assertEquals(handlerCodeAddress1, actual); }
int resolve(Throwable ex, int address) { String className = ClassNameUtils.binaryToInternal(ex.getClass().getName()); return resolve(className, address); }
int childAddress = exceptionResolver.resolve(e, node.getAddress()); if (childAddress <= 0) { throw new RuntimeException("Real exception was thrown executing " + node +
private static void spawnExceptionChildren(ExecutionGraph graph, ExecutionNode node, ExceptionHandlerAddressResolver exceptionResolver) throws UnhandledVirtualException { if (node.mayThrowException()) { for (Throwable exception : node.getExceptions()) { if (log.isTraceEnabled()) { log.trace("{} may throw virtual exception: ", node, exception); } int childAddress = exceptionResolver.resolve(exception, node.getAddress()); if (childAddress >= 0) { ExecutionNode childNode = spawnChild(graph, node, childAddress); childNode.getContext().getMethodState().assignExceptionRegister(exception); } else { if (node.getChildLocations().length == 0) { if (log.isErrorEnabled()) { // No children, probably a real exception log.error("{} unhandled virtual exception: ", node, exception); } throw new UnhandledVirtualException(exception); } else { // Op has children, doesn't *always* throw, probably virtual exception if (log.isTraceEnabled()) { log.trace("{} possible unhandled virtual exception: ", node, exception); } } } } } }