1 15 16 package javassist.bytecode; 17 18 import javassist.CtClass; 19 import javassist.CtPrimitiveType; 20 21 42 public class Bytecode implements Opcode { 43 47 public static final CtClass THIS = ConstPool.THIS; 48 49 static final int bufsize = 64; 50 ConstPool constPool; 51 int maxStack, maxLocals; 52 ExceptionTable tryblocks; 53 Bytecode next; 54 byte[] buffer; 55 int num; 56 57 private int stackDepth; 58 59 72 public Bytecode(ConstPool cp, int stacksize, int localvars) { 73 this(); 74 constPool = cp; 75 maxStack = stacksize; 76 maxLocals = localvars; 77 tryblocks = new ExceptionTable(cp); 78 stackDepth = 0; 79 } 80 81 90 public Bytecode(ConstPool cp) { 91 this(cp, 0, 0); 92 } 93 94 96 private Bytecode() { 97 buffer = new byte[bufsize]; 98 num = 0; 99 next = null; 100 } 101 102 105 public ConstPool getConstPool() { return constPool; } 106 107 110 public ExceptionTable getExceptionTable() { return tryblocks; } 111 112 115 public CodeAttribute toCodeAttribute() { 116 return new CodeAttribute(constPool, maxStack, maxLocals, 117 get(), tryblocks); 118 } 119 120 123 public int length() { 124 int len = 0; 125 Bytecode b = this; 126 while (b != null) { 127 len += b.num; 128 b = b.next; 129 } 130 131 return len; 132 } 133 134 private void copy(byte[] dest, int index) { 135 Bytecode b = this; 136 while (b != null) { 137 System.arraycopy(b.buffer, 0, dest, index, b.num); 138 index += b.num; 139 b = b.next; 140 } 141 } 142 143 146 public byte[] get() { 147 byte[] b = new byte[length()]; 148 copy(b, 0); 149 return b; 150 } 151 152 155 public int getMaxStack() { return maxStack; } 156 157 171 public void setMaxStack(int size) { 172 maxStack = size; 173 } 174 175 178 public int getMaxLocals() { return maxLocals; } 179 180 183 public void setMaxLocals(int size) { 184 maxLocals = size; 185 } 186 187 200 public void setMaxLocals(boolean isStatic, CtClass[] params, 201 int locals) { 202 if (!isStatic) 203 ++locals; 204 205 if (params != null) { 206 CtClass doubleType = CtClass.doubleType; 207 CtClass longType = CtClass.longType; 208 int n = params.length; 209 for (int i = 0; i < n; ++i) { 210 CtClass type = params[i]; 211 if (type == doubleType || type == longType) 212 locals += 2; 213 else 214 ++locals; 215 } 216 } 217 218 maxLocals = locals; 219 } 220 221 224 public void incMaxLocals(int diff) { 225 maxLocals += diff; 226 } 227 228 231 public void addExceptionHandler(int start, int end, 232 int handler, CtClass type) { 233 addExceptionHandler(start, end, handler, 234 constPool.addClassInfo(type)); 235 } 236 237 242 public void addExceptionHandler(int start, int end, 243 int handler, String type) { 244 addExceptionHandler(start, end, handler, 245 constPool.addClassInfo(type)); 246 } 247 248 251 public void addExceptionHandler(int start, int end, 252 int handler, int type) { 253 tryblocks.add(start, end, handler, type); 254 } 255 256 260 public int currentPc() { 261 int n = 0; 262 Bytecode b = this; 263 while (b != null) { 264 n += b.num; 265 b = b.next; 266 } 267 268 return n; 269 } 270 271 277 public int read(int offset) { 278 if (offset < 0) 279 return Opcode.NOP; 280 else if (offset < num) 281 return buffer[offset]; 282 else 283 try { 284 return next.read(offset - num); 285 } 286 catch (NullPointerException e) { 287 throw new ArrayIndexOutOfBoundsException (offset); 288 } 289 } 290 291 295 public int read16bit(int offset) { 296 int v1 = read(offset); 297 int v2 = read(offset + 1); 298 return (v1 << 8) + (v2 & 0xff); 299 } 300 301 305 public int read32bit(int offset) { 306 int v1 = read16bit(offset); 307 int v2 = read16bit(offset + 2); 308 return (v1 << 16) + (v2 & 0xffff); 309 } 310 311 317 public void write(int offset, int value) { 318 if (offset < num) 319 buffer[offset] = (byte)value; 320 else 321 try { 322 next.write(offset - num, value); 323 } 324 catch (NullPointerException e) { 325 throw new ArrayIndexOutOfBoundsException (offset); 326 } 327 } 328 329 333 public void write16bit(int offset, int value) { 334 write(offset, value >> 8); 335 write(offset + 1, value); 336 } 337 338 342 public void write32bit(int offset, int value) { 343 write16bit(offset, value >> 16); 344 write16bit(offset + 2, value); 345 } 346 347 350 public void add(int code) { 351 if (num < bufsize) 352 buffer[num++] = (byte)code; 353 else { 354 if (next == null) 355 next = new Bytecode(); 356 357 next.add(code); 358 } 359 } 360 361 364 public void add32bit(int value) { 365 add(value >> 24); 366 add(value >> 16); 367 add(value >> 8); 368 add(value); 369 } 370 371 376 public void addGap(int length) { 377 if (num < bufsize) { 378 num += length; 379 if (num <= bufsize) 380 return; 381 else { 382 length = num - bufsize; 383 num = bufsize; 384 } 385 } 386 387 if (next == null) 388 next = new Bytecode(); 389 390 next.addGap(length); 391 } 392 393 404 public void addOpcode(int code) { 405 add(code); 406 growStack(STACK_GROW[code]); 407 } 408 409 416 public void growStack(int diff) { 417 setStackDepth(stackDepth + diff); 418 } 419 420 423 public int getStackDepth() { return stackDepth; } 424 425 432 public void setStackDepth(int depth) { 433 stackDepth = depth; 434 if (stackDepth > maxStack) 435 maxStack = stackDepth; 436 } 437 438 442 public void addIndex(int index) { 443 add(index >> 8); 444 add(index); 445 } 446 447 452 public void addAload(int n) { 453 if (n < 4) 454 addOpcode(42 + n); else if (n < 0x100) { 456 addOpcode(ALOAD); add(n); 458 } 459 else { 460 addOpcode(WIDE); 461 addOpcode(ALOAD); 462 addIndex(n); 463 } 464 } 465 466 471 public void addAstore(int n) { 472 if (n < 4) 473 addOpcode(75 + n); else if (n < 0x100) { 475 addOpcode(ASTORE); add(n); 477 } 478 else { 479 addOpcode(WIDE); 480 addOpcode(ASTORE); 481 addIndex(n); 482 } 483 } 484 485 490 public void addIconst(int n) { 491 if (n < 6 && -2 < n) 492 addOpcode(3 + n); else if (n <= 127 && -128 <= n) { 494 addOpcode(16); add(n); 496 } 497 else if (n <= 32767 && -32768 <= n) { 498 addOpcode(17); add(n >> 8); 500 add(n); 501 } 502 else 503 addLdc(constPool.addIntegerInfo(n)); 504 } 505 506 512 public void addConstZero(CtClass type) { 513 if (type.isPrimitive()) { 514 if (type == CtClass.longType) 515 addOpcode(LCONST_0); 516 else if (type == CtClass.floatType) 517 addOpcode(FCONST_0); 518 else if (type == CtClass.doubleType) 519 addOpcode(DCONST_0); 520 else if (type == CtClass.voidType) 521 throw new RuntimeException ("void type?"); 522 else 523 addOpcode(ICONST_0); 524 } 525 else 526 addOpcode(ACONST_NULL); 527 } 528 529 534 public void addIload(int n) { 535 if (n < 4) 536 addOpcode(26 + n); else if (n < 0x100) { 538 addOpcode(ILOAD); add(n); 540 } 541 else { 542 addOpcode(WIDE); 543 addOpcode(ILOAD); 544 addIndex(n); 545 } 546 } 547 548 553 public void addIstore(int n) { 554 if (n < 4) 555 addOpcode(59 + n); else if (n < 0x100) { 557 addOpcode(ISTORE); add(n); 559 } 560 else { 561 addOpcode(WIDE); 562 addOpcode(ISTORE); 563 addIndex(n); 564 } 565 } 566 567 572 public void addLconst(long n) { 573 if (n == 0 || n == 1) 574 addOpcode(9 + (int)n); else 576 addLdc2w(n); 577 } 578 579 584 public void addLload(int n) { 585 if (n < 4) 586 addOpcode(30 + n); else if (n < 0x100) { 588 addOpcode(LLOAD); add(n); 590 } 591 else { 592 addOpcode(WIDE); 593 addOpcode(LLOAD); 594 addIndex(n); 595 } 596 } 597 598 603 public void addLstore(int n) { 604 if (n < 4) 605 addOpcode(63 + n); else if (n < 0x100) { 607 addOpcode(LSTORE); add(n); 609 } 610 else { 611 addOpcode(WIDE); 612 addOpcode(LSTORE); 613 addIndex(n); 614 } 615 } 616 617 622 public void addDconst(double d) { 623 if (d == 0.0 || d == 1.0) 624 addOpcode(14 + (int)d); else 626 addLdc2w(d); 627 } 628 629 634 public void addDload(int n) { 635 if (n < 4) 636 addOpcode(38 + n); else if (n < 0x100) { 638 addOpcode(DLOAD); add(n); 640 } 641 else { 642 addOpcode(WIDE); 643 addOpcode(DLOAD); 644 addIndex(n); 645 } 646 } 647 648 653 public void addDstore(int n) { 654 if (n < 4) 655 addOpcode(71 + n); else if (n < 0x100) { 657 addOpcode(DSTORE); add(n); 659 } 660 else { 661 addOpcode(WIDE); 662 addOpcode(DSTORE); 663 addIndex(n); 664 } 665 } 666 667 672 public void addFconst(float f) { 673 if (f == 0.0f || f == 1.0f || f == 2.0f) 674 addOpcode(11 + (int)f); else 676 addLdc(constPool.addFloatInfo(f)); 677 } 678 679 684 public void addFload(int n) { 685 if (n < 4) 686 addOpcode(34 + n); else if (n < 0x100) { 688 addOpcode(FLOAD); add(n); 690 } 691 else { 692 addOpcode(WIDE); 693 addOpcode(FLOAD); 694 addIndex(n); 695 } 696 } 697 698 703 public void addFstore(int n) { 704 if (n < 4) 705 addOpcode(67 + n); else if (n < 0x100) { 707 addOpcode(FSTORE); add(n); 709 } 710 else { 711 addOpcode(WIDE); 712 addOpcode(FSTORE); 713 addIndex(n); 714 } 715 } 716 717 725 public int addLoad(int n, CtClass type) { 726 if (type.isPrimitive()) { 727 if (type == CtClass.booleanType || type == CtClass.charType 728 || type == CtClass.byteType || type == CtClass.shortType 729 || type == CtClass.intType) 730 addIload(n); 731 else if (type == CtClass.longType) { 732 addLload(n); 733 return 2; 734 } 735 else if(type == CtClass.floatType) 736 addFload(n); 737 else if(type == CtClass.doubleType) { 738 addDload(n); 739 return 2; 740 } 741 else 742 throw new RuntimeException ("void type?"); 743 } 744 else 745 addAload(n); 746 747 return 1; 748 } 749 750 758 public int addStore(int n, CtClass type) { 759 if (type.isPrimitive()) { 760 if (type == CtClass.booleanType || type == CtClass.charType 761 || type == CtClass.byteType || type == CtClass.shortType 762 || type == CtClass.intType) 763 addIstore(n); 764 else if (type == CtClass.longType) { 765 addLstore(n); 766 return 2; 767 } 768 else if (type == CtClass.floatType) 769 addFstore(n); 770 else if (type == CtClass.doubleType) { 771 addDstore(n); 772 return 2; 773 } 774 else 775 throw new RuntimeException ("void type?"); 776 } 777 else 778 addAstore(n); 779 780 return 1; 781 } 782 783 790 public int addLoadParameters(CtClass[] params, int offset) { 791 int stacksize = 0; 792 if (params != null) { 793 int n = params.length; 794 for (int i = 0; i < n; ++i) 795 stacksize += addLoad(stacksize + offset, params[i]); 796 } 797 798 return stacksize; 799 } 800 801 806 public void addCheckcast(CtClass c) { 807 addOpcode(CHECKCAST); 808 addIndex(constPool.addClassInfo(c)); 809 } 810 811 816 public void addCheckcast(String classname) { 817 addOpcode(CHECKCAST); 818 addIndex(constPool.addClassInfo(classname)); 819 } 820 821 826 public void addInstanceof(String classname) { 827 addOpcode(INSTANCEOF); 828 addIndex(constPool.addClassInfo(classname)); 829 } 830 831 840 public void addGetfield(CtClass c, String name, String type) { 841 add(GETFIELD); 842 int ci = constPool.addClassInfo(c); 843 addIndex(constPool.addFieldrefInfo(ci, name, type)); 844 growStack(Descriptor.dataSize(type) - 1); 845 } 846 847 856 public void addGetstatic(CtClass c, String name, String type) { 857 add(GETSTATIC); 858 int ci = constPool.addClassInfo(c); 859 addIndex(constPool.addFieldrefInfo(ci, name, type)); 860 growStack(Descriptor.dataSize(type)); 861 } 862 863 872 public void addGetstatic(String c, String name, String type) { 873 add(GETSTATIC); 874 int ci = constPool.addClassInfo(c); 875 addIndex(constPool.addFieldrefInfo(ci, name, type)); 876 growStack(Descriptor.dataSize(type)); 877 } 878 879 887 public void addInvokespecial(CtClass clazz, String name, 888 CtClass returnType, CtClass[] paramTypes) { 889 String desc = Descriptor.ofMethod(returnType, paramTypes); 890 addInvokespecial(clazz, name, desc); 891 } 892 893 903 public void addInvokespecial(CtClass clazz, String name, String desc) { 904 addInvokespecial(constPool.addClassInfo(clazz), name, desc); 905 } 906 907 917 public void addInvokespecial(String clazz, String name, String desc) { 918 addInvokespecial(constPool.addClassInfo(clazz), name, desc); 919 } 920 921 932 public void addInvokespecial(int clazz, String name, String desc) { 933 add(INVOKESPECIAL); 934 addIndex(constPool.addMethodrefInfo(clazz, name, desc)); 935 growStack(Descriptor.dataSize(desc) - 1); 936 } 937 938 946 public void addInvokestatic(CtClass clazz, String name, 947 CtClass returnType, CtClass[] paramTypes) { 948 String desc = Descriptor.ofMethod(returnType, paramTypes); 949 addInvokestatic(clazz, name, desc); 950 } 951 952 961 public void addInvokestatic(CtClass clazz, String name, String desc) { 962 addInvokestatic(constPool.addClassInfo(clazz), name, desc); 963 } 964 965 974 public void addInvokestatic(String classname, String name, String desc) { 975 addInvokestatic(constPool.addClassInfo(classname), name, desc); 976 } 977 978 988 public void addInvokestatic(int clazz, String name, String desc) { 989 add(INVOKESTATIC); 990 addIndex(constPool.addMethodrefInfo(clazz, name, desc)); 991 growStack(Descriptor.dataSize(desc)); 992 } 993 994 1006 public void addInvokevirtual(CtClass clazz, String name, 1007 CtClass returnType, CtClass[] paramTypes) { 1008 String desc = Descriptor.ofMethod(returnType, paramTypes); 1009 addInvokevirtual(clazz, name, desc); 1010 } 1011 1012 1025 public void addInvokevirtual(CtClass clazz, String name, String desc) { 1026 addInvokevirtual(constPool.addClassInfo(clazz), name, desc); 1027 } 1028 1029 1042 public void addInvokevirtual(String classname, String name, String desc) { 1043 addInvokevirtual(constPool.addClassInfo(classname), name, desc); 1044 } 1045 1046 1060 public void addInvokevirtual(int clazz, String name, String desc) { 1061 add(INVOKEVIRTUAL); 1062 addIndex(constPool.addMethodrefInfo(clazz, name, desc)); 1063 growStack(Descriptor.dataSize(desc) - 1); 1064 } 1065 1066 1075 public void addInvokeinterface(CtClass clazz, String name, 1076 CtClass returnType, CtClass[] paramTypes, 1077 int count) { 1078 String desc = Descriptor.ofMethod(returnType, paramTypes); 1079 addInvokeinterface(clazz, name, desc, count); 1080 } 1081 1082 1092 public void addInvokeinterface(CtClass clazz, String name, 1093 String desc, int count) { 1094 addInvokeinterface(constPool.addClassInfo(clazz), name, desc, 1095 count); 1096 } 1097 1098 1108 public void addInvokeinterface(String classname, String name, 1109 String desc, int count) { 1110 addInvokeinterface(constPool.addClassInfo(classname), name, desc, 1111 count); 1112 } 1113 1114 1125 public void addInvokeinterface(int clazz, String name, 1126 String desc, int count) { 1127 add(INVOKEINTERFACE); 1128 addIndex(constPool.addInterfaceMethodrefInfo(clazz, name, desc)); 1129 add(count); 1130 add(0); 1131 growStack(Descriptor.dataSize(desc) - 1); 1132 } 1133 1134 1140 public void addLdc(String s) { 1141 addLdc(constPool.addStringInfo(s)); 1142 } 1143 1144 1149 public void addLdc(int i) { 1150 if (i > 0xFF) { 1151 addOpcode(LDC_W); 1152 addIndex(i); 1153 } 1154 else { 1155 addOpcode(LDC); 1156 add(i); 1157 } 1158 } 1159 1160 1163 public void addLdc2w(long l) { 1164 addOpcode(LDC2_W); 1165 addIndex(constPool.addLongInfo(l)); 1166 } 1167 1168 1171 public void addLdc2w(double d) { 1172 addOpcode(LDC2_W); 1173 addIndex(constPool.addDoubleInfo(d)); 1174 } 1175 1176 1181 public void addNew(CtClass clazz) { 1182 addOpcode(NEW); 1183 addIndex(constPool.addClassInfo(clazz)); 1184 } 1185 1186 1191 public void addNew(String classname) { 1192 addOpcode(NEW); 1193 addIndex(constPool.addClassInfo(classname)); 1194 } 1195 1196 1201 public void addAnewarray(String classname) { 1202 addOpcode(ANEWARRAY); 1203 addIndex(constPool.addClassInfo(classname)); 1204 } 1205 1206 1212 public void addAnewarray(CtClass clazz, int length) { 1213 addIconst(length); 1214 addOpcode(ANEWARRAY); 1215 addIndex(constPool.addClassInfo(clazz)); 1216 } 1217 1218 1224 public void addNewarray(int atype, int length) { 1225 addIconst(length); 1226 addOpcode(NEWARRAY); 1227 add(atype); 1228 } 1229 1230 1237 public int addMultiNewarray(CtClass clazz, int[] dimensions) { 1238 int len = dimensions.length; 1239 for (int i = 0; i < len; ++i) 1240 addIconst(dimensions[i]); 1241 1242 growStack(len); 1243 return addMultiNewarray(clazz, len); 1244 } 1245 1246 1254 public int addMultiNewarray(CtClass clazz, int dim) { 1255 add(MULTIANEWARRAY); 1256 addIndex(constPool.addClassInfo(clazz)); 1257 add(dim); 1258 growStack(1 - dim); 1259 return dim; 1260 } 1261 1262 1269 public int addMultiNewarray(String desc, int dim) { 1270 add(MULTIANEWARRAY); 1271 addIndex(constPool.addClassInfo(desc)); 1272 add(dim); 1273 growStack(1 - dim); 1274 return dim; 1275 } 1276 1277 1284 public void addPutfield(CtClass c, String name, String desc) { 1285 add(PUTFIELD); 1286 int ci = constPool.addClassInfo(c); 1287 addIndex(constPool.addFieldrefInfo(ci, name, desc)); 1288 growStack(-1 - Descriptor.dataSize(desc)); 1289 } 1290 1291 1298 public void addPutstatic(CtClass c, String name, String desc) { 1299 add(PUTSTATIC); 1300 int ci = constPool.addClassInfo(c); 1301 addIndex(constPool.addFieldrefInfo(ci, name, desc)); 1302 growStack(-Descriptor.dataSize(desc)); 1303 } 1304 1305 1310 public void addReturn(CtClass type) { 1311 if (type == null) 1312 addOpcode(RETURN); 1313 else if (type.isPrimitive()) { 1314 CtPrimitiveType ptype = (CtPrimitiveType)type; 1315 addOpcode(ptype.getReturnOp()); 1316 } 1317 else 1318 addOpcode(ARETURN); 1319 } 1320 1321 1326 public void addRet(int var) { 1327 if (var < 0x100) { 1328 addOpcode(RET); 1329 add(var); 1330 } 1331 else { 1332 addOpcode(WIDE); 1333 addOpcode(RET); 1334 addIndex(var); 1335 } 1336 } 1337 1338 1344 public void addPrintln(String message) { 1345 addGetstatic("java.lang.System", "err", "Ljava/io/PrintStream;"); 1346 addLdc(message); 1347 addInvokevirtual("java.io.PrintStream", 1348 "println", "(Ljava/lang/String;)V"); 1349 } 1350} 1351 | Popular Tags |