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.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 */ 019 final 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 public static final int NOTBLOCK = 0; 029 public static final int EXITBLOCK = 1; 030 public static final int STARTPREDSIZE = 4; 031 public 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 /** This should be called only from the factory. */ 063 BasicBlock(int startval, int bn) { 064 blockNumber = bn; 065 start = startval; 066 } 067 068 /** 069 * This should be used when building the EXIT block EXIT is likely to have 070 * several predecessors. 071 */ 072 BasicBlock(int startval, int endval, int blockNumber) { 073 start = startval; 074 end = endval; 075 this.blockNumber = blockNumber; 076 restPredecessors = new short[STARTPREDSIZE]; 077 } 078 079 // ------------------ Static Methods ------------------------- 080 081 /** transfer predecessor blocks from one block to another */ 082 public static void transferPredecessors(BasicBlock fromBB, 083 BasicBlock toBB) { 084 toBB.predcount = fromBB.predcount; 085 toBB.pred1 = fromBB.pred1; 086 toBB.pred2 = fromBB.pred2; 087 toBB.restPredecessors = fromBB.restPredecessors; 088 089 fromBB.predcount = 0; 090 fromBB.restPredecessors = null; 091 } 092 093 // -------------------------- Instance Methods ---------------- 094 095 void setStart(int startval) { 096 start = startval; 097 } 098 099 void setEnd(int endval) { 100 end = endval; 101 } 102 103 void setState(byte stateval) { 104 state |= stateval; 105 } 106 107 public int getStart() { 108 return start; 109 } 110 111 public int getEnd() { 112 return end; 113 } 114 115 public int getBlockNumber() { 116 return blockNumber; 117 } 118 119 public byte getState() { 120 return state; 121 } 122 123 public boolean isJSRExit() { 124 return ((state & JSREXIT) == JSREXIT); 125 } 126 127 public boolean isJSREntry() { 128 return ((state & JSRENTRY) == JSRENTRY); 129 } 130 131 public boolean isInJSR() { 132 return ((state & INJSR) == INJSR); 133 } 134 135 public boolean isMethodEntry() { 136 return ((state & METHODENTRY) == METHODENTRY); 137 } 138 139 public boolean isTryStart() { 140 return ((state & TRYSTART) == TRYSTART); 141 } 142 143 public boolean isTryBlock() { 144 return ((state & TRYBLOCK) == TRYBLOCK); 145 } 146 147 public boolean isTryHandlerStart() { 148 return ((state & TRYHANDLERSTART) == TRYHANDLERSTART); 149 } 150 151 public void addPredecessor(BasicBlock predbb) { 152 predcount++; 153 if (predcount == 1) { 154 pred1 = (short) predbb.getBlockNumber(); 155 } else if (predcount == 2) { 156 pred2 = (short) predbb.getBlockNumber(); 157 } else if (restPredecessors == null) { 158 restPredecessors = new short[STARTPREDSIZE]; 159 restPredecessors[predcount - 3] = (short) predbb.getBlockNumber(); 160 } else { 161 if (restPredecessors.length <= predcount - 3) { 162 short[] newpreds = new short[predcount << 1]; 163 int restLength = restPredecessors.length; 164 for (int i = 0; i < restLength; i++) { 165 newpreds[i] = restPredecessors[i]; 166 } 167 restPredecessors = newpreds; 168 newpreds = null; 169 } 170 restPredecessors[predcount - 3] = (short) predbb.getBlockNumber(); 171 // -3 to get it zero-based 172 } 173 } 174 175 /** 176 * This method first checks if a block is already on the predecessor list. 177 * Used with try blocks being added to their catch block as predecessors. 178 */ 179 public void addUniquePredecessor(BasicBlock predbb) { 180 boolean dupFound = false, checkMade = false; 181 short predbbNum = (short) predbb.getBlockNumber(); 182 183 if (predcount >= 1) { 184 if (pred1 == predbbNum) { 185 return; 186 } 187 188 if (predcount > 1) { 189 if (pred2 == predbbNum) { 190 return; 191 } 192 193 if (predcount > 2) { 194 if (restPredecessors.length <= predcount - 2) { 195 short[] newpreds = new short[predcount << 1]; 196 int restLength = restPredecessors.length; 197 for (int i = 0; i < restLength; i++) { 198 if (restPredecessors[i] == predbbNum) { 199 dupFound = true; // finish up the copy anyway. 200 } 201 newpreds[i] = restPredecessors[i]; 202 } 203 restPredecessors = newpreds; 204 newpreds = null; 205 206 if (dupFound) 207 return; 208 checkMade = true; 209 } 210 211 if (!checkMade) { 212 for (int i = 0; i < predcount - 2; i++) { 213 if (restPredecessors[i] == predbbNum) { 214 return; 215 } 216 } 217 } 218 219 predcount++; 220 restPredecessors[predcount - 3] = predbbNum; 221 } else { // predcount must be 2 222 restPredecessors = new short[STARTPREDSIZE]; 223 predcount++; 224 restPredecessors[predcount - 3] = predbbNum; 225 } 226 } else { 227 // predcount must be 1 228 predcount++; 229 pred2 = predbbNum; 230 } 231 } else { // predcount must be 0 232 predcount++; 233 pred1 = predbbNum; 234 } 235 } 236 237 public int[] getPredecessors() { 238 int[] preds; 239 preds = new int[predcount]; 240 if (predcount >= 1) { 241 preds[0] = pred1; 242 } 243 if (predcount > 1) { 244 preds[1] = pred2; 245 } 246 for (int i = 0; i < predcount - 2; i++) { 247 preds[i + 2] = restPredecessors[i]; 248 } 249 return preds; 250 251 } 252 253 }