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