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