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