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.opt.ir; 014 015 import static org.jikesrvm.compilers.opt.driver.OptConstants.MAYBE; 016 import static org.jikesrvm.compilers.opt.driver.OptConstants.NO; 017 import static org.jikesrvm.compilers.opt.driver.OptConstants.YES; 018 019 import java.util.Enumeration; 020 021 import org.jikesrvm.classloader.TypeReference; 022 import org.jikesrvm.compilers.opt.ClassLoaderProxy; 023 import org.jikesrvm.compilers.opt.inlining.InlineSequence; 024 import org.jikesrvm.compilers.opt.ir.operand.TypeOperand; 025 import org.jikesrvm.compilers.opt.liveness.LiveSet; 026 027 /** 028 * A basic block that marks the start of an exception handler. 029 * Exception Handler Basic Block; acronym EHBB. 030 */ 031 public final class ExceptionHandlerBasicBlock extends BasicBlock { 032 033 /** 034 * The RVMType(s) of the exception(s) caught by this block. 035 */ 036 private TypeOperand[] exceptionTypes; 037 038 /** 039 * The liveness information at the beginning of this block. 040 * <p> 041 * NOTE: If we decide to store this for all blocks, we should move 042 * this field to BasicBlock (the parent class) 043 */ 044 private LiveSet liveSet; 045 046 /** 047 * Creates a new exception handler basic block at the specified location, 048 * which catches the specified type of exception. 049 * 050 * @param loc Bytecode index to create basic block at 051 * @param position The inline context for this basic block 052 * @param type The exception type 053 * @param cfg The ControlFlowGraph that will contain the basic block 054 */ 055 public ExceptionHandlerBasicBlock(int loc, InlineSequence position, TypeOperand type, ControlFlowGraph cfg) { 056 super(loc, position, cfg); 057 exceptionTypes = new TypeOperand[1]; 058 exceptionTypes[0] = type; 059 setExceptionHandlerBasicBlock(); 060 liveSet = null; 061 } 062 063 /** 064 * Add a new exception type to an extant exception handler block. 065 * Do filtering of duplicates internally for efficiency. 066 * NOTE: this routine is only intended to be called by 067 * {@link org.jikesrvm.compilers.opt.bc2ir.BC2IR}. 068 * 069 * @param et the exception type to be added 070 */ 071 public void addCaughtException(TypeOperand et) { 072 for (TypeOperand exceptionType : exceptionTypes) { 073 if (exceptionType.similar(et)) return; 074 } 075 TypeOperand[] newets = new TypeOperand[exceptionTypes.length + 1]; 076 for (int i = 0; i < exceptionTypes.length; i++) { 077 newets[i] = exceptionTypes[i]; 078 } 079 newets[exceptionTypes.length] = et; 080 exceptionTypes = newets; 081 } 082 083 /** 084 * Return YES/NO/MAYBE values that answer the question is it possible for 085 * this handler block to catch an exception of the type et. 086 * 087 * @param cand the TypeReference of the exception in question. 088 * @return YES, NO, MAYBE 089 */ 090 public byte mayCatchException(TypeReference cand) { 091 boolean seenMaybe = false; 092 byte t; 093 for (TypeOperand exceptionType : exceptionTypes) { 094 t = ClassLoaderProxy.includesType(exceptionType.getTypeRef(), cand); 095 if (t == YES) return YES; 096 seenMaybe |= (t == MAYBE); 097 t = ClassLoaderProxy.includesType(cand, exceptionType.getTypeRef()); 098 if (t == YES) return YES; 099 seenMaybe |= (t == MAYBE); 100 } 101 return seenMaybe ? MAYBE : NO; 102 } 103 104 /** 105 * Return YES/NO/MAYBE values that answer the question is it guarenteed that 106 * this handler block will catch an exception of type <code>cand</code> 107 * 108 * @param cand the TypeReference of the exception in question. 109 * @return YES, NO, MAYBE 110 */ 111 public byte mustCatchException(TypeReference cand) { 112 boolean seenMaybe = false; 113 byte t; 114 for (TypeOperand exceptionType : exceptionTypes) { 115 t = ClassLoaderProxy.includesType(exceptionType.getTypeRef(), cand); 116 if (t == YES) return YES; 117 seenMaybe |= (t == MAYBE); 118 } 119 if (seenMaybe) { 120 return MAYBE; 121 } else { 122 return NO; 123 } 124 } 125 126 /** 127 * Return an Enumeration of the caught exception types. 128 * Mainly intended for creation of exception tables during 129 * final assembly. Most other clients shouldn't care about this 130 * level of detail. 131 */ 132 public Enumeration<TypeOperand> getExceptionTypes() { 133 return new Enumeration<TypeOperand>() { 134 private int idx = 0; 135 136 @Override 137 public boolean hasMoreElements() { 138 return idx != exceptionTypes.length; 139 } 140 141 @Override 142 public TypeOperand nextElement() { 143 try { 144 return exceptionTypes[idx++]; 145 } catch (ArrayIndexOutOfBoundsException e) { 146 throw new java.util.NoSuchElementException("ExceptionHandlerBasicBlock.getExceptionTypes"); 147 } 148 } 149 }; 150 } 151 152 /** 153 * Get how many table entries this EHBB needs. 154 * Really only of interest during final assembly. 155 * 156 * @see org.jikesrvm.compilers.opt.runtimesupport.OptExceptionTable 157 * 158 * @return the number of table entries for this basic block 159 */ 160 public int getNumberOfExceptionTableEntries() { 161 return exceptionTypes.length; 162 } 163 164 /** 165 * Returns the set of registers live before the first instruction of 166 * this basic block 167 * 168 * @return the set of registers live before the first instruction of 169 * this basic block 170 */ 171 public LiveSet getLiveSet() { 172 return liveSet; 173 } 174 175 /** 176 * Set the set of registers live before the first instruction of 177 * this basic block 178 * 179 * @param liveSet The set of registers live before the first instruction of 180 * this basic block 181 */ 182 public void setLiveSet(LiveSet liveSet) { 183 this.liveSet = liveSet; 184 } 185 186 /** 187 * Return a string representation of the basic block 188 * (augment {@link BasicBlock#toString} with 189 * the exceptions caught by this handler block). 190 * 191 * @return a string representation of the block 192 */ 193 @Override 194 public String toString() { 195 String exmsg = " (catches "; 196 for (int i = 0; i < exceptionTypes.length - 1; i++) { 197 exmsg = exmsg + exceptionTypes[i].toString() + ", "; 198 } 199 exmsg = exmsg + exceptionTypes[exceptionTypes.length - 1].toString(); 200 exmsg = exmsg + " for"; 201 Enumeration<BasicBlock> in = getIn(); 202 while (in.hasMoreElements()) { 203 exmsg = exmsg + " " + in.nextElement().toString(); 204 } 205 exmsg = exmsg + ")"; 206 207 return super.toString() + exmsg; 208 } 209 }