Package javassist.bytecode.stackmap

Source Code of javassist.bytecode.stackmap.MapMaker

/*     */ package javassist.bytecode.stackmap;
/*     */
/*     */ import javassist.ClassPool;
/*     */ import javassist.bytecode.BadBytecode;
/*     */ import javassist.bytecode.CodeAttribute;
/*     */ import javassist.bytecode.ConstPool;
/*     */ import javassist.bytecode.MethodInfo;
/*     */ import javassist.bytecode.StackMap;
/*     */ import javassist.bytecode.StackMap.Writer;
/*     */ import javassist.bytecode.StackMapTable;
/*     */ import javassist.bytecode.StackMapTable.Writer;
/*     */
/*     */ public class MapMaker extends Tracer
/*     */ {
/*     */   public static StackMapTable make(ClassPool classes, MethodInfo minfo)
/*     */     throws BadBytecode
/*     */   {
/*  87 */     CodeAttribute ca = minfo.getCodeAttribute();
/*  88 */     if (ca == null) {
/*  89 */       return null;
/*     */     }
/*  91 */     TypedBlock[] blocks = TypedBlock.makeBlocks(minfo, ca, true);
/*  92 */     if (blocks == null) {
/*  93 */       return null;
/*     */     }
/*  95 */     MapMaker mm = new MapMaker(classes, minfo, ca);
/*  96 */     mm.make(blocks, ca.getCode());
/*  97 */     return mm.toStackMap(blocks);
/*     */   }
/*     */
/*     */   public static StackMap make2(ClassPool classes, MethodInfo minfo)
/*     */     throws BadBytecode
/*     */   {
/* 108 */     CodeAttribute ca = minfo.getCodeAttribute();
/* 109 */     if (ca == null) {
/* 110 */       return null;
/*     */     }
/* 112 */     TypedBlock[] blocks = TypedBlock.makeBlocks(minfo, ca, true);
/* 113 */     if (blocks == null) {
/* 114 */       return null;
/*     */     }
/* 116 */     MapMaker mm = new MapMaker(classes, minfo, ca);
/* 117 */     mm.make(blocks, ca.getCode());
/* 118 */     return mm.toStackMap2(minfo.getConstPool(), blocks);
/*     */   }
/*     */
/*     */   public MapMaker(ClassPool classes, MethodInfo minfo, CodeAttribute ca) {
/* 122 */     super(classes, minfo.getConstPool(), ca.getMaxStack(), ca.getMaxLocals(), TypedBlock.getRetType(minfo.getDescriptor()));
/*     */   }
/*     */
/*     */   protected MapMaker(MapMaker old, boolean copyStack)
/*     */   {
/* 128 */     super(old, copyStack);
/*     */   }
/*     */
/*     */   void make(TypedBlock[] blocks, byte[] code)
/*     */     throws BadBytecode
/*     */   {
/* 137 */     TypedBlock first = blocks[0];
/* 138 */     fixParamTypes(first);
/* 139 */     TypeData[] srcTypes = first.localsTypes;
/* 140 */     copyFrom(srcTypes.length, srcTypes, this.localsTypes);
/* 141 */     make(code, first);
/*     */
/* 143 */     int n = blocks.length;
/* 144 */     for (int i = 0; i < n; i++)
/* 145 */       evalExpected(blocks[i]);
/*     */   }
/*     */
/*     */   private void fixParamTypes(TypedBlock first)
/*     */     throws BadBytecode
/*     */   {
/* 155 */     TypeData[] types = first.localsTypes;
/* 156 */     int n = types.length;
/* 157 */     for (int i = 0; i < n; i++) {
/* 158 */       TypeData t = types[i];
/* 159 */       if (!(t instanceof TypeData.ClassName))
/*     */       {
/*     */         continue;
/*     */       }
/* 163 */       TypeData.setType(t, t.getName(), this.classPool);
/*     */     }
/*     */   }
/*     */
/*     */   private void make(byte[] code, TypedBlock tb)
/*     */     throws BadBytecode
/*     */   {
/* 173 */     BasicBlock.Catch handlers = tb.toCatch;
/* 174 */     while (handlers != null) {
/* 175 */       traceException(code, handlers);
/* 176 */       handlers = handlers.next;
/*     */     }
/*     */
/* 179 */     int pos = tb.position;
/* 180 */     int end = pos + tb.length;
/* 181 */     while (pos < end) {
/* 182 */       pos += doOpcode(pos, code);
/*     */     }
/* 184 */     if (tb.exit != null)
/* 185 */       for (int i = 0; i < tb.exit.length; i++) {
/* 186 */         TypedBlock e = (TypedBlock)tb.exit[i];
/* 187 */         if (e.alreadySet()) {
/* 188 */           mergeMap(e, true);
/*     */         } else {
/* 190 */           recordStackMap(e);
/* 191 */           MapMaker maker = new MapMaker(this, true);
/* 192 */           maker.make(code, e);
/*     */         }
/*     */       }
/*     */   }
/*     */
/*     */   private void traceException(byte[] code, BasicBlock.Catch handler)
/*     */     throws BadBytecode
/*     */   {
/* 201 */     TypedBlock tb = (TypedBlock)handler.body;
/* 202 */     if (tb.alreadySet()) {
/* 203 */       mergeMap(tb, false);
/*     */     } else {
/* 205 */       recordStackMap(tb, handler.typeIndex);
/* 206 */       MapMaker maker = new MapMaker(this, false);
/*     */
/* 211 */       maker.stackTypes[0] = tb.stackTypes[0].getSelf();
/* 212 */       maker.stackTop = 1;
/* 213 */       maker.make(code, tb);
/*     */     }
/*     */   }
/*     */
/*     */   private void mergeMap(TypedBlock dest, boolean mergeStack) {
/* 218 */     boolean[] inputs = dest.inputs;
/* 219 */     int n = inputs.length;
/* 220 */     for (int i = 0; i < n; i++) {
/* 221 */       if (inputs[i] != 0)
/* 222 */         merge(this.localsTypes[i], dest.localsTypes[i]);
/*     */     }
/* 224 */     if (mergeStack) {
/* 225 */       n = this.stackTop;
/* 226 */       for (int i = 0; i < n; i++)
/* 227 */         merge(this.stackTypes[i], dest.stackTypes[i]);
/*     */     }
/*     */   }
/*     */
/*     */   private void merge(TypeData td, TypeData target) {
/* 232 */     boolean tdIsObj = false;
/* 233 */     boolean targetIsObj = false;
/*     */
/* 235 */     if ((td != TOP) && (td.isObjectType())) {
/* 236 */       tdIsObj = true;
/*     */     }
/* 238 */     if ((target != TOP) && (target.isObjectType())) {
/* 239 */       targetIsObj = true;
/*     */     }
/* 241 */     if ((tdIsObj) && (targetIsObj))
/* 242 */       target.merge(td);
/*     */   }
/*     */
/*     */   private void recordStackMap(TypedBlock target)
/*     */     throws BadBytecode
/*     */   {
/* 248 */     TypeData[] tStackTypes = new TypeData[this.stackTypes.length];
/* 249 */     int st = this.stackTop;
/* 250 */     copyFrom(st, this.stackTypes, tStackTypes);
/* 251 */     recordStackMap0(target, st, tStackTypes);
/*     */   }
/*     */
/*     */   private void recordStackMap(TypedBlock target, int exceptionType)
/*     */     throws BadBytecode
/*     */   {
/*     */     String type;
/*     */     String type;
/* 258 */     if (exceptionType == 0)
/* 259 */       type = "java.lang.Throwable";
/*     */     else {
/* 261 */       type = this.cpool.getClassInfo(exceptionType);
/*     */     }
/* 263 */     TypeData[] tStackTypes = new TypeData[this.stackTypes.length];
/* 264 */     tStackTypes[0] = new TypeData.ClassName(type);
/*     */
/* 266 */     recordStackMap0(target, 1, tStackTypes);
/*     */   }
/*     */
/*     */   private void recordStackMap0(TypedBlock target, int st, TypeData[] tStackTypes)
/*     */     throws BadBytecode
/*     */   {
/* 272 */     int n = this.localsTypes.length;
/* 273 */     TypeData[] tLocalsTypes = new TypeData[n];
/* 274 */     int k = copyFrom(n, this.localsTypes, tLocalsTypes);
/*     */
/* 276 */     boolean[] inputs = target.inputs;
/* 277 */     for (int i = 0; i < n; i++) {
/* 278 */       if (inputs[i] == 0)
/* 279 */         tLocalsTypes[i] = TOP;
/*     */     }
/* 281 */     target.setStackMap(st, tStackTypes, k, tLocalsTypes);
/*     */   }
/*     */
/*     */   void evalExpected(TypedBlock target)
/*     */     throws BadBytecode
/*     */   {
/* 287 */     ClassPool cp = this.classPool;
/* 288 */     evalExpected(cp, target.stackTop, target.stackTypes);
/* 289 */     TypeData[] types = target.localsTypes;
/* 290 */     if (types != null)
/* 291 */       evalExpected(cp, types.length, types);
/*     */   }
/*     */
/*     */   private static void evalExpected(ClassPool cp, int n, TypeData[] types)
/*     */     throws BadBytecode
/*     */   {
/* 297 */     for (int i = 0; i < n; i++) {
/* 298 */       TypeData td = types[i];
/* 299 */       if (td != null)
/* 300 */         td.evalExpectedType(cp);
/*     */     }
/*     */   }
/*     */
/*     */   public StackMapTable toStackMap(TypedBlock[] blocks)
/*     */   {
/* 307 */     StackMapTable.Writer writer = new StackMapTable.Writer(32);
/* 308 */     int n = blocks.length;
/* 309 */     TypedBlock prev = blocks[0];
/* 310 */     int offsetDelta = prev.length;
/* 311 */     if (prev.incoming > 0) {
/* 312 */       writer.sameFrame(0);
/* 313 */       offsetDelta--;
/*     */     }
/*     */
/* 316 */     for (int i = 1; i < n; i++) {
/* 317 */       TypedBlock bb = blocks[i];
/* 318 */       if (isTarget(bb, blocks[(i - 1)])) {
/* 319 */         bb.resetNumLocals();
/* 320 */         int diffL = stackMapDiff(prev.numLocals, prev.localsTypes, bb.numLocals, bb.localsTypes);
/*     */
/* 322 */         toStackMapBody(writer, bb, diffL, offsetDelta, prev);
/* 323 */         offsetDelta = bb.length - 1;
/* 324 */         prev = bb;
/*     */       }
/*     */       else {
/* 327 */         offsetDelta += bb.length;
/*     */       }
/*     */     }
/* 330 */     return writer.toStackMapTable(this.cpool);
/*     */   }
/*     */
/*     */   private boolean isTarget(TypedBlock cur, TypedBlock prev)
/*     */   {
/* 337 */     int in = cur.incoming;
/* 338 */     if (in > 1)
/* 339 */       return true;
/* 340 */     if (in < 1) {
/* 341 */       return false;
/*     */     }
/* 343 */     return prev.stop;
/*     */   }
/*     */
/*     */   private void toStackMapBody(StackMapTable.Writer writer, TypedBlock bb, int diffL, int offsetDelta, TypedBlock prev)
/*     */   {
/* 351 */     int stackTop = bb.stackTop;
/* 352 */     if (stackTop == 0) {
/* 353 */       if (diffL == 0) {
/* 354 */         writer.sameFrame(offsetDelta);
/* 355 */         return;
/*     */       }
/* 357 */       if ((0 > diffL) && (diffL >= -3)) {
/* 358 */         writer.chopFrame(offsetDelta, -diffL);
/* 359 */         return;
/*     */       }
/* 361 */       if ((0 < diffL) && (diffL <= 3)) {
/* 362 */         int[] data = new int[diffL];
/* 363 */         int[] tags = fillStackMap(bb.numLocals - prev.numLocals, prev.numLocals, data, bb.localsTypes);
/*     */
/* 366 */         writer.appendFrame(offsetDelta, tags, data);
/* 367 */         return;
/*     */       }
/*     */     } else {
/* 370 */       if ((stackTop == 1) && (diffL == 0)) {
/* 371 */         TypeData td = bb.stackTypes[0];
/* 372 */         if (td == TOP)
/* 373 */           writer.sameLocals(offsetDelta, 0, 0);
/*     */         else {
/* 375 */           writer.sameLocals(offsetDelta, td.getTypeTag(), td.getTypeData(this.cpool));
/*     */         }
/* 377 */         return;
/*     */       }
/* 379 */       if ((stackTop == 2) && (diffL == 0)) {
/* 380 */         TypeData td = bb.stackTypes[0];
/* 381 */         if ((td != TOP) && (td.is2WordType()))
/*     */         {
/* 383 */           writer.sameLocals(offsetDelta, td.getTypeTag(), td.getTypeData(this.cpool));
/*     */
/* 385 */           return;
/*     */         }
/*     */       }
/*     */     }
/* 389 */     int[] sdata = new int[stackTop];
/* 390 */     int[] stags = fillStackMap(stackTop, 0, sdata, bb.stackTypes);
/* 391 */     int[] ldata = new int[bb.numLocals];
/* 392 */     int[] ltags = fillStackMap(bb.numLocals, 0, ldata, bb.localsTypes);
/* 393 */     writer.fullFrame(offsetDelta, ltags, ldata, stags, sdata);
/*     */   }
/*     */
/*     */   private int[] fillStackMap(int num, int offset, int[] data, TypeData[] types) {
/* 397 */     int realNum = diffSize(types, offset, offset + num);
/* 398 */     ConstPool cp = this.cpool;
/* 399 */     int[] tags = new int[realNum];
/* 400 */     int j = 0;
/* 401 */     for (int i = 0; i < num; i++) {
/* 402 */       TypeData td = types[(offset + i)];
/* 403 */       if (td == TOP) {
/* 404 */         tags[j] = 0;
/* 405 */         data[j] = 0;
/*     */       }
/*     */       else {
/* 408 */         tags[j] = td.getTypeTag();
/* 409 */         data[j] = td.getTypeData(cp);
/* 410 */         if (td.is2WordType()) {
/* 411 */           i++;
/*     */         }
/*     */       }
/* 414 */       j++;
/*     */     }
/*     */
/* 417 */     return tags;
/*     */   }
/*     */
/*     */   private static int stackMapDiff(int oldTdLen, TypeData[] oldTd, int newTdLen, TypeData[] newTd)
/*     */   {
/* 423 */     int diff = newTdLen - oldTdLen;
/*     */     int len;
/*     */     int len;
/* 425 */     if (diff > 0)
/* 426 */       len = oldTdLen;
/*     */     else {
/* 428 */       len = newTdLen;
/*     */     }
/* 430 */     if (stackMapEq(oldTd, newTd, len)) {
/* 431 */       if (diff > 0) {
/* 432 */         return diffSize(newTd, len, newTdLen);
/*     */       }
/* 434 */       return -diffSize(oldTd, len, oldTdLen);
/*     */     }
/* 436 */     return -100;
/*     */   }
/*     */
/*     */   private static boolean stackMapEq(TypeData[] oldTd, TypeData[] newTd, int len) {
/* 440 */     for (int i = 0; i < len; i++) {
/* 441 */       TypeData td = oldTd[i];
/* 442 */       if (td == TOP) {
/* 443 */         if (newTd[i] != TOP) {
/* 444 */           return false;
/*     */         }
/*     */       }
/* 447 */       else if (!oldTd[i].equals(newTd[i])) {
/* 448 */         return false;
/*     */       }
/*     */     }
/* 451 */     return true;
/*     */   }
/*     */
/*     */   private static int diffSize(TypeData[] types, int offset, int len) {
/* 455 */     int num = 0;
/* 456 */     while (offset < len) {
/* 457 */       TypeData td = types[(offset++)];
/* 458 */       num++;
/* 459 */       if ((td != TOP) && (td.is2WordType())) {
/* 460 */         offset++;
/*     */       }
/*     */     }
/* 463 */     return num;
/*     */   }
/*     */
/*     */   public StackMap toStackMap2(ConstPool cp, TypedBlock[] blocks)
/*     */   {
/* 469 */     StackMap.Writer writer = new StackMap.Writer();
/* 470 */     int n = blocks.length;
/* 471 */     boolean[] effective = new boolean[n];
/* 472 */     TypedBlock prev = blocks[0];
/*     */
/* 475 */     effective[0] = (prev.incoming > 0 ? 1 : false);
/*     */
/* 477 */     int num = effective[0] != 0 ? 1 : 0;
/* 478 */     for (int i = 1; i < n; i++) {
/* 479 */       TypedBlock bb = blocks[i];
/* 480 */       if ((effective[i] = isTarget(bb, blocks[(i - 1)]))) {
/* 481 */         bb.resetNumLocals();
/* 482 */         prev = bb;
/* 483 */         num++;
/*     */       }
/*     */     }
/*     */
/* 487 */     if (num == 0) {
/* 488 */       return null;
/*     */     }
/* 490 */     writer.write16bit(num);
/* 491 */     for (int i = 0; i < n; i++) {
/* 492 */       if (effective[i] != 0)
/* 493 */         writeStackFrame(writer, cp, blocks[i].position, blocks[i]);
/*     */     }
/* 495 */     return writer.toStackMap(cp);
/*     */   }
/*     */
/*     */   private void writeStackFrame(StackMap.Writer writer, ConstPool cp, int offset, TypedBlock tb) {
/* 499 */     writer.write16bit(offset);
/* 500 */     writeVerifyTypeInfo(writer, cp, tb.localsTypes, tb.numLocals);
/* 501 */     writeVerifyTypeInfo(writer, cp, tb.stackTypes, tb.stackTop);
/*     */   }
/*     */
/*     */   private void writeVerifyTypeInfo(StackMap.Writer writer, ConstPool cp, TypeData[] types, int num) {
/* 505 */     int numDWord = 0;
/* 506 */     for (int i = 0; i < num; i++) {
/* 507 */       TypeData td = types[i];
/* 508 */       if ((td != null) && (td.is2WordType())) {
/* 509 */         numDWord++;
/* 510 */         i++;
/*     */       }
/*     */     }
/*     */
/* 514 */     writer.write16bit(num - numDWord);
/* 515 */     for (int i = 0; i < num; i++) {
/* 516 */       TypeData td = types[i];
/* 517 */       if (td == TOP) {
/* 518 */         writer.writeVerifyTypeInfo(0, 0);
/*     */       } else {
/* 520 */         writer.writeVerifyTypeInfo(td.getTypeTag(), td.getTypeData(cp));
/* 521 */         if (td.is2WordType())
/* 522 */           i++;
/*     */       }
/*     */     }
/*     */   }
/*     */ }

/* Location:           /home/mnovotny/projects/EMBEDDED_JBOSS_BETA3_COMMUNITY/embedded/output/lib/embedded-jboss/lib/thirdparty-all.jar
* Qualified Name:     javassist.bytecode.stackmap.MapMaker
* JD-Core Version:    0.6.0
*/
TOP

Related Classes of javassist.bytecode.stackmap.MapMaker

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.