1 52 53 package com.go.trove.classfile; 54 55 import java.lang.reflect.*; 56 57 65 public class CodeBuilder implements CodeBuffer, CodeAssembler { 66 private CodeAttr mCodeAttr; 67 private ClassFile mClassFile; 68 private ConstantPool mCp; 69 70 private InstructionList mInstructions = new InstructionList(); 71 72 private LocalVariable mThisReference; 73 private LocalVariable[] mParameters; 74 75 private boolean mSaveLineNumberInfo; 76 private boolean mSaveLocalVariableInfo; 77 78 82 public CodeBuilder(MethodInfo info) { 83 this(info, true, false); 84 } 85 86 99 public CodeBuilder(MethodInfo info, boolean saveLineNumberInfo, 100 boolean saveLocalVariableInfo) { 101 mCodeAttr = info.getCodeAttr(); 102 mClassFile = info.getClassFile(); 103 mCp = mClassFile.getConstantPool(); 104 105 mCodeAttr.setCodeBuffer(this); 106 107 mSaveLineNumberInfo = saveLineNumberInfo; 108 mSaveLocalVariableInfo = saveLocalVariableInfo; 109 110 113 LocalVariable localVar; 114 int varNum = 0; 115 116 if (!info.getAccessFlags().isStatic()) { 117 localVar = mInstructions.createLocalParameter 118 ("this", mClassFile.getType(), varNum++); 119 mThisReference = localVar; 120 121 if (saveLocalVariableInfo) { 122 mCodeAttr.localVariableUse(localVar); 123 } 124 } 125 126 TypeDescriptor[] paramTypes = 127 info.getMethodDescriptor().getParameterTypes(); 128 int paramSize = paramTypes.length; 129 130 mParameters = new LocalVariable[paramSize]; 131 132 for (int i = 0; i<paramTypes.length; i++) { 133 localVar = mInstructions.createLocalParameter 134 (null, paramTypes[i], varNum); 135 varNum += (localVar.isDoubleWord() ? 2 : 1); 136 mParameters[i] = localVar; 137 138 if (saveLocalVariableInfo) { 139 mCodeAttr.localVariableUse(localVar); 140 } 141 } 142 } 143 144 public int getMaxStackDepth() { 145 return mInstructions.getMaxStackDepth(); 146 } 147 148 public int getMaxLocals() { 149 return mInstructions.getMaxLocals(); 150 } 151 152 public byte[] getByteCodes() { 153 return mInstructions.getByteCodes(); 154 } 155 156 public ExceptionHandler[] getExceptionHandlers() { 157 return mInstructions.getExceptionHandlers(); 158 } 159 160 private void addCode(int stackAdjust, byte opcode) { 161 mInstructions.new CodeInstruction(stackAdjust, new byte[] {opcode}); 162 } 163 164 private void addCode(int stackAdjust, byte opcode, byte operand) { 165 mInstructions.new CodeInstruction 166 (stackAdjust, new byte[] {opcode, operand}); 167 } 168 169 private void addCode(int stackAdjust, byte opcode, short operand) { 170 mInstructions.new CodeInstruction 171 (stackAdjust, 172 new byte[] {opcode, (byte)(operand >> 8), (byte)operand}); 173 } 174 175 private void addCode(int stackAdjust, byte opcode, int operand) { 176 byte[] bytes = new byte[5]; 177 178 bytes[0] = opcode; 179 bytes[1] = (byte)(operand >> 24); 180 bytes[2] = (byte)(operand >> 16); 181 bytes[3] = (byte)(operand >> 8); 182 bytes[4] = (byte)operand; 183 184 mInstructions.new CodeInstruction(stackAdjust, bytes); 185 } 186 187 private void addCode(int stackAdjust, byte opcode, ConstantInfo info) { 188 mInstructions.new ConstantOperandInstruction 191 (stackAdjust, 192 new byte[] {opcode, (byte)0, (byte)0}, info); 193 } 194 195 203 public LocalVariable[] getParameters() { 204 return (LocalVariable[])mParameters.clone(); 205 } 206 207 216 public LocalVariable createLocalVariable(String name, 217 TypeDescriptor type) { 218 LocalVariable localVar = mInstructions.createLocalVariable(name, type); 219 220 if (mSaveLocalVariableInfo) { 221 mCodeAttr.localVariableUse(localVar); 222 } 223 224 return localVar; 225 } 226 227 240 public Label createLabel() { 241 return mInstructions.new LabelInstruction(); 242 } 243 244 255 public void exceptionHandler(Location startLocation, 256 Location endLocation, 257 String catchClassName) { 258 Location catchLocation = createLabel().setLocation(); 259 260 ConstantClassInfo catchClass; 261 if (catchClassName == null) { 262 catchClass = null; 263 } 264 else { 265 catchClass = ConstantClassInfo.make(mCp, catchClassName); 266 } 267 268 ExceptionHandler handler = 269 new ExceptionHandler(startLocation, endLocation, 270 catchLocation, catchClass); 271 272 mInstructions.addExceptionHandler(handler); 273 } 274 275 280 public void mapLineNumber(int lineNumber) { 281 if (mSaveLineNumberInfo) { 282 mCodeAttr.mapLineNumber(createLabel().setLocation(), lineNumber); 283 } 284 } 285 286 288 295 public void loadConstant(String value) { 296 if (value == null) { 297 addCode(1, Opcode.ACONST_NULL); 298 return; 299 } 300 301 int strlen = value.length(); 302 303 if (strlen <= (65535 / 3)) { 304 ConstantInfo info = ConstantStringInfo.make(mCp, value); 306 mInstructions.new LoadConstantInstruction(1, info); 307 return; 308 } 309 310 312 int utflen = 0; 313 314 for (int i=0; i<strlen; i++) { 315 int c = value.charAt(i); 316 if ((c >= 0x0001) && (c <= 0x007F)) { 317 utflen++; 318 } 319 else if (c > 0x07FF) { 320 utflen += 3; 321 } 322 else { 323 utflen += 2; 324 } 325 } 326 327 if (utflen <= 65535) { 328 ConstantInfo info = ConstantStringInfo.make(mCp, value); 329 mInstructions.new LoadConstantInstruction(1, info); 330 return; 331 } 332 333 335 TypeDescriptor stringBufferDesc = 336 new TypeDescriptor(StringBuffer .class); 337 338 TypeDescriptor intDesc = new TypeDescriptor(int.class); 339 TypeDescriptor stringDesc = new TypeDescriptor(String .class); 340 TypeDescriptor[] stringParam = new TypeDescriptor[] {stringDesc}; 341 342 newObject(stringBufferDesc); 343 dup(); 344 loadConstant(strlen); 345 invokeConstructor("java.lang.StringBuffer", 346 new TypeDescriptor[] {intDesc}); 347 348 int beginIndex; 349 int endIndex = 0; 350 351 while (endIndex < strlen) { 352 beginIndex = endIndex; 353 354 utflen = 0; 356 for (; endIndex < strlen; endIndex++) { 357 int c = value.charAt(endIndex); 358 int size; 359 if ((c >= 0x0001) && (c <= 0x007F)) { 360 size = 1; 361 } 362 else if (c > 0x07FF) { 363 size = 3; 364 } 365 else { 366 size = 2; 367 } 368 369 if ((utflen + size) > 65535) { 370 break; 371 } 372 else { 373 utflen += size; 374 } 375 } 376 377 String substr = value.substring(beginIndex, endIndex); 378 379 ConstantInfo info = ConstantStringInfo.make(mCp, substr); 380 mInstructions.new LoadConstantInstruction(1, info); 381 382 invokeVirtual("java.lang.StringBuffer", "append", 383 stringBufferDesc, stringParam); 384 } 385 386 invokeVirtual("java.lang.StringBuffer", "toString", 387 stringDesc, null); 388 } 389 390 393 public void loadConstant(boolean value) { 394 loadConstant(value?1:0); 395 } 396 397 401 public void loadConstant(int value) { 402 if (-1 <= value && value <= 5) { 403 byte op; 404 405 switch(value) { 406 case -1: 407 op = Opcode.ICONST_M1; 408 break; 409 case 0: 410 op = Opcode.ICONST_0; 411 break; 412 case 1: 413 op = Opcode.ICONST_1; 414 break; 415 case 2: 416 op = Opcode.ICONST_2; 417 break; 418 case 3: 419 op = Opcode.ICONST_3; 420 break; 421 case 4: 422 op = Opcode.ICONST_4; 423 break; 424 case 5: 425 op = Opcode.ICONST_5; 426 break; 427 default: 428 op = Opcode.NOP; 429 } 430 431 addCode(1, op); 432 } 433 else if (-128 <= value && value <= 127) { 434 addCode(1, Opcode.BIPUSH, (byte)value); 435 } 436 else if (-32768 <= value && value <= 32767) { 437 addCode(1, Opcode.SIPUSH, (short)value); 438 } 439 else { 440 ConstantInfo info = ConstantIntegerInfo.make(mCp, value); 441 mInstructions.new LoadConstantInstruction(1, info); 442 } 443 } 444 445 448 public void loadConstant(long value) { 449 if (value == 0) { 450 addCode(2, Opcode.LCONST_0); 451 } 452 else if (value == 1) { 453 addCode(2, Opcode.LCONST_1); 454 } 455 else { 456 ConstantInfo info = ConstantLongInfo.make(mCp, value); 457 mInstructions.new LoadConstantInstruction(2, info, true); 458 } 459 } 460 461 464 public void loadConstant(float value) { 465 if (value == 0) { 466 addCode(1, Opcode.FCONST_0); 467 } 468 else if (value == 1) { 469 addCode(1, Opcode.FCONST_1); 470 } 471 else if (value == 2) { 472 addCode(1, Opcode.FCONST_2); 473 } 474 else { 475 ConstantInfo info = ConstantFloatInfo.make(mCp, value); 476 mInstructions.new LoadConstantInstruction(1, info); 477 } 478 } 479 480 483 public void loadConstant(double value) { 484 if (value == 0) { 485 addCode(2, Opcode.DCONST_0); 486 } 487 else if (value == 1) { 488 addCode(2, Opcode.DCONST_1); 489 } 490 else { 491 ConstantInfo info = ConstantDoubleInfo.make(mCp, value); 492 mInstructions.new LoadConstantInstruction(2, info, true); 493 } 494 } 495 496 498 507 public void loadLocal(LocalVariable local) { 508 if (local == null) { 509 throw new NullPointerException ("No local variable specified"); 510 } 511 512 TypeDescriptor type = local.getType(); 513 Class clazz = type.getClassArg(); 514 515 int stackAdjust = 1; 516 517 if (clazz != null && type.getDimensions() == 0 && 518 (clazz == long.class || clazz == double.class)) { 519 520 stackAdjust++; 521 } 522 523 mInstructions.new LoadLocalInstruction(stackAdjust, local); 524 } 525 526 531 public void loadThis() { 532 if (mThisReference != null) { 533 loadLocal(mThisReference); 534 } 535 else { 536 throw new RuntimeException 537 ("Attempt to load \"this\" reference in a static method"); 538 } 539 } 540 541 543 552 public void storeLocal(LocalVariable local) { 553 if (local == null) { 554 throw new NullPointerException ("No local variable specified"); 555 } 556 557 TypeDescriptor type = local.getType(); 558 Class clazz = type.getClassArg(); 559 560 int stackAdjust = -1; 561 562 if (clazz != null && type.getDimensions() == 0 && 563 (clazz == long.class || clazz == double.class)) { 564 565 stackAdjust--; 566 } 567 568 mInstructions.new StoreLocalInstruction(stackAdjust, local); 569 } 570 571 573 585 public void loadFromArray(Class type) { 586 byte op; 587 int stackAdjust; 588 589 if (type == int.class) { 590 stackAdjust = -1; 591 op = Opcode.IALOAD; 592 } 593 else if (type == boolean.class || type == byte.class) { 594 stackAdjust = -1; 595 op = Opcode.BALOAD; 596 } 597 else if (type == short.class) { 598 stackAdjust = -1; 599 op = Opcode.SALOAD; 600 } 601 else if (type == char.class) { 602 stackAdjust = -1; 603 op = Opcode.CALOAD; 604 } 605 else if (type == long.class) { 606 stackAdjust = 0; 607 op = Opcode.LALOAD; 608 } 609 else if (type == float.class) { 610 stackAdjust = -1; 611 op = Opcode.FALOAD; 612 } 613 else if (type == double.class) { 614 stackAdjust = 0; 615 op = Opcode.DALOAD; 616 } 617 else { 618 stackAdjust = -1; 619 op = Opcode.AALOAD; 620 } 621 622 addCode(stackAdjust, op); 623 } 624 625 627 639 public void storeToArray(Class type) { 640 byte op; 641 int stackAdjust; 642 643 if (type == int.class) { 644 stackAdjust = -3; 645 op = Opcode.IASTORE; 646 } 647 else if (type == boolean.class || type == byte.class) { 648 stackAdjust = -3; 649 op = Opcode.BASTORE; 650 } 651 else if (type == short.class) { 652 stackAdjust = -3; 653 op = Opcode.SASTORE; 654 } 655 else if (type == char.class) { 656 stackAdjust = -3; 657 op = Opcode.CASTORE; 658 } 659 else if (type == long.class) { 660 stackAdjust = -4; 661 op = Opcode.LASTORE; 662 } 663 else if (type == float.class) { 664 stackAdjust = -3; 665 op = Opcode.FASTORE; 666 } 667 else if (type == double.class) { 668 stackAdjust = -4; 669 op = Opcode.DASTORE; 670 } 671 else { 672 stackAdjust = -3; 673 op = Opcode.AASTORE; 674 } 675 676 addCode(stackAdjust, op); 677 } 678 679 681 687 public void loadField(String fieldName, 688 TypeDescriptor type) { 689 getfield(0, Opcode.GETFIELD, constantField(fieldName, type), type); 690 } 691 692 698 public void loadField(String className, 699 String fieldName, 700 TypeDescriptor type) { 701 702 getfield(0, Opcode.GETFIELD, 703 mCp.addConstantField(className, fieldName, type), 704 type); 705 } 706 707 712 public void loadStaticField(String fieldName, 713 TypeDescriptor type) { 714 715 getfield(1, Opcode.GETSTATIC, constantField(fieldName, type), type); 716 } 717 718 723 public void loadStaticField(String className, 724 String fieldName, 725 TypeDescriptor type) { 726 727 getfield(1, Opcode.GETSTATIC, 728 mCp.addConstantField(className, fieldName, type), 729 type); 730 } 731 732 private void getfield(int stackAdjust, byte opcode, ConstantInfo info, 733 TypeDescriptor type) { 734 735 Class clazz = type.getClassArg(); 736 if (clazz != null && type.getDimensions() == 0 && 737 (clazz == long.class || clazz == double.class)) { 738 stackAdjust++; 739 } 740 741 addCode(stackAdjust, opcode, info); 742 } 743 744 private ConstantFieldInfo constantField(String fieldName, 745 TypeDescriptor type) { 746 return mCp.addConstantField 747 (mClassFile.getClassName(), fieldName, type); 748 } 749 750 752 758 public void storeField(String fieldName, 759 TypeDescriptor type) { 760 761 putfield(-1, Opcode.PUTFIELD, constantField(fieldName, type), type); 762 } 763 764 770 public void storeField(String className, 771 String fieldName, 772 TypeDescriptor type) { 773 774 putfield(-1, Opcode.PUTFIELD, 775 mCp.addConstantField(className, fieldName, type), 776 type); 777 } 778 779 784 public void storeStaticField(String fieldName, 785 TypeDescriptor type) { 786 787 putfield(0, Opcode.PUTSTATIC, constantField(fieldName, type), type); 788 } 789 790 795 public void storeStaticField(String className, 796 String fieldName, 797 TypeDescriptor type) { 798 799 putfield(0, Opcode.PUTSTATIC, 800 mCp.addConstantField(className, fieldName, type), 801 type); 802 } 803 804 private void putfield(int stackAdjust, byte opcode, ConstantInfo info, 805 TypeDescriptor type) { 806 807 Class clazz = type.getClassArg(); 808 if (clazz != null && type.getDimensions() == 0 && 809 (clazz == long.class || clazz == double.class)) { 810 811 stackAdjust -= 2; 812 } 813 else { 814 stackAdjust--; 815 } 816 817 addCode(stackAdjust, opcode, info); 818 } 819 820 822 825 public void returnVoid() { 826 addCode(0, Opcode.RETURN); 827 } 828 829 837 public void returnValue(Class type) { 838 int stackAdjust = -1; 839 byte op; 840 841 if (type == int.class || 842 type == boolean.class || 843 type == byte.class || 844 type == short.class || 845 type == char.class) { 846 847 op = Opcode.IRETURN; 848 } 849 else if (type == long.class) { 850 stackAdjust--; 851 op = Opcode.LRETURN; 852 } 853 else if (type == float.class) { 854 op = Opcode.FRETURN; 855 } 856 else if (type == double.class) { 857 stackAdjust--; 858 op = Opcode.DRETURN; 859 } 860 else if (type == void.class) { 861 stackAdjust++; 862 op = Opcode.RETURN; 863 } 864 else { 865 op = Opcode.ARETURN; 866 } 867 868 addCode(stackAdjust, op); 869 } 870 871 873 877 public void convert(Class fromType, Class toType) { 878 int stackAdjust = 0; 879 byte op; 880 881 if (fromType == int.class || 882 fromType == boolean.class || 883 fromType == byte.class || 884 fromType == short.class || 885 fromType == char.class) { 886 887 if (toType == byte.class) { 888 op = Opcode.I2B; 889 } 890 else if (toType == short.class) { 891 op = Opcode.I2S; 892 } 893 else if (toType == char.class) { 894 op = Opcode.I2C; 895 } 896 else if (toType == float.class) { 897 op = Opcode.I2F; 898 } 899 else if (toType == long.class) { 900 stackAdjust = 1; 901 op = Opcode.I2L; 902 } 903 else if (toType == double.class) { 904 stackAdjust = 1; 905 op = Opcode.I2D; 906 } 907 else if (toType == int.class) { 908 return; 909 } 910 else { 911 throw new RuntimeException ("Invalid conversion: int to " + 912 toType); 913 } 914 915 addCode(stackAdjust, op); 916 return; 917 } 918 else if (fromType == long.class) { 919 if (toType == int.class) { 920 stackAdjust = -1; 921 op = Opcode.L2I; 922 } 923 else if (toType == float.class) { 924 stackAdjust = -1; 925 op = Opcode.L2F; 926 } 927 else if (toType == double.class) { 928 op = Opcode.L2D; 929 } 930 else if (toType == byte.class || 931 toType == char.class || 932 toType == short.class) { 933 934 convert(fromType, int.class); 935 convert(int.class, toType); 936 return; 937 } 938 else if (toType == long.class) { 939 return; 940 } 941 else { 942 throw new RuntimeException ("Invalid conversion: long to " + 943 toType); 944 } 945 946 addCode(stackAdjust, op); 947 return; 948 } 949 else if (fromType == float.class) { 950 if (toType == int.class) { 951 op = Opcode.F2I; 952 } 953 else if (toType == long.class) { 954 stackAdjust = 1; 955 op = Opcode.F2L; 956 } 957 else if (toType == double.class) { 958 stackAdjust = 1; 959 op = Opcode.F2D; 960 } 961 else if (toType == byte.class || 962 toType == char.class || 963 toType == short.class) { 964 965 convert(fromType, int.class); 966 convert(int.class, toType); 967 return; 968 } 969 else if (toType == float.class) { 970 return; 971 } 972 else { 973 throw new RuntimeException ("Invalid conversion: float to " + 974 toType); 975 } 976 977 addCode(stackAdjust, op); 978 return; 979 } 980 else if (fromType == double.class) { 981 if (toType == int.class) { 982 stackAdjust = -1; 983 op = Opcode.D2I; 984 } 985 else if (toType == float.class) { 986 stackAdjust = -1; 987 op = Opcode.D2F; 988 } 989 else if (toType == long.class) { 990 op = Opcode.D2L; 991 } 992 else if (toType == byte.class || 993 toType == char.class || 994 toType == short.class) { 995 996 convert(fromType, int.class); 997 convert(int.class, toType); 998 return; 999 } 1000 else if (toType == double.class) { 1001 return; 1002 } 1003 else { 1004 throw new RuntimeException ("Invalid conversion: double to " + 1005 toType); 1006 } 1007 1008 addCode(stackAdjust, op); 1009 return; 1010 } 1011 else { 1012 throw new RuntimeException ("Invalid conversion: " + fromType + 1013 " to " + toType); 1014 } 1015 } 1016 1017 1019 1025 public void invoke(Method method) { 1026 TypeDescriptor ret = new TypeDescriptor(method.getReturnType()); 1027 1028 Class [] paramClasses = method.getParameterTypes(); 1029 TypeDescriptor[] params = new TypeDescriptor[paramClasses.length]; 1030 for (int i=0; i<params.length; i++) { 1031 params[i] = new TypeDescriptor(paramClasses[i]); 1032 } 1033 1034 Class clazz = method.getDeclaringClass(); 1035 1036 if (Modifier.isStatic(method.getModifiers())) { 1037 invokeStatic(clazz.getName(), 1038 method.getName(), 1039 ret, 1040 params); 1041 } 1042 else if (clazz.isInterface()) { 1043 invokeInterface(clazz.getName(), 1044 method.getName(), 1045 ret, 1046 params); 1047 } 1048 else { 1049 invokeVirtual(clazz.getName(), 1050 method.getName(), 1051 ret, 1052 params); 1053 } 1054 } 1055 1056 1060 public void invoke(Constructor constructor) { 1061 Class [] paramClasses = constructor.getParameterTypes(); 1062 TypeDescriptor[] params = new TypeDescriptor[paramClasses.length]; 1063 for (int i=0; i<params.length; i++) { 1064 params[i] = new TypeDescriptor(paramClasses[i]); 1065 } 1066 1067 invokeConstructor(constructor.getDeclaringClass().toString(), params); 1068 } 1069 1070 1077 public void invokeVirtual(String methodName, 1078 TypeDescriptor ret, 1079 TypeDescriptor[] params) { 1080 1081 ConstantInfo info = mCp.addConstantMethod 1082 (mClassFile.getClassName(), methodName, ret, params); 1083 1084 int stackAdjust = returnSize(ret) - 1; 1085 if (params != null) { 1086 stackAdjust -= argSize(params); 1087 } 1088 1089 addCode(stackAdjust, Opcode.INVOKEVIRTUAL, info); 1090 } 1091 1092 1099 public void invokeVirtual(String className, 1100 String methodName, 1101 TypeDescriptor ret, 1102 TypeDescriptor[] params) { 1103 ConstantInfo info = 1104 mCp.addConstantMethod(className, methodName, ret, params); 1105 1106 int stackAdjust = returnSize(ret) - 1; 1107 if (params != null) { 1108 stackAdjust -= argSize(params); 1109 } 1110 1111 addCode(stackAdjust, Opcode.INVOKEVIRTUAL, info); 1112 } 1113 1114 1121 public void invokeStatic(String methodName, 1122 TypeDescriptor ret, 1123 TypeDescriptor[] params) { 1124 ConstantInfo info = mCp.addConstantMethod 1125 (mClassFile.getClassName(), methodName, ret, params); 1126 1127 int stackAdjust = returnSize(ret) - 0; 1128 if (params != null) { 1129 stackAdjust -= argSize(params); 1130 } 1131 1132 addCode(stackAdjust, Opcode.INVOKESTATIC, info); 1133 } 1134 1135 1142 public void invokeStatic(String className, 1143 String methodName, 1144 TypeDescriptor ret, 1145 TypeDescriptor[] params) { 1146 ConstantInfo info = 1147 mCp.addConstantMethod(className, methodName, ret, params); 1148 1149 int stackAdjust = returnSize(ret) - 0; 1150 if (params != null) { 1151 stackAdjust -= argSize(params); 1152 } 1153 1154 addCode(stackAdjust, Opcode.INVOKESTATIC, info); 1155 } 1156 1157 1164 public void invokeInterface(String className, 1165 String methodName, 1166 TypeDescriptor ret, 1167 TypeDescriptor[] params) { 1168 1169 ConstantInfo info = 1170 mCp.addConstantInterfaceMethod(className, methodName, ret, params); 1171 1172 int paramCount = 1; 1173 if (params != null) { 1174 paramCount += argSize(params); 1175 } 1176 1177 int stackAdjust = returnSize(ret) - paramCount; 1178 1179 byte[] bytes = new byte[5]; 1180 1181 bytes[0] = Opcode.INVOKEINTERFACE; 1182 bytes[1] = (byte)0; 1183 bytes[2] = (byte)0; 1184 bytes[3] = (byte)paramCount; 1185 bytes[4] = (byte)0; 1186 1187 mInstructions.new ConstantOperandInstruction(stackAdjust, bytes, info); 1188 } 1189 1190 1197 public void invokePrivate(String methodName, 1198 TypeDescriptor ret, 1199 TypeDescriptor[] params) { 1200 ConstantInfo info = mCp.addConstantMethod 1201 (mClassFile.getClassName(), methodName, ret, params); 1202 1203 int stackAdjust = returnSize(ret) - 1; 1204 if (params != null) { 1205 stackAdjust -= argSize(params); 1206 } 1207 1208 addCode(stackAdjust, Opcode.INVOKESPECIAL, info); 1209 } 1210 1211 1218 public void invokeSuper(String superClassName, 1219 String methodName, 1220 TypeDescriptor ret, 1221 TypeDescriptor[] params) { 1222 ConstantInfo info = 1223 mCp.addConstantMethod(superClassName, methodName, ret, params); 1224 1225 int stackAdjust = returnSize(ret) - 1; 1226 if (params != null) { 1227 stackAdjust -= argSize(params); 1228 } 1229 1230 addCode(stackAdjust, Opcode.INVOKESPECIAL, info); 1231 } 1232 1233 1237 public void invokeSuper(Method method) { 1238 TypeDescriptor ret = new TypeDescriptor(method.getReturnType()); 1239 1240 Class [] paramClasses = method.getParameterTypes(); 1241 TypeDescriptor[] params = new TypeDescriptor[paramClasses.length]; 1242 for (int i=0; i<params.length; i++) { 1243 params[i] = new TypeDescriptor(paramClasses[i]); 1244 } 1245 1246 invokeSuper(method.getDeclaringClass().getName(), 1247 method.getName(), 1248 ret, 1249 params); 1250 } 1251 1252 1258 public void invokeConstructor(TypeDescriptor[] params) { 1259 ConstantInfo info = 1260 mCp.addConstantConstructor(mClassFile.getClassName(), params); 1261 1262 int stackAdjust = -1; 1263 if (params != null) { 1264 stackAdjust -= argSize(params); 1265 } 1266 1267 addCode(stackAdjust, Opcode.INVOKESPECIAL, info); 1268 } 1269 1270 1276 public void invokeConstructor(String className, TypeDescriptor[] params) { 1277 ConstantInfo info = mCp.addConstantConstructor(className, params); 1278 1279 int stackAdjust = -1; 1280 if (params != null) { 1281 stackAdjust -= argSize(params); 1282 } 1283 1284 addCode(stackAdjust, Opcode.INVOKESPECIAL, info); 1285 } 1286 1287 1293 public void invokeSuperConstructor(TypeDescriptor[] params) { 1294 invokeConstructor(mClassFile.getSuperClassName(), params); 1295 } 1296 1297 1301 public void invokeSuper(Constructor constructor) { 1302 Class [] paramClasses = constructor.getParameterTypes(); 1303 TypeDescriptor[] params = new TypeDescriptor[paramClasses.length]; 1304 for (int i=0; i<params.length; i++) { 1305 params[i] = new TypeDescriptor(paramClasses[i]); 1306 } 1307 1308 invokeSuperConstructor(params); 1309 } 1310 1311 private int returnSize(TypeDescriptor ret) { 1312 if (ret == null) return 0; 1313 1314 String className = ret.getClassName(); 1315 1316 if (className.equals(void.class.getName())) { 1317 return 0; 1318 } 1319 else if (className.equals(long.class.getName()) || 1320 className.equals(double.class.getName())) { 1321 return 2; 1322 } 1323 else { 1324 return 1; 1325 } 1326 } 1327 1328 private int argSize(TypeDescriptor[] params) { 1329 int size = 0; 1330 if (params != null) { 1331 for (int i=0; i<params.length; i++) { 1332 String className = params[i].getClassName(); 1333 if (params[i].getDimensions() == 0 && 1334 (className.equals(long.class.getName()) || 1335 className.equals(double.class.getName()))) { 1336 size += 2; 1337 } 1338 else { 1339 size++; 1340 } 1341 } 1342 } 1343 1344 return size; 1345 } 1346 1347 1349 1357 public void newObject(TypeDescriptor type) { 1358 int dim = type.getSpecifiedDimensions(); 1359 1360 if (dim == 0) { 1361 ConstantInfo info = mCp.addConstantClass(type); 1362 addCode(1, Opcode.NEW, info); 1363 return; 1364 } 1365 1366 TypeDescriptor componentType = type.getComponentType(); 1367 1368 if (dim == 1) { 1369 if (componentType.getDimensions() == 0) { 1370 Class clazz = componentType.getClassArg(); 1371 1372 if (clazz != null && clazz.isPrimitive()) { 1373 byte atype = (byte)0; 1374 1375 if (clazz == int.class) { 1376 atype = (byte)10; 1377 } 1378 else if (clazz == byte.class) { 1379 atype = (byte)8; 1380 } 1381 else if (clazz == boolean.class) { 1382 atype = (byte)4; 1383 } 1384 else if (clazz == char.class) { 1385 atype = (byte)5; 1386 } 1387 else if (clazz == float.class) { 1388 atype = (byte)6; 1389 } 1390 else if (clazz == double.class) { 1391 atype = (byte)7; 1392 } 1393 else if (clazz == short.class) { 1394 atype = (byte)9; 1395 } 1396 else if (clazz == long.class) { 1397 atype = (byte)11; 1398 } 1399 1400 addCode(0, Opcode.NEWARRAY, atype); 1401 return; 1402 } 1403 } 1404 1405 ConstantInfo info = mCp.addConstantClass(componentType); 1406 addCode(0, Opcode.ANEWARRAY, info); 1407 return; 1408 } 1409 1410 int stackAdjust = -(dim - 1); 1412 1413 ConstantInfo info = mCp.addConstantClass(componentType); 1414 1415 byte[] bytes = new byte[4]; 1416 1417 bytes[0] = Opcode.MULTIANEWARRAY; 1418 bytes[1] = (byte)0; 1419 bytes[2] = (byte)0; 1420 bytes[3] = (byte)dim; 1421 1422 mInstructions.new ConstantOperandInstruction(stackAdjust, bytes, info); 1423 } 1424 1425 1427 1430 public void dup() { 1431 addCode(1, Opcode.DUP); 1432 } 1433 1434 1437 public void dupX1() { 1438 addCode(1, Opcode.DUP_X1); 1439 } 1440 1441 1444 public void dupX2() { 1445 addCode(1, Opcode.DUP_X2); 1446 } 1447 1448 1451 public void dup2() { 1452 addCode(2, Opcode.DUP2); 1453 } 1454 1455 1458 public void dup2X1() { 1459 addCode(2, Opcode.DUP2_X1); 1460 } 1461 1462 1465 public void dup2X2() { 1466 addCode(2, Opcode.DUP2_X2); 1467 } 1468 1469 1472 public void pop() { 1473 addCode(-1, Opcode.POP); 1474 } 1475 1476 1479 public void pop2() { 1480 addCode(-2, Opcode.POP2); 1481 } 1482 1483 1486 public void swap() { 1487 addCode(0, Opcode.SWAP); 1488 } 1489 1490 1493 public void swap2() { 1494 dup2X2(); 1495 pop2(); 1496 } 1497 1498 1500 private void branch(int stackAdjust, Location location, byte opcode) { 1501 mInstructions.new BranchInstruction(stackAdjust, opcode, location); 1502 } 1503 1504 1510 public void branch(Location location) { 1511 branch(0, location, Opcode.GOTO); 1512 } 1513 1514 1522 public void ifNullBranch(Location location, boolean choice) { 1523 branch(-1, location, choice ? Opcode.IFNULL : Opcode.IFNONNULL); 1524 } 1525 1526 1527 1535 public void ifEqualBranch(Location location, boolean choice) { 1536 branch(-2, location, choice ? Opcode.IF_ACMPEQ : Opcode.IF_ACMPNE); 1537 } 1538 1539 1548 public void ifZeroComparisonBranch(Location location, String choice) 1549 throws IllegalArgumentException { 1550 1551 choice = choice.intern(); 1552 1553 byte opcode; 1554 if (choice == "==") { 1555 opcode = Opcode.IFEQ; 1556 } 1557 else if (choice == "!=") { 1558 opcode = Opcode.IFNE; 1559 } 1560 else if (choice == "<") { 1561 opcode = Opcode.IFLT; 1562 } 1563 else if (choice == ">=") { 1564 opcode = Opcode.IFGE; 1565 } 1566 else if (choice == ">") { 1567 opcode = Opcode.IFGT; 1568 } 1569 else if (choice == "<=") { 1570 opcode = Opcode.IFLE; 1571 } 1572 else { 1573 throw new IllegalArgumentException 1574 ("Invalid comparision choice: " + choice); 1575 } 1576 1577 branch(-1, location, opcode); 1578 } 1579 1580 1589 public void ifComparisonBranch(Location location, String choice) 1590 throws IllegalArgumentException { 1591 1592 choice = choice.intern(); 1593 1594 byte opcode; 1595 if (choice == "==") { 1596 opcode = Opcode.IF_ICMPEQ; 1597 } 1598 else if (choice == "!=") { 1599 opcode = Opcode.IF_ICMPNE; 1600 } 1601 else if (choice == "<") { 1602 opcode = Opcode.IF_ICMPLT; 1603 } 1604 else if (choice == ">=") { 1605 opcode = Opcode.IF_ICMPGE; 1606 } 1607 else if (choice == ">") { 1608 opcode = Opcode.IF_ICMPGT; 1609 } 1610 else if (choice == "<=") { 1611 opcode = Opcode.IF_ICMPLE; 1612 } 1613 else { 1614 throw new IllegalArgumentException 1615 ("Invalid comparision choice: " + choice); 1616 } 1617 1618 branch(-2, location, opcode); 1619 } 1620 1621 1637 public void switchBranch(int[] cases, 1638 Location[] locations, Location defaultLocation) { 1639 1640 mInstructions.new SwitchInstruction(cases, locations, defaultLocation); 1641 } 1642 1643 1650 public void jsr(Location location) { 1651 branch(1, location, Opcode.JSR); 1653 } 1654 1655 1661 public void ret(LocalVariable local) { 1662 if (local == null) { 1663 throw new NullPointerException ("No local variable specified"); 1664 } 1665 1666 mInstructions.new RetInstruction(local); 1667 } 1668 1669 1671 1697 public void math(byte opcode) { 1698 int stackAdjust; 1699 1700 switch(opcode) { 1701 case Opcode.INEG: 1702 case Opcode.LNEG: 1703 case Opcode.FNEG: 1704 case Opcode.DNEG: 1705 stackAdjust = 0; 1706 break; 1707 case Opcode.IADD: 1708 case Opcode.ISUB: 1709 case Opcode.IMUL: 1710 case Opcode.IDIV: 1711 case Opcode.IREM: 1712 case Opcode.IAND: 1713 case Opcode.IOR: 1714 case Opcode.IXOR: 1715 case Opcode.ISHL: 1716 case Opcode.ISHR: 1717 case Opcode.IUSHR: 1718 case Opcode.FADD: 1719 case Opcode.FSUB: 1720 case Opcode.FMUL: 1721 case Opcode.FDIV: 1722 case Opcode.FREM: 1723 case Opcode.FCMPG: 1724 case Opcode.FCMPL: 1725 stackAdjust = -1; 1726 break; 1727 case Opcode.LADD: 1728 case Opcode.LSUB: 1729 case Opcode.LMUL: 1730 case Opcode.LDIV: 1731 case Opcode.LREM: 1732 case Opcode.LAND: 1733 case Opcode.LOR: 1734 case Opcode.LXOR: 1735 case Opcode.LSHL: 1736 case Opcode.LSHR: 1737 case Opcode.LUSHR: 1738 case Opcode.DADD: 1739 case Opcode.DSUB: 1740 case Opcode.DMUL: 1741 case Opcode.DDIV: 1742 case Opcode.DREM: 1743 stackAdjust = -2; 1744 break; 1745 case Opcode.LCMP: 1746 case Opcode.DCMPG: 1747 case Opcode.DCMPL: 1748 stackAdjust = -3; 1749 break; 1750 default: 1751 throw new IllegalArgumentException 1752 ("Not a math opcode: " + Opcode.getMnemonic(opcode)); 1753 } 1754 1755 addCode(stackAdjust, opcode); 1756 } 1757 1758 1760 1764 public void arrayLength() { 1765 addCode(0, Opcode.ARRAYLENGTH); 1766 } 1767 1768 1772 public void throwObject() { 1773 addCode(-1, Opcode.ATHROW); 1774 } 1775 1776 1780 public void checkCast(TypeDescriptor type) { 1781 ConstantInfo info = mCp.addConstantClass(type); 1782 addCode(0, Opcode.CHECKCAST, info); 1783 } 1784 1785 1789 public void instanceOf(TypeDescriptor type) { 1790 ConstantInfo info = mCp.addConstantClass(type); 1791 addCode(0, Opcode.INSTANCEOF, info); 1792 } 1793 1794 1798 public void integerIncrement(LocalVariable local, int amount) { 1799 if (local == null) { 1800 throw new NullPointerException ("No local variable specified"); 1801 } 1802 1803 if (-32768 <= amount && amount <= 32767) { 1804 mInstructions.new ShortIncrementInstruction(local, (short)amount); 1805 } 1806 else { 1807 1810 loadLocal(local); 1811 loadConstant(amount); 1812 math(Opcode.IADD); 1813 storeLocal(local); 1814 } 1815 } 1816 1817 1820 public void monitorEnter() { 1821 addCode(-1, Opcode.MONITORENTER); 1822 } 1823 1824 1827 public void monitorExit() { 1828 addCode(-1, Opcode.MONITOREXIT); 1829 } 1830 1831 1834 public void nop() { 1835 addCode(0, Opcode.NOP); 1836 } 1837 1838 1841 public void breakpoint() { 1842 addCode(0, Opcode.BREAKPOINT); 1843 } 1844} 1845 | Popular Tags |