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 }