1 11 package org.eclipse.jdt.internal.compiler.codegen; 12 13 import java.text.MessageFormat ; 14 15 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; 16 import org.eclipse.jdt.internal.compiler.lookup.TypeIds; 17 18 public class StackMapFrame implements Cloneable { 19 public static final int USED = 1; 20 public static final int SAME_FRAME = 0; 21 public static final int CHOP_FRAME = 1; 22 public static final int APPEND_FRAME = 2; 23 public static final int SAME_FRAME_EXTENDED = 3; 24 public static final int FULL_FRAME = 4; 25 public static final int SAME_LOCALS_1_STACK_ITEMS = 5; 26 public static final int SAME_LOCALS_1_STACK_ITEMS_EXTENDED = 6; 27 28 public int pc; 29 public int numberOfStackItems; 30 private int numberOfLocals; 31 public int localIndex; 32 public VerificationTypeInfo[] locals; 33 public VerificationTypeInfo[] stackItems; 34 private int numberOfDifferentLocals = -1; 35 public int tagBits; 36 37 public StackMapFrame() { 38 this.numberOfLocals = -1; 39 this.numberOfDifferentLocals = -1; 40 } 41 public int getFrameType(StackMapFrame prevFrame) { 42 final int offsetDelta = this.getOffsetDelta(prevFrame); 43 switch(this.numberOfStackItems) { 44 case 0 : 45 switch(this.numberOfDifferentLocals(prevFrame)) { 46 case 0 : 47 return offsetDelta <= 63 ? SAME_FRAME : SAME_FRAME_EXTENDED; 48 case 1 : 49 case 2 : 50 case 3 : 51 return APPEND_FRAME; 52 case -1 : 53 case -2 : 54 case -3 : 55 return CHOP_FRAME; 56 } 57 break; 58 case 1 : 59 switch(this.numberOfDifferentLocals(prevFrame)) { 60 case 0 : 61 return offsetDelta <= 63 ? SAME_LOCALS_1_STACK_ITEMS : SAME_LOCALS_1_STACK_ITEMS_EXTENDED; 62 } 63 } 64 return FULL_FRAME; 65 } 66 public void addLocal(int resolvedPosition, VerificationTypeInfo info) { 67 if (this.locals == null) { 68 this.locals = new VerificationTypeInfo[resolvedPosition + 1]; 69 this.locals[resolvedPosition] = info; 70 } else { 71 final int length = this.locals.length; 72 if (resolvedPosition >= length) { 73 System.arraycopy(this.locals, 0, this.locals = new VerificationTypeInfo[resolvedPosition + 1], 0, length); 74 } 75 this.locals[resolvedPosition] = info; 76 } 77 } 78 public void addStackItem(VerificationTypeInfo info) { 79 if (info == null) return; 80 if (this.stackItems == null) { 81 this.stackItems = new VerificationTypeInfo[1]; 82 this.stackItems[0] = info; 83 this.numberOfStackItems = 1; 84 } else { 85 final int length = this.stackItems.length; 86 if (this.numberOfStackItems == length) { 87 System.arraycopy(this.stackItems, 0, this.stackItems = new VerificationTypeInfo[length + 1], 0, length); 88 } 89 this.stackItems[this.numberOfStackItems++] = info; 90 } 91 } 92 public void addStackItem(TypeBinding binding) { 93 this.addStackItem(new VerificationTypeInfo(binding)); 94 } 95 public Object clone() throws CloneNotSupportedException { 96 StackMapFrame result = (StackMapFrame) super.clone(); 97 result.numberOfLocals = -1; 98 result.numberOfDifferentLocals = -1; 99 result.pc = this.pc; 100 result.numberOfStackItems = this.numberOfStackItems; 101 102 int length = this.locals == null ? 0 : this.locals.length; 103 if (length != 0) { 104 result.locals = new VerificationTypeInfo[length]; 105 for (int i = 0; i < length; i++) { 106 final VerificationTypeInfo verificationTypeInfo = this.locals[i]; 107 if (verificationTypeInfo != null) { 108 result.locals[i] = (VerificationTypeInfo) verificationTypeInfo.clone(); 109 } 110 } 111 } 112 length = this.numberOfStackItems; 113 if (length != 0) { 114 result.stackItems = new VerificationTypeInfo[length]; 115 for (int i = 0; i < length; i++) { 116 result.stackItems[i] = (VerificationTypeInfo) this.stackItems[i].clone(); 117 } 118 } 119 return result; 120 } 121 public int numberOfDiffentStackItems(StackMapFrame prevFrame) { 122 if (prevFrame == null) { 123 return this.numberOfStackItems; 124 } 125 return this.numberOfStackItems - prevFrame.numberOfStackItems; 126 } 127 public int numberOfDifferentLocals(StackMapFrame prevFrame) { 128 if (this.numberOfDifferentLocals != -1) return this.numberOfDifferentLocals; 129 if (prevFrame == null) { 130 this.numberOfDifferentLocals = 0; 131 return 0; 132 } 133 VerificationTypeInfo[] prevLocals = prevFrame.locals; 134 VerificationTypeInfo[] currentLocals = this.locals; 135 int prevLocalsLength = prevLocals == null ? 0 : prevLocals.length; 136 int currentLocalsLength = currentLocals == null ? 0 : currentLocals.length; 137 int prevNumberOfLocals = prevFrame.getNumberOfLocals(); 138 int currentNumberOfLocals = this.getNumberOfLocals(); 139 140 int result = 0; 141 if (prevNumberOfLocals == 0) { 142 if (currentNumberOfLocals != 0) { 143 result = currentNumberOfLocals; int counter = 0; 146 for(int i = 0; i < currentLocalsLength && counter < currentNumberOfLocals; i++) { 147 if (currentLocals[i] != null) { 148 switch(currentLocals[i].id()) { 149 case TypeIds.T_double : 150 case TypeIds.T_long : 151 i++; 152 } 153 counter++; 154 } else { 155 result = Integer.MAX_VALUE; 156 this.numberOfDifferentLocals = result; 157 return result; 158 } 159 } 160 } 161 } else if (currentNumberOfLocals == 0) { 162 int counter = 0; 164 result = -prevNumberOfLocals; for(int i = 0; i < prevLocalsLength && counter < prevNumberOfLocals; i++) { 166 if (prevLocals[i] != null) { 167 switch(prevLocals[i].id()) { 168 case TypeIds.T_double : 169 case TypeIds.T_long : 170 i++; 171 } 172 counter++; 173 } else { 174 result = Integer.MAX_VALUE; 175 this.numberOfDifferentLocals = result; 176 return result; 177 } 178 } 179 } else { 180 int indexInPrevLocals = 0; 182 int indexInCurrentLocals = 0; 183 int currentLocalsCounter = 0; 184 int prevLocalsCounter = 0; 185 currentLocalsLoop: for (;indexInCurrentLocals < currentLocalsLength && currentLocalsCounter < currentNumberOfLocals; indexInCurrentLocals++) { 186 VerificationTypeInfo currentLocal = currentLocals[indexInCurrentLocals]; 187 if (currentLocal != null) { 188 currentLocalsCounter++; 189 switch(currentLocal.id()) { 190 case TypeIds.T_double : 191 case TypeIds.T_long : 192 indexInCurrentLocals++; } 194 } 195 for (;indexInPrevLocals < prevLocalsLength && prevLocalsCounter < prevNumberOfLocals; indexInPrevLocals++) { 196 VerificationTypeInfo prevLocal = prevLocals[indexInPrevLocals]; 197 if (prevLocal != null) { 198 prevLocalsCounter++; 199 switch(prevLocal.id()) { 200 case TypeIds.T_double : 201 case TypeIds.T_long : 202 indexInPrevLocals++; } 204 } 205 if (equals(prevLocal, currentLocal) && indexInPrevLocals == indexInCurrentLocals) { 208 if (result != 0) { 209 result = Integer.MAX_VALUE; 210 this.numberOfDifferentLocals = result; 211 return result; 212 } 213 } else { 214 result = Integer.MAX_VALUE; 216 this.numberOfDifferentLocals = result; 217 return result; 218 } 219 indexInPrevLocals++; 220 continue currentLocalsLoop; 221 } 222 if (currentLocal != null) { 224 result++; 225 } else { 226 result = Integer.MAX_VALUE; 227 this.numberOfDifferentLocals = result; 228 return result; 229 } 230 indexInCurrentLocals++; 231 break currentLocalsLoop; 232 } 233 if (currentLocalsCounter < currentNumberOfLocals) { 234 for(;indexInCurrentLocals < currentLocalsLength && currentLocalsCounter < currentNumberOfLocals; indexInCurrentLocals++) { 235 VerificationTypeInfo currentLocal = currentLocals[indexInCurrentLocals]; 236 if (currentLocal == null) { 237 result = Integer.MAX_VALUE; 238 this.numberOfDifferentLocals = result; 239 return result; 240 } 241 result++; 242 currentLocalsCounter++; 243 switch(currentLocal.id()) { 244 case TypeIds.T_double : 245 case TypeIds.T_long : 246 indexInCurrentLocals++; } 248 } 249 } else if (prevLocalsCounter < prevNumberOfLocals) { 250 result = -result; 251 for(; indexInPrevLocals < prevLocalsLength && prevLocalsCounter < prevNumberOfLocals; indexInPrevLocals++) { 253 VerificationTypeInfo prevLocal = prevLocals[indexInPrevLocals]; 254 if (prevLocal == null) { 255 result = Integer.MAX_VALUE; 256 this.numberOfDifferentLocals = result; 257 return result; 258 } 259 result--; 260 prevLocalsCounter++; 261 switch(prevLocal.id()) { 262 case TypeIds.T_double : 263 case TypeIds.T_long : 264 indexInPrevLocals++; } 266 } 267 } 268 } 269 this.numberOfDifferentLocals = result; 270 return result; 271 } 272 public int getNumberOfLocals() { 273 if (this.numberOfLocals != -1) { 274 return this.numberOfLocals; 275 } 276 int result = 0; 277 final int length = this.locals == null ? 0 : this.locals.length; 278 for(int i = 0; i < length; i++) { 279 if (this.locals[i] != null) { 280 switch(this.locals[i].id()) { 281 case TypeIds.T_double : 282 case TypeIds.T_long : 283 i++; 284 } 285 result++; 286 } 287 } 288 this.numberOfLocals = result; 289 return result; 290 } 291 public int getOffsetDelta(StackMapFrame prevFrame) { 292 if (prevFrame == null) return this.pc; 293 return prevFrame.pc == -1 ? this.pc : this.pc - prevFrame.pc - 1; 294 } 295 public String toString() { 296 StringBuffer buffer = new StringBuffer (); 297 printFrame(buffer, this); 298 return String.valueOf(buffer); 299 } 300 private void printFrame(StringBuffer buffer, StackMapFrame frame) { 301 String pattern = "[pc : {0} locals: {1} stack items: {2}\n{3}\n{4}\n]"; int localsLength = frame.locals == null ? 0 : frame.locals.length; 303 buffer.append(MessageFormat.format( 304 pattern, 305 new String [] { 306 Integer.toString(frame.pc), 307 Integer.toString(frame.getNumberOfLocals()), 308 Integer.toString(frame.numberOfStackItems), 309 print(frame.locals, localsLength), 310 print(frame.stackItems, frame.numberOfStackItems) 311 } 312 )); 313 } 314 private String print(VerificationTypeInfo[] infos, int length) { 315 StringBuffer buffer = new StringBuffer (); 316 buffer.append('['); 317 if (infos != null) { 318 for (int i = 0; i < length; i++) { 319 if (i != 0) buffer.append(','); 320 if (infos[i] == null) { 321 buffer.append("top"); continue; 323 } 324 switch(infos[i].tag) { 325 case VerificationTypeInfo.ITEM_NULL : 326 buffer.append("null"); break; 328 case VerificationTypeInfo.ITEM_UNINITIALIZED_THIS : 329 buffer.append("uninitialized_this"); break; 331 case VerificationTypeInfo.ITEM_TOP : 332 buffer.append("top"); break; 334 case VerificationTypeInfo.ITEM_UNINITIALIZED : 335 buffer.append("uninitialized(").append(infos[i].readableName()).append(")"); break; 337 default: 338 buffer.append(infos[i].readableName()); 339 } 340 } 341 } 342 buffer.append(']'); 343 return String.valueOf(buffer); 344 } 345 public void setTopOfStack(TypeBinding typeBinding) { 346 this.stackItems[this.numberOfStackItems - 1].setBinding(typeBinding); 347 } 348 public void initializeReceiver() { 349 if (this.numberOfStackItems > 0) { 350 this.stackItems[this.numberOfStackItems - 1].tag = VerificationTypeInfo.ITEM_OBJECT; 351 } 352 } 353 public void removeLocals(int resolvedPosition) { 354 if (this.locals == null || resolvedPosition < 0) return; 355 if (resolvedPosition < this.locals.length) { 356 this.locals[resolvedPosition] = null; 357 } 358 } 359 public void putLocal(int resolvedPosition, VerificationTypeInfo info) { 360 if (this.locals == null) { 361 this.locals = new VerificationTypeInfo[resolvedPosition + 1]; 362 this.locals[resolvedPosition] = info; 363 } else { 364 final int length = this.locals.length; 365 if (resolvedPosition >= length) { 366 System.arraycopy(this.locals, 0, this.locals = new VerificationTypeInfo[resolvedPosition + 1], 0, length); 367 } 368 this.locals[resolvedPosition] = info; 369 } 370 } 371 public void replaceWithElementType() { 372 VerificationTypeInfo info = this.stackItems[this.numberOfStackItems - 1]; 373 try { 374 VerificationTypeInfo info2 = (VerificationTypeInfo) info.clone(); 375 info2.replaceWithElementType(); 376 this.stackItems[this.numberOfStackItems - 1] = info2; 377 } catch (CloneNotSupportedException e) { 378 } 380 } 381 public int getIndexOfDifferentLocals(int differentLocalsCount) { 382 for (int i = this.locals.length - 1; i >= 0; i--) { 383 VerificationTypeInfo currentLocal = this.locals[i]; 384 if (currentLocal == null) { 385 continue; 387 } else { 388 differentLocalsCount--; 389 } 390 if (differentLocalsCount == 0) { 391 return i; 392 } 393 } 394 return 0; 395 } 396 private boolean equals(VerificationTypeInfo info, VerificationTypeInfo info2) { 397 if (info == null) { 398 return info2 == null; 399 } 400 if (info2 == null) return false; 401 return info.equals(info2); 402 } 403 public void mergeLocals(StackMapFrame currentFrame) { 404 int currentFrameLocalsLength = currentFrame.locals == null ? 0 : currentFrame.locals.length; 405 int localsLength = this.locals == null ? 0 : this.locals.length; 406 for (int i = 0, max = Math.min(currentFrameLocalsLength, localsLength); i < max; i++) { 407 VerificationTypeInfo info = this.locals[i]; 408 VerificationTypeInfo info2 = currentFrame.locals[i]; 409 if (info == null) { 410 if (info2 != null) { 411 this.locals[i] = info2; 412 } 413 } else if (info2 == null) { 414 this.locals[i] = null; 415 } else { 416 int tag1 = info.tag; 417 int tag2 = info2.tag; 418 if (tag1 != tag2) { 419 this.locals[i] = null; 420 } 421 } 422 } 423 } 424 } 425 | Popular Tags |