/*
* 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;
private ExceptionHandlerMap(int[] startPCs, int[] endPCs, int[] handlerPCs, TypeReference[] exceptionTypes) {
this.startPCs = startPCs;
this.endPCs = endPCs;
this.handlerPCs = handlerPCs;
this.exceptionTypes = exceptionTypes;
}
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);
}
}