001 /* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013 package org.jikesrvm.classloader; 014 015 import java.io.DataInputStream; 016 import java.io.IOException; 017 018 /** 019 * A java method's try/catch/finally information. 020 */ 021 public final class ExceptionHandlerMap { 022 //-----------// 023 // Interface // 024 //-----------// 025 026 public int[] getStartPC() { return startPCs; } 027 028 public int[] getEndPC() { return endPCs; } 029 030 public int[] getHandlerPC() { return handlerPCs; } 031 032 public TypeReference[] getExceptionTypes() { return exceptionTypes; } 033 034 public TypeReference getExceptionType(int i) { return exceptionTypes[i]; } 035 036 /* we need to adjust the exception handler map for pseudo bytecode 037 * TODO: OSR redesign; make a subclass of ExceptionHandlerMap with this functionality 038 */ 039 public void setStartPC(int[] newPCs) { startPCs = newPCs; } 040 041 public void setEndPC(int[] newPCs) { endPCs = newPCs; } 042 043 public void setHandlerPC(int[] newPCs) { handlerPCs = newPCs; } 044 045 //----------------// 046 // Implementation // 047 //----------------// 048 049 /** 050 * bytecode offset at which i-th try block begins 051 * 0-indexed from start of method's bytecodes[] 052 */ 053 private int[] startPCs; 054 055 /** 056 * bytecode offset at which i-th try block ends (exclusive) 057 * 0-indexed from start of method's bytecodes[] 058 */ 059 private int[] endPCs; 060 061 /** 062 * bytecode offset at which exception handler for i-th try block begins 063 * 0-indexed from start of method's bytecodes[] 064 */ 065 private int[] handlerPCs; 066 067 /** 068 * exception type for which i-th handler is to be invoked 069 * - something like "java/lang/IOException". 070 * NOTE: When constructing the ExceptionHandlerMap we replace 071 * 'null' entries (means a finally block that catches everything) 072 * with RVMType.JavaLangThrowableType so we don't have to do anything 073 * special anywhere else in the VM. 074 */ 075 private final TypeReference[] exceptionTypes; 076 077 /** 078 * Construct the exception handler map 079 * 080 * @param startPCs 081 * @param endPCs 082 * @param handlerPCs 083 * @param exceptionTypes 084 */ 085 private ExceptionHandlerMap(int[] startPCs, int[] endPCs, int[] handlerPCs, TypeReference[] exceptionTypes) { 086 this.startPCs = startPCs; 087 this.endPCs = endPCs; 088 this.handlerPCs = handlerPCs; 089 this.exceptionTypes = exceptionTypes; 090 } 091 092 /** 093 * Read the exception handler map 094 * 095 * @return an exception handler map or null if none were present 096 */ 097 static ExceptionHandlerMap readExceptionHandlerMap(DataInputStream input, int[] constantPool) throws IOException { 098 int cnt = input.readUnsignedShort(); 099 if (cnt != 0) { 100 int[] startPCs = new int[cnt]; 101 int[] endPCs = new int[cnt]; 102 int[] handlerPCs = new int[cnt]; 103 TypeReference[] exceptionTypes = new TypeReference[cnt]; 104 for (int i = 0; i < cnt; ++i) { 105 startPCs[i] = input.readUnsignedShort(); 106 endPCs[i] = input.readUnsignedShort(); 107 handlerPCs[i] = input.readUnsignedShort(); 108 TypeReference et = ClassFileReader.getTypeRef(constantPool, input.readUnsignedShort()); // possibly null 109 if (et == null) { 110 // A finally block...set to java.lang.Throwable to avoid 111 // needing to think about this case anywhere else in the VM. 112 exceptionTypes[i] = TypeReference.JavaLangThrowable; 113 } else { 114 exceptionTypes[i] = et; 115 } 116 } 117 return new ExceptionHandlerMap(startPCs, endPCs, handlerPCs, exceptionTypes); 118 } else { 119 return null; 120 } 121 } 122 123 ExceptionHandlerMap deepCopy() { 124 int n = startPCs.length; 125 int[] copyStartPCs = new int[n]; 126 System.arraycopy(this.startPCs, 0, copyStartPCs, 0, n); 127 int[] copyEndPCs = new int[n]; 128 System.arraycopy(this.endPCs, 0, copyEndPCs, 0, n); 129 int[] copyHandlerPCs = new int[n]; 130 System.arraycopy(this.handlerPCs, 0, copyHandlerPCs, 0, n); 131 TypeReference[] copyExceptionTypes = new TypeReference[n]; 132 System.arraycopy(this.exceptionTypes, 0, copyExceptionTypes, 0, n); 133 134 return new ExceptionHandlerMap(copyStartPCs, copyEndPCs, copyHandlerPCs, copyExceptionTypes); 135 } 136 }