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.compilers.common;
014
015 import org.jikesrvm.VM;
016 import org.jikesrvm.Services;
017 import org.jikesrvm.classloader.DynamicTypeCheck;
018 import org.jikesrvm.classloader.RVMType;
019 import org.jikesrvm.objectmodel.TIB;
020 import org.vmmagic.pragma.Unpreemptible;
021 import org.vmmagic.unboxed.Offset;
022
023 /**
024 * Encoding of try ranges in the final machinecode and the
025 * corresponding exception type and catch block start.
026 */
027 public abstract class ExceptionTable {
028
029 /**
030 * An eTable array encodes the exception tables using 4 ints for each
031 */
032 protected static final int TRY_START = 0;
033 protected static final int TRY_END = 1;
034 protected static final int CATCH_START = 2;
035 protected static final int EX_TYPE = 3;
036
037 /**
038 * Return the machine code offset for the catch block that will handle
039 * the argument exceptionType,or -1 if no such catch block exists.
040 *
041 * @param eTable the encoded exception table to search
042 * @param instructionOffset the offset of the instruction after the PEI.
043 * @param exceptionType the type of exception that was raised
044 * @return the machine code offset of the catch block.
045 */
046 @Unpreemptible
047 public static int findCatchBlockForInstruction(int[] eTable, Offset instructionOffset, RVMType exceptionType) {
048 for (int i = 0, n = eTable.length; i < n; i += 4) {
049 // note that instructionOffset points to the instruction after the PEI
050 // so the range check here must be "offset > beg && offset <= end"
051 // and not "offset >= beg && offset < end"
052 //
053 // offset starts are sorted by starting point
054 if (instructionOffset.sGT(Offset.fromIntSignExtend(eTable[i + TRY_START])) &&
055 instructionOffset.sLE(Offset.fromIntSignExtend(eTable[i + TRY_END]))) {
056 RVMType lhs = RVMType.getType(eTable[i + EX_TYPE]);
057 if (lhs == exceptionType) {
058 return eTable[i + CATCH_START];
059 } else if (lhs.isInitialized()) {
060 TIB rhsTIB = exceptionType.getTypeInformationBlock();
061 if (DynamicTypeCheck.instanceOfClass(lhs.asClass(), rhsTIB)) {
062 return eTable[i + CATCH_START];
063 }
064 }
065 }
066 }
067 return -1;
068 }
069
070 /**
071 * Print an encoded exception table.
072 * @param eTable the encoded exception table to print.
073 */
074 public static void printExceptionTable(int[] eTable) {
075 int length = eTable.length;
076 VM.sysWriteln("Exception Table:");
077 VM.sysWriteln(" trystart tryend catch type");
078 for (int i = 0; i < length; i += 4) {
079 VM.sysWriteln(" " +
080 Services.getHexString(eTable[i + TRY_START], true) +
081 " " +
082 Services.getHexString(eTable[i + TRY_END], true) +
083 " " +
084 Services.getHexString(eTable[i + CATCH_START], true) +
085 " " +
086 RVMType.getType(eTable[i + EX_TYPE]));
087 }
088 }
089 }
090
091
092