1 28 29 package org.jibx.binding.classes; 30 31 import java.util.ArrayList ; 32 import java.util.HashMap ; 33 34 import org.apache.bcel.Constants; 35 import org.apache.bcel.classfile.Method; 36 import org.apache.bcel.classfile.Utility; 37 import org.apache.bcel.generic.*; 38 import org.jibx.binding.util.StringStack; 39 import org.jibx.runtime.JiBXException; 40 41 51 52 public abstract class MethodBuilder extends BindingMethod 53 { 54 57 public static final String FRAMEWORK_EXCEPTION_CLASS = 58 "org.jibx.runtime.JiBXException"; 59 60 public static final String EXCEPTION_CONSTRUCTOR_SIGNATURE1 = 61 "(Ljava/lang/String;)V"; 62 63 public static final String EXCEPTION_CONSTRUCTOR_SIGNATURE2 = 64 "(Ljava/lang/String;Ljava/lang/Throwable;)V"; 65 66 69 70 protected static ArrayList s_argNameLists = new ArrayList (); 71 72 73 protected static String [] EMPTY_STRING_ARRAY = new String [0]; 74 75 78 79 protected InstructionBuilder m_instructionBuilder; 80 81 82 private InstructionList m_instructionList; 83 84 85 private StringStack m_stackState; 86 87 88 protected MethodGen m_generator; 89 90 91 protected Method m_method; 92 93 94 protected ClassItem m_item; 95 96 97 private ArrayList m_localTypes; 98 99 101 protected ArrayList m_exceptions; 102 103 104 protected int m_hashCode; 105 106 107 protected BranchWrapper[] m_targetBranches; 108 109 111 protected HashMap m_valueMap; 112 113 123 124 protected MethodBuilder(String name, Type ret, Type[] args, 125 ClassFile cf, int access) throws JiBXException { 126 super(cf); 127 128 if (args.length >= s_argNameLists.size()) { 130 131 for (int i = s_argNameLists.size(); i <= args.length; i++) { 133 String [] list = new String [i]; 134 if (i > 0) { 135 Object last = s_argNameLists.get(i-1); 136 System.arraycopy(last, 0, list, 0, i-1); 137 list[i-1] = "arg" + i; 138 } 139 s_argNameLists.add(list); 140 } 141 142 } 143 144 String [] names = (String [])s_argNameLists.get(args.length); 146 m_instructionList = new InstructionList(); 147 m_stackState = new StringStack(); 148 m_instructionBuilder = cf.getInstructionBuilder(); 149 m_generator = new MethodGen(access, ret, args, names, name, 150 cf.getName(), m_instructionList, cf.getConstPoolGen()); 151 152 m_localTypes = new ArrayList (); 154 if ((access & Constants.ACC_STATIC) == 0) { 155 m_localTypes.add(cf.getName()); 156 } 157 for (int i = 0; i < args.length; i++) { 158 m_localTypes.add(args[i].toString()); 159 if (args[i].getSize() > 1) { 160 m_localTypes.add(null); 161 } 162 } 163 } 164 165 170 171 public String getName() { 172 return m_generator.getName(); 173 } 174 175 180 181 public String getSignature() { 182 return m_generator.getSignature(); 183 } 184 185 190 191 public int getAccessFlags() { 192 return m_generator.getAccessFlags(); 193 } 194 195 200 201 public void setAccessFlags(int flags) { 202 m_generator.setAccessFlags(flags); 203 } 204 205 211 212 public Method getMethod() { 213 if (m_method == null) { 214 throw new IllegalStateException ("Method still under construction"); 215 } else { 216 return m_method; 217 } 218 } 219 220 226 227 public Object setKeyValue(Object key, Object value) { 228 if (m_valueMap == null) { 229 m_valueMap = new HashMap (); 230 } 231 return m_valueMap.put(key, value); 232 } 233 234 238 239 public Object getKeyValue(Object key) { 240 return m_valueMap == null ? null : m_valueMap.get(key); 241 } 242 243 248 249 public void addException(String name) { 250 if (m_exceptions == null) { 251 m_exceptions = new ArrayList (); 252 } 253 if (!m_exceptions.contains(name)) { 254 m_exceptions.add(name); 255 } 256 } 257 258 263 264 public void addMethodExceptions(ClassItem method) { 265 String [] excepts = method.getExceptions(); 266 if (excepts != null) { 267 for (int i = 0; i < excepts.length; i++) { 268 addException(excepts[i]); 269 } 270 } 271 } 272 273 278 279 protected InstructionHandle getFirstInstruction() { 280 return m_instructionList.getStart(); 281 } 282 283 288 289 protected InstructionHandle getLastInstruction() { 290 return m_instructionList.getEnd(); 291 } 292 293 299 300 protected final void setTarget(InstructionHandle inst) { 301 if (m_targetBranches != null) { 302 303 String [] types = m_stackState.toArray(); 306 if (m_targetBranches.length > 0) { 307 boolean match = true; 308 int depth = m_targetBranches[0].getStackState().length; 309 for (int i = 1; i < m_targetBranches.length; i++) { 310 if (depth != m_targetBranches[i].getStackState().length) { 311 match = false; 312 break; 313 } 314 } 315 if (match) { 316 if (depth > types.length) { 317 BranchWrapper merge = new BranchWrapper 318 (m_instructionList.insert(inst, new GOTO(null)), 319 types, this); 320 String [] stack = m_targetBranches[0].getStackState(); 321 m_stackState = new StringStack(stack); 322 InstructionHandle poph = m_instructionList. 323 insert(inst, InstructionConstants.POP); 324 for (int i = 0; i < m_targetBranches.length; i++) { 325 m_targetBranches[i].setTarget(poph, stack, this); 326 } 327 m_stackState.pop(); 328 while (m_stackState.size() > types.length) { 329 m_instructionList.insert(inst, 330 InstructionConstants.POP); 331 m_stackState.pop(); 332 } 333 merge.setTarget(inst, m_stackState.toArray(), this); 334 m_targetBranches = null; 335 return; 336 } else { 337 while (depth < types.length) { 338 m_instructionList.insert(inst, 339 InstructionConstants.POP); 340 m_stackState.pop(); 341 types = m_stackState.toArray(); 342 } 343 } 344 } 345 } 346 347 for (int i = 0; i < m_targetBranches.length; i++) { 349 m_targetBranches[i].setTarget(inst, types, this); 350 } 351 m_targetBranches = null; 352 } 353 } 354 355 360 361 private String describeStack() { 362 StringBuffer buff = new StringBuffer (); 363 String [] types = m_stackState.toArray(); 364 for (int i = 0; i < types.length; i++) { 365 buff.append(" "); 366 buff.append(i); 367 buff.append(": "); 368 buff.append(types[i]); 369 buff.append('\n'); 370 } 371 return buff.toString(); 372 } 373 374 381 382 private void verifyCompatible(String type, String need) { 383 if (!need.equals(type)) { 384 try { 385 if ("<null>".equals(type)) { 386 if (ClassItem.isPrimitive(need)) { 387 throw new IllegalStateException 388 ("Internal error: Expected " + need + 389 " on stack , found null"); 390 } 391 } else if ("java.lang.Object".equals(need)) { 392 if (ClassItem.isPrimitive(type)) { 393 throw new IllegalStateException ("Internal error: " + 394 "Expected object reference on stack, found " + 395 type + "\n full stack:\n" + describeStack()); 396 } 397 } else { 398 boolean match = false; 399 if ("int".equals(need)) { 400 match = "boolean".equals(type) || 401 "short".equals(type) || "char".equals(type) || 402 "byte".equals(type); 403 } else if ("int".equals(type)) { 404 match = "boolean".equals(need) || 405 "short".equals(need) || "char".equals(need) || 406 "byte".equals(need); 407 } 408 if (!match && !ClassItem.isAssignable(type, need)) { 409 throw new IllegalStateException 410 ("Internal error: Expected " + need + 411 " on stack, found " + type + "\n full stack:\n" + 412 describeStack()); 413 } 414 } 415 } catch (JiBXException e) { 416 throw new RuntimeException 417 ("Internal error: Attempting to compare types " + need + 418 " and " + type); 419 } 420 } 421 } 422 423 429 430 private void verifyStackDepth(int count) { 431 if (m_stackState.size() < count) { 432 throw new IllegalStateException 433 ("Internal error: Too few values on stack\n full stack:\n" + 434 describeStack()); 435 } 436 } 437 438 444 445 private void verifyStack(String t1) { 446 verifyStackDepth(1); 447 verifyCompatible(m_stackState.peek(), t1); 448 } 449 450 457 458 private void verifyStack(String t1, String t2) { 459 verifyStackDepth(2); 460 verifyCompatible(m_stackState.peek(), t1); 461 verifyCompatible(m_stackState.peek(1), t2); 462 } 463 464 470 471 private void verifyCallStack(String [] types) { 472 473 int count = types.length; 475 verifyStackDepth(count); 476 477 for (int i = 0; i < count; i++) { 479 int slot = count - i - 1; 480 verifyCompatible(m_stackState.peek(slot), types[i]); 481 } 482 } 483 484 492 493 private void verifyCallStack(String clas, String [] types) { 494 495 int count = types.length; 497 verifyStackDepth(count+1); 498 verifyCompatible(m_stackState.peek(count), clas); 499 500 verifyCallStack(types); 502 } 503 504 508 509 private void verifyStackObject() { 510 verifyStackDepth(1); 511 String top = m_stackState.peek(); 512 if (ClassItem.isPrimitive(top)) { 513 throw new IllegalStateException ("Internal error: " + 514 "Expected object reference on stack , found " + 515 m_stackState.peek() + "\n full stack:\n" + describeStack()); 516 } 517 } 518 519 525 526 public BranchWrapper appendIFEQ(Object src) { 527 verifyStack("int"); 528 BranchHandle hand = m_instructionList.append(new IFEQ(null)); 529 setTarget(hand); 530 m_stackState.pop(); 531 return new BranchWrapper(hand, m_stackState.toArray(), src); 532 } 533 534 540 541 public BranchWrapper appendIFGE(Object src) { 542 verifyStack("int"); 543 BranchHandle hand = m_instructionList.append(new IFGE(null)); 544 setTarget(hand); 545 m_stackState.pop(); 546 return new BranchWrapper(hand, m_stackState.toArray(), src); 547 } 548 549 555 556 public BranchWrapper appendIFNE(Object src) { 557 verifyStack("int"); 558 BranchHandle hand = m_instructionList.append(new IFNE(null)); 559 setTarget(hand); 560 m_stackState.pop(); 561 return new BranchWrapper(hand, m_stackState.toArray(), src); 562 } 563 564 570 571 public BranchWrapper appendIFNONNULL(Object src) { 572 verifyStackObject(); 573 BranchHandle hand = m_instructionList.append(new IFNONNULL(null)); 574 setTarget(hand); 575 m_stackState.pop(); 576 return new BranchWrapper(hand, m_stackState.toArray(), src); 577 } 578 579 585 586 public BranchWrapper appendIFNULL(Object src) { 587 verifyStackObject(); 588 BranchHandle hand = m_instructionList.append(new IFNULL(null)); 589 setTarget(hand); 590 m_stackState.pop(); 591 return new BranchWrapper(hand, m_stackState.toArray(), src); 592 } 593 594 600 601 public BranchWrapper appendIF_ICMPNE(Object src) { 602 verifyStack("int", "int"); 603 BranchHandle hand = m_instructionList.append(new IF_ICMPNE(null)); 604 setTarget(hand); 605 m_stackState.pop(2); 606 return new BranchWrapper(hand, m_stackState.toArray(), src); 607 } 608 609 615 616 public BranchWrapper appendUnconditionalBranch(Object src) { 617 BranchHandle hand = m_instructionList.append(new GOTO(null)); 618 setTarget(hand); 619 BranchWrapper wrapper = 620 new BranchWrapper(hand, m_stackState.toArray(), src); 621 m_stackState = null; 622 return wrapper; 623 } 624 625 630 631 private void append(CompoundInstruction ins) { 632 setTarget(m_instructionList.append(ins)); 633 } 634 635 640 641 private void append(Instruction ins) { 642 setTarget(m_instructionList.append(ins)); 643 } 644 645 651 652 public void appendLoadConstant(int value) { 653 append(m_instructionBuilder.createLoadConstant(value)); 654 m_stackState.push("int"); 655 } 656 657 663 664 public void appendLoadConstant(String value) { 665 append(m_instructionBuilder.createLoadConstant(value)); 666 m_stackState.push("java.lang.String"); 667 } 668 669 675 676 public void appendLoadConstant(Object value) { 677 append(m_instructionBuilder.createLoadConstant(value)); 678 if (value instanceof Integer || value instanceof Character || 679 value instanceof Short || value instanceof Boolean || 680 value instanceof Byte ) { 681 m_stackState.push("int"); 682 } else if (value instanceof Long ) { 683 m_stackState.push("long"); 684 } else if (value instanceof Float ) { 685 m_stackState.push("float"); 686 } else if (value instanceof Double ) { 687 m_stackState.push("double"); 688 } else { 689 throw new IllegalArgumentException ("Unknown argument type"); 690 } 691 } 692 693 699 700 public void appendGetField(ClassItem item) { 701 verifyStack(item.getClassFile().getName()); 702 append(m_instructionBuilder.createGetField(item)); 703 m_stackState.pop(); 704 m_stackState.push(item.getTypeName()); 705 } 706 707 713 714 public void appendGetStatic(ClassItem item) { 715 append(m_instructionBuilder.createGetStatic(item)); 716 m_stackState.push(item.getTypeName()); 717 } 718 719 725 726 public void appendGet(ClassItem item) { 727 if (item.isStatic()) { 728 appendGetStatic(item); 729 } else { 730 appendGetField(item); 731 } 732 } 733 734 740 741 public void appendPutField(ClassItem item) { 742 String tname = item.getTypeName(); 743 verifyStack(tname, item.getClassFile().getName()); 744 append(m_instructionBuilder.createPutField(item)); 745 m_stackState.pop(2); 746 } 747 748 754 755 public void appendPutStatic(ClassItem item) { 756 verifyStack(item.getTypeName()); 757 append(m_instructionBuilder.createPutStatic(item)); 758 m_stackState.pop(); 759 } 760 761 767 768 public void appendPut(ClassItem item) { 769 if (item.isStatic()) { 770 appendPutStatic(item); 771 } else { 772 appendPutField(item); 773 } 774 } 775 776 783 784 public void appendCall(ClassItem item) { 785 786 String [] types = item.getArgumentTypes(); 788 int count = types.length; 789 if (item.getClassFile().isInterface()) { 790 791 verifyCallStack(item.getClassFile().getName(), types); 793 append(m_instructionBuilder.createCallInterface(item)); 794 m_stackState.pop(count+1); 795 796 } else if ((item.getAccessFlags() & Constants.ACC_STATIC) != 0) { 797 798 verifyCallStack(types); 800 append(m_instructionBuilder.createCallStatic(item)); 801 if (count > 0) { 802 m_stackState.pop(count); 803 } 804 805 } else { 806 807 verifyCallStack(item.getClassFile().getName(), types); 809 append(m_instructionBuilder.createCallVirtual(item)); 810 m_stackState.pop(count+1); 811 } 812 813 if (!"void".equals(item.getTypeName())) { 815 m_stackState.push(item.getTypeName()); 816 } 817 } 818 819 826 827 public void appendCallStatic(String method, String signature) { 828 829 String [] types = ClassItem.getParametersFromSignature(signature); 831 verifyCallStack(types); 832 833 append(m_instructionBuilder.createCallStatic(method, signature)); 835 836 if (types.length > 0) { 838 m_stackState.pop(types.length); 839 } 840 String result = ClassItem.getTypeFromSignature(signature); 841 if (!"void".equals(result)) { 842 m_stackState.push(result); 843 } 844 } 845 846 853 854 public void appendCallVirtual(String method, String signature) { 855 856 String [] types = ClassItem.getParametersFromSignature(signature); 858 int split = method.lastIndexOf('.'); 859 if (split < 0) { 860 throw new IllegalArgumentException 861 ("Internal error: Missing class name on method " + method); 862 } 863 verifyCallStack(method.substring(0, split), types); 864 865 append(m_instructionBuilder.createCallVirtual(method, signature)); 867 868 m_stackState.pop(types.length+1); 870 String result = ClassItem.getTypeFromSignature(signature); 871 if (!"void".equals(result)) { 872 m_stackState.push(result); 873 } 874 } 875 876 883 884 public void appendCallInterface(String method, String signature) { 885 886 String [] types = ClassItem.getParametersFromSignature(signature); 888 int split = method.lastIndexOf('.'); 889 if (split < 0) { 890 throw new IllegalArgumentException 891 ("Internal error: Missing class name on method " + method); 892 } 893 verifyCallStack(method.substring(0, split), types); 894 895 append(m_instructionBuilder.createCallInterface(method, signature)); 897 898 m_stackState.pop(types.length+1); 900 String result = ClassItem.getTypeFromSignature(signature); 901 if (!"void".equals(result)) { 902 m_stackState.push(result); 903 } 904 } 905 906 911 912 public void appendCreateNew(String name) { 913 append(m_instructionBuilder.createNew(name)); 914 m_stackState.push(name); 915 } 916 917 924 925 public void appendCallInit(String name, String signature) { 926 927 String [] types = ClassItem.getParametersFromSignature(signature); 929 verifyCallStack(name, types); 930 931 append(m_instructionBuilder.createCallInit(name, signature)); 933 934 m_stackState.pop(types.length+1); 936 } 937 938 943 944 public void appendCreateArray(String type) { 945 if (ClassItem.isPrimitive(type)) { 946 String sig = Utility.getSignature(type); 947 append(new NEWARRAY(Utility.typeOfSignature(sig))); 948 } else { 949 append(new ANEWARRAY(m_instructionBuilder. 950 getConstantPoolGen().addClass(type))); 951 } 952 m_stackState.pop(); 953 m_stackState.push(type + "[]"); 954 } 955 956 962 963 public void appendCreateCast(String from, String to) { 964 965 verifyStack(from); 967 968 if (!from.equals(to)) { 970 971 append(m_instructionBuilder. 973 createCast(ClassItem.typeFromName(from), 974 ClassItem.typeFromName(to))); 975 m_stackState.pop(); 976 m_stackState.push(to); 977 } 978 } 979 980 985 986 public void appendCreateCast(String to) { 987 988 verifyStackObject(); 990 991 if (!m_stackState.peek().equals(to)) { 993 994 append(m_instructionBuilder. 996 createCast(Type.OBJECT, ClassItem.typeFromName(to))); 997 m_stackState.pop(); 998 m_stackState.push(to); 999 } 1000 } 1001 1002 1007 1008 public void appendInstanceOf(String to) { 1009 1010 verifyStackObject(); 1012 1013 if ("java.lang.Object".equals(to)) { 1015 append(InstructionConstants.POP); 1016 appendLoadConstant(1); 1017 } else { 1018 append(m_instructionBuilder. 1019 createInstanceOf((ObjectType)ClassItem.typeFromName(to))); 1020 } 1021 1022 m_stackState.pop(); 1024 m_stackState.push("int"); 1025 } 1026 1027 1036 1037 protected LocalVariableGen createLocal(String name, Type type) { 1038 1039 verifyStack(type.toString()); 1041 1042 LocalVariableGen var = m_generator.addLocalVariable 1044 (name, type, getLastInstruction(), null); 1045 append(InstructionFactory.createStore(type, var.getIndex())); 1046 1047 int slot = var.getIndex(); 1049 while (slot >= m_localTypes.size()) { 1050 m_localTypes.add(null); 1051 } 1052 m_localTypes.set(slot, type.toString()); 1053 1054 m_stackState.pop(); 1056 return var; 1057 } 1058 1059 1069 1070 public int addLocal(String name, Type type) { 1071 LocalVariableGen var = createLocal(name, type); 1072 return var.getIndex(); 1073 } 1074 1075 1080 1081 public void appendLoadLocal(int slot) { 1082 String type = (String )m_localTypes.get(slot); 1083 if (type == null) { 1084 throw new IllegalArgumentException 1085 ("Internal error: No variable defined at position " + slot); 1086 } 1087 append(InstructionFactory. 1088 createLoad(ClassItem.typeFromName(type), slot)); 1089 m_stackState.push(type); 1090 } 1091 1092 1097 1098 public void appendStoreLocal(int slot) { 1099 String type = (String )m_localTypes.get(slot); 1100 if (type == null) { 1101 throw new IllegalArgumentException 1102 ("Internal error: No variable defined at position " + slot); 1103 } 1104 verifyStack(type); 1105 append(InstructionFactory. 1106 createStore(ClassItem.typeFromName(type), slot)); 1107 m_stackState.pop(); 1108 } 1109 1110 1116 1117 public void appendIncrementLocal(int inc, int slot) { 1118 String type = (String )m_localTypes.get(slot); 1119 if (type == null) { 1120 throw new IllegalArgumentException 1121 ("Internal error: No variable defined at position " + slot); 1122 } else if (!"int".equals(type)) { 1123 throw new IllegalArgumentException ("Internal error: Variable at " + 1124 slot + " is " + type + ", not int"); 1125 } 1126 append(new IINC(slot, inc)); 1127 } 1128 1129 1132 1133 public void appendReturn() { 1134 append(InstructionConstants.RETURN); 1135 m_stackState = null; 1136 } 1137 1138 1143 1144 public void appendReturn(Type type) { 1145 1146 if (type != Type.VOID) { 1148 verifyStack(type.toString()); 1149 } 1150 append(InstructionFactory.createReturn(type)); 1151 1152 m_stackState = null; 1154 } 1155 1156 1161 1162 public void appendReturn(String type) { 1163 1164 if ("void".equals(type)) { 1166 append(InstructionConstants.RETURN); 1167 } else { 1168 verifyStack(type); 1169 if (ClassItem.isPrimitive(type)) { 1170 if ("int".equals(type) || "char".equals(type) || 1171 "short".equals(type) || "boolean".equals(type)) { 1172 append(InstructionConstants.IRETURN); 1173 } else if ("long".equals(type)) { 1174 append(InstructionConstants.LRETURN); 1175 } else if ("float".equals(type)) { 1176 append(InstructionConstants.FRETURN); 1177 } else if ("double".equals(type)) { 1178 append(InstructionConstants.DRETURN); 1179 } else { 1180 throw new IllegalArgumentException ("Unknown argument type"); 1181 } 1182 } else { 1183 append(InstructionConstants.ARETURN); 1184 } 1185 } 1186 1187 m_stackState = null; 1189 } 1190 1191 1194 1195 public void appendThrow() { 1196 append(InstructionConstants.ATHROW); 1197 m_stackState = null; 1198 } 1199 1200 1204 1205 public void appendAASTORE() { 1206 verifyStackDepth(3); 1207 append(InstructionConstants.AASTORE); 1208 m_stackState.pop(3); 1209 } 1210 1211 1214 1215 public void appendACONST_NULL() { 1216 append(InstructionConstants.ACONST_NULL); 1217 m_stackState.push("<null>"); 1218 } 1219 1220 1223 1224 public void appendDCMPG() { 1225 verifyStack("double", "double"); 1226 append(InstructionConstants.DCMPG); 1227 m_stackState.pop(2); 1228 m_stackState.push("int"); 1229 } 1230 1231 1234 1235 public void appendDUP() { 1236 verifyStackDepth(1); 1237 append(InstructionConstants.DUP); 1238 m_stackState.push(m_stackState.peek()); 1239 } 1240 1241 1244 1245 public void appendDUP2() { 1246 verifyStackDepth(1); 1247 append(InstructionConstants.DUP2); 1248 m_stackState.push(m_stackState.peek()); 1249 } 1250 1251 1254 1255 public void appendDUP_X1() { 1256 verifyStackDepth(2); 1257 append(InstructionConstants.DUP_X1); 1258 String hold0 = m_stackState.pop(); 1259 String hold1 = m_stackState.pop(); 1260 m_stackState.push(hold0); 1261 m_stackState.push(hold1); 1262 m_stackState.push(hold0); 1263 } 1264 1265 1268 1269 public void appendFCMPG() { 1270 verifyStack("float", "float"); 1271 append(InstructionConstants.FCMPG); 1272 m_stackState.pop(2); 1273 m_stackState.push("int"); 1274 } 1275 1276 1280 1281 public void appendIASTORE() { 1282 verifyStackDepth(3); 1283 append(InstructionConstants.IASTORE); 1284 m_stackState.pop(3); 1285 } 1286 1287 1290 1291 public void appendICONST_0() { 1292 append(InstructionConstants.ICONST_0); 1293 m_stackState.push("int"); 1294 } 1295 1296 1299 1300 public void appendICONST_1() { 1301 append(InstructionConstants.ICONST_1); 1302 m_stackState.push("int"); 1303 } 1304 1305 1308 1309 public void appendISUB() { 1310 verifyStack("int", "int"); 1311 append(InstructionConstants.ISUB); 1312 m_stackState.pop(1); 1313 } 1314 1315 1318 1319 public void appendIXOR() { 1320 verifyStack("int", "int"); 1321 append(InstructionConstants.IXOR); 1322 m_stackState.pop(1); 1323 } 1324 1325 1328 1329 public void appendLCMP() { 1330 verifyStack("long", "long"); 1331 append(InstructionConstants.LCMP); 1332 m_stackState.pop(2); 1333 m_stackState.push("int"); 1334 } 1335 1336 1339 1340 public void appendPOP() { 1341 verifyStackDepth(1); 1342 String type = m_stackState.peek(); 1343 if ("long".equals(type) || "double".equals(type)) { 1344 throw new IllegalStateException 1345 ("Internal error: POP splits long value"); 1346 } 1347 append(InstructionConstants.POP); 1348 m_stackState.pop(); 1349 } 1350 1351 1354 1355 public void appendPOP2() { 1356 verifyStackDepth(1); 1357 String type = m_stackState.peek(); 1358 if (!"long".equals(type) && !"double".equals(type)) { 1359 throw new IllegalStateException 1360 ("Internal error: POP2 requires long value"); 1361 } 1362 append(InstructionConstants.POP2); 1363 m_stackState.pop(); 1364 } 1365 1366 1369 1370 public void appendSWAP() { 1371 verifyStackDepth(2); 1372 append(InstructionConstants.SWAP); 1373 String hold0 = m_stackState.pop(); 1374 String hold1 = m_stackState.pop(); 1375 m_stackState.push(hold0); 1376 m_stackState.push(hold1); 1377 } 1378 1379 1385 1386 private BranchTarget appendTargetInstruction(CompoundInstruction inst) { 1387 String [] types = m_stackState.toArray(); 1388 InstructionHandle hand = m_instructionList.append(inst); 1389 return new BranchTarget(hand, types); 1390 } 1391 1392 1398 1399 private BranchTarget appendTargetInstruction(Instruction inst) { 1400 String [] types = m_stackState.toArray(); 1401 InstructionHandle hand = m_instructionList.append(inst); 1402 return new BranchTarget(hand, types); 1403 } 1404 1405 1410 1411 public BranchTarget appendTargetNOP() { 1412 return appendTargetInstruction(InstructionConstants.NOP); 1413 } 1414 1415 1420 1421 public BranchTarget appendTargetACONST_NULL() { 1422 BranchTarget target = appendTargetInstruction 1423 (InstructionConstants.ACONST_NULL); 1424 m_stackState.push("<null>"); 1425 return target; 1426 } 1427 1428 1435 1436 public BranchTarget appendTargetLoadConstant(int value) { 1437 BranchTarget target = appendTargetInstruction(m_instructionBuilder. 1438 createLoadConstant(value)); 1439 m_stackState.push("int"); 1440 return target; 1441 } 1442 1443 1450 1451 public BranchTarget appendTargetLoadConstant(String value) { 1452 BranchTarget target = appendTargetInstruction(m_instructionBuilder. 1453 createLoadConstant(value)); 1454 m_stackState.push("java.lang.String"); 1455 return target; 1456 } 1457 1458 1464 1465 public BranchTarget appendTargetCreateNew(String name) { 1466 BranchTarget target = 1467 appendTargetInstruction(m_instructionBuilder.createNew(name)); 1468 m_stackState.push(name); 1469 return target; 1470 } 1471 1472 1478 1479 protected InstructionHandle internalAppendCreateNew(String name) { 1480 InstructionHandle handle = m_instructionList.append 1481 (m_instructionBuilder.createNew(name)); 1482 m_stackState.push(name); 1483 return handle; 1484 } 1485 1486 1491 1492 public boolean isStackTopLong() { 1493 verifyStackDepth(1); 1494 String type = m_stackState.peek(); 1495 return "long".equals(type) || "double".equals(type); 1496 } 1497 1498 1507 1508 public void initStackState(BranchWrapper branch) { 1509 m_stackState = new StringStack(branch.getStackState()); 1510 } 1511 1512 1522 1523 public void initStackState(BranchWrapper branch, int pop) { 1524 m_stackState = new StringStack(branch.getStackState()); 1525 if (pop > 0) { 1526 m_stackState.pop(pop); 1527 } 1528 } 1529 1530 1537 1538 protected void initStackState(String [] types) { 1539 m_stackState = new StringStack(types); 1540 } 1541 1542 1552 1553 public void targetNext(BranchWrapper branch) { 1554 if (branch != null) { 1555 if (m_targetBranches == null) { 1556 m_targetBranches = new BranchWrapper[] { branch }; 1557 if (m_stackState == null) { 1558 m_stackState = new StringStack(branch.getStackState()); 1559 } 1560 } else { 1561 int length = m_targetBranches.length; 1562 BranchWrapper[] wrappers = new BranchWrapper[length+1]; 1563 System.arraycopy(m_targetBranches, 0, wrappers, 0, length); 1564 wrappers[length] = branch; 1565 m_targetBranches = wrappers; 1566 } 1567 } 1568 } 1569 1570 1577 1578 protected abstract void handleExceptions() throws JiBXException; 1579 1580 1590 1591 public void codeComplete(boolean suffix) throws JiBXException { 1592 if (m_targetBranches != null) { 1593 throw new IllegalStateException 1594 ("Method complete with pending branch target"); 1595 } 1596 if (m_exceptions != null) { 1597 handleExceptions(); 1598 } 1599 if (suffix) { 1600 m_generator.setName(getClassFile(). 1601 makeUniqueMethodName(m_generator.getName())); 1602 } 1603 m_generator.setMaxStack(); 1604 m_generator.setMaxLocals(); 1605 m_instructionList.setPositions(true); 1606 m_method = m_generator.getMethod(); 1607 m_instructionList.dispose(); 1608 m_hashCode = computeMethodHash(m_method); 1609 } 1610 1611 1616 1617 public ClassItem getItem() { 1618 if (m_item == null) { 1619 throw new IllegalStateException ("Method not added to class"); 1620 } else { 1621 return m_item; 1622 } 1623 } 1624 1625 1631 1632 public int hashCode() { 1633 if (m_method == null) { 1634 throw new IllegalStateException ("Method still under construction"); 1635 } else { 1636 return m_hashCode; 1637 } 1638 } 1639 1640 1647 1648 public ClassItem addMethod() throws JiBXException { 1649 if (m_method == null) { 1650 throw new IllegalStateException ("Method not finalized."); 1651 } else { 1652 m_item = getClassFile().addMethod(m_method); 1653 return m_item; 1654 } 1655 } 1656} | Popular Tags |