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.baseline; 014 015/** 016 * Structure to describe the basic blocks of the byte code Used in calculating 017 * stack map and local variable map for the garbage collector. 018 */ 019final class BasicBlock { 020 021 // NOTE: Block number 1 is the epilog block, the only block 022 // that exits from the method. Blocks that end in a return will 023 // have the exit block as their only successor. 024 // NOTE: Block number 0 is NOT used; 025 026 // ------------------- Static Class Fields ----------------- 027 028 static final int NOTBLOCK = 0; 029 static final int EXITBLOCK = 1; 030 static final int STARTPREDSIZE = 4; 031 static final int STARTBBNUMBER = 2; 032 033 static final byte JSRENTRY = 1; 034 static final byte JSREXIT = 2; 035 static final byte METHODENTRY = 4; 036 static final byte TRYSTART = 8; 037 static final byte TRYBLOCK = 16; 038 static final byte INJSR = 32; 039 static final byte TRYHANDLERSTART = 64; 040 041 // --------------------- Instance Fields --------------------- 042 043 /** ID number (index into block array) */ 044 private final int blockNumber; 045 /** starting byte in byte code array */ 046 private int start; 047 /** ending byte in byte code array */ 048 private int end; 049 /** number of preceding basic blocks */ 050 private int predcount = 0; 051 // First 2 are listed individually. 052 private short pred1; 053 private short pred2; 054 /** list of rest preceding basic blocks */ 055 private short[] restPredecessors; 056 // may be bigger then predcount; 057 /** additional state info for jsr handling, and other flags */ 058 private byte state = 0; 059 060 // --------------- Constructor -------------------------------- 061 062 /** 063 * This should be called only from the factory. 064 * 065 * @param startval byte index where block starts 066 * @param bn the block's number 067 * */ 068 BasicBlock(int startval, int bn) { 069 blockNumber = bn; 070 start = startval; 071 } 072 073 /** 074 * This should be used when building the EXIT block EXIT is likely to have 075 * several predecessors. 076 * 077 * @param startval byte index where block starts 078 * @param endval byte index where block starts 079 * @param blockNumber the block's number 080 */ 081 BasicBlock(int startval, int endval, int blockNumber) { 082 start = startval; 083 end = endval; 084 this.blockNumber = blockNumber; 085 restPredecessors = new short[STARTPREDSIZE]; 086 } 087 088 // ------------------ Static Methods ------------------------- 089 090 static void transferPredecessors(BasicBlock fromBB, 091 BasicBlock toBB) { 092 toBB.predcount = fromBB.predcount; 093 toBB.pred1 = fromBB.pred1; 094 toBB.pred2 = fromBB.pred2; 095 toBB.restPredecessors = fromBB.restPredecessors; 096 097 fromBB.predcount = 0; 098 fromBB.restPredecessors = null; 099 } 100 101 // -------------------------- Instance Methods ---------------- 102 103 void setStart(int startval) { 104 start = startval; 105 } 106 107 void setEnd(int endval) { 108 end = endval; 109 } 110 111 void setState(byte stateval) { 112 state |= stateval; 113 } 114 115 int getStart() { 116 return start; 117 } 118 119 int getEnd() { 120 return end; 121 } 122 123 int getBlockNumber() { 124 return blockNumber; 125 } 126 127 byte getState() { 128 return state; 129 } 130 131 boolean isJSRExit() { 132 return ((state & JSREXIT) == JSREXIT); 133 } 134 135 boolean isJSREntry() { 136 return ((state & JSRENTRY) == JSRENTRY); 137 } 138 139 boolean isInJSR() { 140 return ((state & INJSR) == INJSR); 141 } 142 143 boolean isMethodEntry() { 144 return ((state & METHODENTRY) == METHODENTRY); 145 } 146 147 boolean isTryStart() { 148 return ((state & TRYSTART) == TRYSTART); 149 } 150 151 boolean isTryBlock() { 152 return ((state & TRYBLOCK) == TRYBLOCK); 153 } 154 155 boolean isTryHandlerStart() { 156 return ((state & TRYHANDLERSTART) == TRYHANDLERSTART); 157 } 158 159 void addPredecessor(BasicBlock predbb) { 160 predcount++; 161 if (predcount == 1) { 162 pred1 = (short) predbb.getBlockNumber(); 163 } else if (predcount == 2) { 164 pred2 = (short) predbb.getBlockNumber(); 165 } else if (restPredecessors == null) { 166 restPredecessors = new short[STARTPREDSIZE]; 167 restPredecessors[predcount - 3] = (short) predbb.getBlockNumber(); 168 } else { 169 if (restPredecessors.length <= predcount - 3) { 170 short[] newpreds = new short[predcount << 1]; 171 int restLength = restPredecessors.length; 172 for (int i = 0; i < restLength; i++) { 173 newpreds[i] = restPredecessors[i]; 174 } 175 restPredecessors = newpreds; 176 newpreds = null; 177 } 178 restPredecessors[predcount - 3] = (short) predbb.getBlockNumber(); 179 // -3 to get it zero-based 180 } 181 } 182 183 /** 184 * This method first checks if a block is already on the predecessor list. 185 * Used with try blocks being added to their catch block as predecessors. 186 * 187 * @param predbb block to add as predecessor 188 */ 189 void addUniquePredecessor(BasicBlock predbb) { 190 boolean dupFound = false, checkMade = false; 191 short predbbNum = (short) predbb.getBlockNumber(); 192 193 if (predcount >= 1) { 194 if (pred1 == predbbNum) { 195 return; 196 } 197 198 if (predcount > 1) { 199 if (pred2 == predbbNum) { 200 return; 201 } 202 203 if (predcount > 2) { 204 if (restPredecessors.length <= predcount - 2) { 205 short[] newpreds = new short[predcount << 1]; 206 int restLength = restPredecessors.length; 207 for (int i = 0; i < restLength; i++) { 208 if (restPredecessors[i] == predbbNum) { 209 dupFound = true; // finish up the copy anyway. 210 } 211 newpreds[i] = restPredecessors[i]; 212 } 213 restPredecessors = newpreds; 214 newpreds = null; 215 216 if (dupFound) 217 return; 218 checkMade = true; 219 } 220 221 if (!checkMade) { 222 for (int i = 0; i < predcount - 2; i++) { 223 if (restPredecessors[i] == predbbNum) { 224 return; 225 } 226 } 227 } 228 229 predcount++; 230 restPredecessors[predcount - 3] = predbbNum; 231 } else { // predcount must be 2 232 restPredecessors = new short[STARTPREDSIZE]; 233 predcount++; 234 restPredecessors[predcount - 3] = predbbNum; 235 } 236 } else { 237 // predcount must be 1 238 predcount++; 239 pred2 = predbbNum; 240 } 241 } else { // predcount must be 0 242 predcount++; 243 pred1 = predbbNum; 244 } 245 } 246 247 int[] getPredecessors() { 248 int[] preds; 249 preds = new int[predcount]; 250 if (predcount >= 1) { 251 preds[0] = pred1; 252 } 253 if (predcount > 1) { 254 preds[1] = pred2; 255 } 256 for (int i = 0; i < predcount - 2; i++) { 257 preds[i + 2] = restPredecessors[i]; 258 } 259 return preds; 260 261 } 262 263}