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 */ 013package org.jikesrvm.compilers.common; 014 015import org.jikesrvm.VM; 016import org.jikesrvm.classloader.DynamicTypeCheck; 017import org.jikesrvm.classloader.RVMType; 018import org.jikesrvm.objectmodel.TIB; 019import org.jikesrvm.util.Services; 020import org.vmmagic.pragma.Uninterruptible; 021import org.vmmagic.pragma.Unpreemptible; 022import org.vmmagic.unboxed.Offset; 023 024/** 025 * Encoding of try ranges in the final machinecode and the 026 * corresponding exception type and catch block start. 027 */ 028public abstract class ExceptionTable { 029 030 /** 031 * An eTable array encodes the exception tables using 4 ints for each 032 */ 033 protected static final int TRY_START = 0; 034 protected static final int TRY_END = 1; 035 protected static final int CATCH_START = 2; 036 protected static final int EX_TYPE = 3; 037 038 /** 039 * Return the machine code offset for the catch block that will handle 040 * the argument exceptionType,or -1 if no such catch block exists. 041 * 042 * @param eTable the encoded exception table to search 043 * @param instructionOffset the offset of the instruction after the PEI. 044 * @param exceptionType the type of exception that was raised 045 * @return the machine code offset of the catch block. 046 */ 047 @Unpreemptible 048 public static int findCatchBlockForInstruction(int[] eTable, Offset instructionOffset, RVMType exceptionType) { 049 for (int i = 0, n = eTable.length; i < n; i += 4) { 050 // note that instructionOffset points to the instruction after the PEI 051 // so the range check here must be "offset > beg && offset <= end" 052 // and not "offset >= beg && offset < end" 053 // 054 // offset starts are sorted by starting point 055 if (instructionOffset.sGT(Offset.fromIntSignExtend(eTable[i + TRY_START])) && 056 instructionOffset.sLE(Offset.fromIntSignExtend(eTable[i + TRY_END]))) { 057 RVMType lhs = RVMType.getType(eTable[i + EX_TYPE]); 058 if (lhs == exceptionType) { 059 return eTable[i + CATCH_START]; 060 } else if (lhs.isInitialized()) { 061 TIB rhsTIB = exceptionType.getTypeInformationBlock(); 062 if (DynamicTypeCheck.instanceOfClass(lhs.asClass(), rhsTIB)) { 063 return eTable[i + CATCH_START]; 064 } 065 } 066 } 067 } 068 return -1; 069 } 070 071 /** 072 * Print an encoded exception table. 073 * @param eTable the encoded exception table to print. 074 */ 075 public static void printExceptionTable(int[] eTable) { 076 writeExceptionTableHeader(); 077 int length = eTable.length; 078 for (int i = 0; i < length; i += 4) { 079 printNicelyFormattedAndInterruptible(eTable, i); 080 } 081 } 082 083 @Uninterruptible 084 private static void writeExceptionTableHeader() { 085 VM.sysWriteln("Exception Table:"); 086 VM.sysWriteln(" trystart tryend catch type"); 087 } 088 089 private static void printNicelyFormattedAndInterruptible(int[] eTable, int i) { 090 VM.sysWriteln(" " + 091 Services.getHexString(eTable[i + TRY_START], true) + 092 " " + 093 Services.getHexString(eTable[i + TRY_END], true) + 094 " " + 095 Services.getHexString(eTable[i + CATCH_START], true) + 096 " " + 097 RVMType.getType(eTable[i + EX_TYPE])); 098 } 099 100 101 /** 102 * Prints an exception table. 103 * <p> 104 * This method does the same thing as {@link #printExceptionTable(int[])} but 105 * with less nicely formatted output because of the constraints imposed by 106 * the requirements for uninterruptible code. 107 * 108 * @param eTable the exception table to print 109 */ 110 @Uninterruptible 111 public static void printExceptionTableUninterruptible(int[] eTable) { 112 writeExceptionTableHeader(); 113 int length = eTable.length; 114 for (int i = 0; i < length; i += 4) { 115 printLessNicelyFormattedAndUninterruptible(eTable, i); 116 } 117 } 118 119 @Uninterruptible 120 private static void printLessNicelyFormattedAndUninterruptible(int[] eTable, 121 int i) { 122 VM.sysWrite(" "); 123 VM.sysWriteHex(eTable[i + TRY_START]); 124 VM.sysWrite(" "); 125 VM.sysWriteHex(eTable[i + TRY_END]); 126 VM.sysWrite(" "); 127 VM.sysWriteHex(eTable[i + CATCH_START]); 128 VM.sysWrite(" "); 129 VM.sysWrite(RVMType.getType(eTable[i + EX_TYPE]).getDescriptor()); 130 VM.sysWriteln(); 131 } 132} 133 134 135