/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/eclipse-1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.jikesrvm.classloader; import java.io.DataInputStream; import java.io.IOException; /** * A java method's try/catch/finally information. */ public final class ExceptionHandlerMap { //-----------// // Interface // //-----------// public int[] getStartPC() { return startPCs; } public int[] getEndPC() { return endPCs; } public int[] getHandlerPC() { return handlerPCs; } public TypeReference[] getExceptionTypes() { return exceptionTypes; } public TypeReference getExceptionType(int i) { return exceptionTypes[i]; } /* we need to adjust the exception handler map for pseudo bytecode * TODO: OSR redesign; make a subclass of ExceptionHandlerMap with this functionality */ public void setStartPC(int[] newPCs) { startPCs = newPCs; } public void setEndPC(int[] newPCs) { endPCs = newPCs; } public void setHandlerPC(int[] newPCs) { handlerPCs = newPCs; } //----------------// // Implementation // //----------------// /** * bytecode offset at which i-th try block begins * 0-indexed from start of method's bytecodes[] */ private int[] startPCs; /** * bytecode offset at which i-th try block ends (exclusive) * 0-indexed from start of method's bytecodes[] */ private int[] endPCs; /** * bytecode offset at which exception handler for i-th try block begins * 0-indexed from start of method's bytecodes[] */ private int[] handlerPCs; /** * exception type for which i-th handler is to be invoked * - something like "java/lang/IOException". * NOTE: When constructing the ExceptionHandlerMap we replace * 'null' entries (means a finally block that catches everything) * with RVMType.JavaLangThrowableType so we don't have to do anything * special anywhere else in the VM. */ private final TypeReference[] exceptionTypes; /** * Construct the exception handler map * * @param startPCs * @param endPCs * @param handlerPCs * @param exceptionTypes */ private ExceptionHandlerMap(int[] startPCs, int[] endPCs, int[] handlerPCs, TypeReference[] exceptionTypes) { this.startPCs = startPCs; this.endPCs = endPCs; this.handlerPCs = handlerPCs; this.exceptionTypes = exceptionTypes; } /** * Read the exception handler map * * @return an exception handler map or null if none were present */ static ExceptionHandlerMap readExceptionHandlerMap(DataInputStream input, int[] constantPool) throws IOException { int cnt = input.readUnsignedShort(); if (cnt != 0) { int[] startPCs = new int[cnt]; int[] endPCs = new int[cnt]; int[] handlerPCs = new int[cnt]; TypeReference[] exceptionTypes = new TypeReference[cnt]; for (int i = 0; i < cnt; ++i) { startPCs[i] = input.readUnsignedShort(); endPCs[i] = input.readUnsignedShort(); handlerPCs[i] = input.readUnsignedShort(); TypeReference et = ClassFileReader.getTypeRef(constantPool, input.readUnsignedShort()); // possibly null if (et == null) { // A finally block...set to java.lang.Throwable to avoid // needing to think about this case anywhere else in the VM. exceptionTypes[i] = TypeReference.JavaLangThrowable; } else { exceptionTypes[i] = et; } } return new ExceptionHandlerMap(startPCs, endPCs, handlerPCs, exceptionTypes); } else { return null; } } ExceptionHandlerMap deepCopy() { int n = startPCs.length; int[] copyStartPCs = new int[n]; System.arraycopy(this.startPCs, 0, copyStartPCs, 0, n); int[] copyEndPCs = new int[n]; System.arraycopy(this.endPCs, 0, copyEndPCs, 0, n); int[] copyHandlerPCs = new int[n]; System.arraycopy(this.handlerPCs, 0, copyHandlerPCs, 0, n); TypeReference[] copyExceptionTypes = new TypeReference[n]; System.arraycopy(this.exceptionTypes, 0, copyExceptionTypes, 0, n); return new ExceptionHandlerMap(copyStartPCs, copyEndPCs, copyHandlerPCs, copyExceptionTypes); } }