/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Common Public License (CPL); * 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/cpl1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.jikesrvm.compilers.common; import org.jikesrvm.VM; import org.jikesrvm.VM_Services; import org.jikesrvm.classloader.VM_DynamicTypeCheck; import org.jikesrvm.classloader.VM_Type; import org.vmmagic.unboxed.Offset; /** * Encoding of try ranges in the final machinecode and the * corresponding exception type and catch block start. */ public abstract class VM_ExceptionTable { /** * An eTable array encodes the exception tables using 4 ints for each */ protected static final int TRY_START = 0; protected static final int TRY_END = 1; protected static final int CATCH_START = 2; protected static final int EX_TYPE = 3; /** * Return the machine code offset for the catch block that will handle * the argument exceptionType,or -1 if no such catch block exists. * * @param eTable the encoded exception table to search * @param instructionOffset the offset of the instruction after the PEI. * @param exceptionType the type of exception that was raised * @return the machine code offset of the catch block. */ public static int findCatchBlockForInstruction(int[] eTable, Offset instructionOffset, VM_Type exceptionType, boolean forSubArch) { for (int i = 0, n = eTable.length; i < n; i += 4) { // note that instructionOffset points to the instruction after the PEI // so the range check here must be "offset > beg && offset <= end" // and not "offset >= beg && offset < end" // // offset starts are sorted by starting point if (instructionOffset.sGT(Offset.fromIntSignExtend(eTable[i + TRY_START])) && instructionOffset.sLE(Offset.fromIntSignExtend(eTable[i + TRY_END]))) { VM_Type lhs = VM_Type.getType(eTable[i + EX_TYPE]); if (lhs == exceptionType) { return eTable[i + CATCH_START]; } else if (lhs.isInitialized(forSubArch)) { Object[] rhsTIB = exceptionType.getTypeInformationBlock(); if (VM_DynamicTypeCheck.instanceOfClass(lhs.asClass(), rhsTIB)) { return eTable[i + CATCH_START]; } } } } return -1; } /** * Print an encoded exception table. * @param eTable the encoded exception table to print. */ public static void printExceptionTable(int[] eTable) { int length = eTable.length; VM.sysWriteln("Exception Table:"); VM.sysWriteln(" trystart tryend catch type"); for (int i = 0; i < length; i += 4) { VM.sysWriteln(" " + VM_Services.getHexString(eTable[i + TRY_START], true) + " " + VM_Services.getHexString(eTable[i + TRY_END], true) + " " + VM_Services.getHexString(eTable[i + CATCH_START], true) + " " + VM_Type.getType(eTable[i + EX_TYPE])); } } }