/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Common Public License (CPL); * 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/cpl1.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 VM_ExceptionHandlerMap { //-----------// // Interface // //-----------// public int[] getStartPC() { return startPCs; } public int[] getEndPC() { return endPCs; } public int[] getHandlerPC() { return handlerPCs; } public VM_TypeReference[] getExceptionTypes() { return exceptionTypes; } public VM_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 VM_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 VM_ExceptionHandlerMap we replace * 'null' entries (means a finally block that catches everything) * with VM_Type.JavaLangThrowableType so we don't have to do anything * special anywhere else in the VM. */ private final VM_TypeReference[] exceptionTypes; /** * Construct the exception handler map * * @param startPCs * @param endPCs * @param handlerPCs * @param exceptionTypes */ private VM_ExceptionHandlerMap(int[] startPCs, int[] endPCs, int[] handlerPCs, VM_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 VM_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]; VM_TypeReference[] exceptionTypes = new VM_TypeReference[cnt]; for (int i = 0; i < cnt; ++i) { startPCs[i] = input.readUnsignedShort(); endPCs[i] = input.readUnsignedShort(); handlerPCs[i] = input.readUnsignedShort(); VM_TypeReference et = VM_Class.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] = VM_TypeReference.JavaLangThrowable; } else { exceptionTypes[i] = et; } } return new VM_ExceptionHandlerMap(startPCs, endPCs, handlerPCs, exceptionTypes); } else { return null; } } VM_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); VM_TypeReference[] copyExceptionTypes = new VM_TypeReference[n]; System.arraycopy(this.exceptionTypes, 0, copyExceptionTypes, 0, n); return new VM_ExceptionHandlerMap(copyStartPCs, copyEndPCs, copyHandlerPCs, copyExceptionTypes); } }