92 * This explains the rather complicated type format used in output frames. 93 * 94 * This format is the following: DIM KIND VALUE (4, 4 and 24 bits). DIM is a 95 * signed number of array dimensions (from -8 to 7). KIND is either BASE, 96 * LOCAL or STACK. BASE is used for types that are not relative to the input 97 * frame. LOCAL is used for types that are relative to the input local 98 * variable types. STACK is used for types that are relative to the input 99 * stack types. VALUE depends on KIND. For LOCAL types, it is an index in 100 * the input local variable types. For STACK types, it is a position 101 * relatively to the top of input frame stack. For BASE types, it is either 102 * one of the constants defined in FrameVisitor, or for OBJECT and 103 * UNINITIALIZED types, a tag and an index in the type table. 104 * 105 * Output frames can contain types of any kind and with a positive or 106 * negative dimension (and even unassigned types, represented by 0 - which 107 * does not correspond to any valid type value). Input frames can only 108 * contain BASE types of positive or null dimension. In all cases the type 109 * table contains only internal type names (array type descriptors are 110 * forbidden - dimensions must be represented through the DIM field). 111 * 112 * The LONG and DOUBLE types are always represented by using two slots (LONG + 113 * TOP or DOUBLE + TOP), for local variable types as well as in the operand 114 * stack. This is necessary to be able to simulate DUPx_y instructions, 115 * whose effect would be dependent on the actual type values if types were 116 * always represented by a single slot in the stack (and this is not 117 * possible, since actual type values are not always known - cf LOCAL and 118 * STACK type kinds). 119 */ 120 121 /** 122 * Mask to get the dimension of a frame type. This dimension is a signed 123 * integer between -8 and 7. 124 */ 125 static final int DIM = 0xF0000000; 126 127 /** 128 * Constant to be added to a type to get a type with one more dimension. 129 */ 130 static final int ARRAY_OF = 0x10000000; 131 132 /** 133 * Constant to be added to a type to get a type with one less dimension. 134 */ 135 static final int ELEMENT_OF = 0xF0000000; 136 137 /** 138 * Mask to get the kind of a frame type. 139 * 140 * @see #BASE 141 * @see #LOCAL 142 * @see #STACK 143 */ 144 static final int KIND = 0xF000000; 145 146 /** 147 * Flag used for LOCAL and STACK types. Indicates that if this type happens 148 * to be a long or double type (during the computations of input frames), 149 * then it must be set to TOP because the second word of this value has 150 * been reused to store other data in the basic block. Hence the first word 151 * no longer stores a valid long or double value. 152 */ 153 static final int TOP_IF_LONG_OR_DOUBLE = 0x800000; 154 155 /** 156 * Mask to get the value of a frame type. 157 */ 158 static final int VALUE = 0x7FFFFF; 159 160 /** 161 * Mask to get the kind of base types. 162 */ 163 static final int BASE_KIND = 0xFF00000; 164 165 /** 166 * Mask to get the value of base types. 167 */ 168 static final int BASE_VALUE = 0xFFFFF; 169 170 /** 171 * Kind of the types that are not relative to an input stack map frame. 535 private int initializationCount; 536 537 /** 538 * The types that are initialized in the basic block. A constructor 539 * invocation on an UNINITIALIZED or UNINITIALIZED_THIS type must replace 540 * <i>every occurence</i> of this type in the local variables and in the 541 * operand stack. This cannot be done during the first phase of the 542 * algorithm since, during this phase, the local variables and the operand 543 * stack are not completely computed. It is therefore necessary to store the 544 * types on which constructors are invoked in the basic block, in order to 545 * do this replacement during the second phase of the algorithm, where the 546 * frames are fully computed. Note that this array can contain types that 547 * are relative to input locals or to the input stack (see below for the 548 * description of the algorithm). 549 */ 550 private int[] initializations; 551 552 /** 553 * Returns the output frame local variable type at the given index. 554 * 555 * @param local the index of the local that must be returned. 556 * @return the output frame local variable type at the given index. 557 */ 558 private int get(final int local) { 559 if (outputLocals == null || local >= outputLocals.length) { 560 // this local has never been assigned in this basic block, 561 // so it is still equal to its value in the input frame 562 return LOCAL | local; 563 } else { 564 int type = outputLocals[local]; 565 if (type == 0) { 566 // this local has never been assigned in this basic block, 567 // so it is still equal to its value in the input frame 568 type = outputLocals[local] = LOCAL | local; 569 } 570 return type; 571 } 572 } 573 574 /** 575 * Sets the output frame local variable type at the given index. 576 * 577 * @param local the index of the local that must be set. 578 * @param type the value of the local that must be set. 579 */ 580 private void set(final int local, final int type) { 581 // creates and/or resizes the output local variables array if necessary 582 if (outputLocals == null) { 583 outputLocals = new int[10]; 584 } 585 int n = outputLocals.length; 586 if (local >= n) { 587 int[] t = new int[Math.max(local + 1, 2 * n)]; 588 System.arraycopy(outputLocals, 0, t, 0, n); 589 outputLocals = t; 590 } 591 // sets the local variable 592 outputLocals[local] = type; 593 } 594 595 /** 596 * Pushes a new type onto the output frame stack. 597 * 598 * @param type the type that must be pushed. 599 */ 600 private void push(final int type) { 601 // creates and/or resizes the output stack array if necessary 602 if (outputStack == null) { 603 outputStack = new int[10]; 604 } 605 int n = outputStack.length; 606 if (outputStackTop >= n) { 607 int[] t = new int[Math.max(outputStackTop + 1, 2 * n)]; 608 System.arraycopy(outputStack, 0, t, 0, n); 609 outputStack = t; 610 } 611 // pushes the type on the output stack 612 outputStack[outputStackTop++] = type; 613 // updates the maximun height reached by the output stack, if needed 614 int top = owner.inputStackTop + outputStackTop; 615 if (top > owner.outputStackMax) { 616 owner.outputStackMax = top; 617 } 618 } 619 620 /** 621 * Pushes a new type onto the output frame stack. 622 * 623 * @param cw the ClassWriter to which this label belongs. 624 * @param desc the descriptor of the type to be pushed. Can also be a method 625 * descriptor (in this case this method pushes its return type onto 626 * the output frame stack). 627 */ 628 private void push(final ClassWriter cw, final String desc) { 629 int type = type(cw, desc); 630 if (type != 0) { 631 push(type); 632 if (type == LONG || type == DOUBLE) { 633 push(TOP); 634 } 635 } 636 } 637 638 /** 639 * Returns the int encoding of the given type. 640 * 641 * @param cw the ClassWriter to which this label belongs. 642 * @param desc a type descriptor. 643 * @return the int encoding of the given type. 644 */ 645 private static int type(final ClassWriter cw, final String desc) { 646 String t; 647 int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0; 648 switch (desc.charAt(index)) { 649 case 'V': 650 return 0; 651 case 'Z': 652 case 'C': 653 case 'B': 654 case 'S': 655 case 'I': 656 return INTEGER; 657 case 'F': 658 return FLOAT; 659 case 'J': 660 return LONG; 661 case 'D': 662 return DOUBLE; 707 } 708 } 709 710 /** 711 * Pops a type from the output frame stack and returns its value. 712 * 713 * @return the type that has been popped from the output frame stack. 714 */ 715 private int pop() { 716 if (outputStackTop > 0) { 717 return outputStack[--outputStackTop]; 718 } else { 719 // if the output frame stack is empty, pops from the input stack 720 return STACK | -(--owner.inputStackTop); 721 } 722 } 723 724 /** 725 * Pops the given number of types from the output frame stack. 726 * 727 * @param elements the number of types that must be popped. 728 */ 729 private void pop(final int elements) { 730 if (outputStackTop >= elements) { 731 outputStackTop -= elements; 732 } else { 733 // if the number of elements to be popped is greater than the number 734 // of elements in the output stack, clear it, and pops the remaining 735 // elements from the input stack. 736 owner.inputStackTop -= elements - outputStackTop; 737 outputStackTop = 0; 738 } 739 } 740 741 /** 742 * Pops a type from the output frame stack. 743 * 744 * @param desc the descriptor of the type to be popped. Can also be a method 745 * descriptor (in this case this method pops the types corresponding 746 * to the method arguments). 747 */ 748 private void pop(final String desc) { 749 char c = desc.charAt(0); 750 if (c == '(') { 751 pop((Type.getArgumentsAndReturnSizes(desc) >> 2) - 1); 752 } else if (c == 'J' || c == 'D') { 753 pop(2); 754 } else { 755 pop(1); 756 } 757 } 758 759 /** 760 * Adds a new type to the list of types on which a constructor is invoked in 761 * the basic block. 762 * 763 * @param var a type on a which a constructor is invoked. 764 */ 765 private void init(final int var) { 766 // creates and/or resizes the initializations array if necessary 767 if (initializations == null) { 768 initializations = new int[2]; 769 } 770 int n = initializations.length; 771 if (initializationCount >= n) { 772 int[] t = new int[Math.max(initializationCount + 1, 2 * n)]; 773 System.arraycopy(initializations, 0, t, 0, n); 774 initializations = t; 775 } 776 // stores the type to be initialized 777 initializations[initializationCount++] = var; 778 } 779 780 /** 781 * Replaces the given type with the appropriate type if it is one of the 782 * types on which a constructor is invoked in the basic block. 783 * 784 * @param cw the ClassWriter to which this label belongs. 785 * @param t a type 786 * @return t or, if t is one of the types on which a constructor is invoked 787 * in the basic block, the type corresponding to this constructor. 788 */ 789 private int init(final ClassWriter cw, final int t) { 790 int s; 791 if (t == UNINITIALIZED_THIS) { 792 s = OBJECT | cw.addType(cw.thisName); 793 } else if ((t & (DIM | BASE_KIND)) == UNINITIALIZED) { 794 String type = cw.typeTable[t & BASE_VALUE].strVal1; 795 s = OBJECT | cw.addType(type); 796 } else { 797 return t; 798 } 799 for (int j = 0; j < initializationCount; ++j) { 800 int u = initializations[j]; 801 int dim = u & DIM; 802 int kind = u & KIND; 803 if (kind == LOCAL) { 804 u = dim + inputLocals[u & VALUE]; 805 } else if (kind == STACK) { 806 u = dim + inputStack[inputStack.length - (u & VALUE)]; 807 } 808 if (t == u) { 809 return s; 810 } 811 } 812 return t; 813 } 814 815 /** 816 * Initializes the input frame of the first basic block from the method 817 * descriptor. 818 * 819 * @param cw the ClassWriter to which this label belongs. 820 * @param access the access flags of the method to which this label belongs. 821 * @param args the formal parameter types of this method. 822 * @param maxLocals the maximum number of local variables of this method. 823 */ 824 void initInputFrame( 825 final ClassWriter cw, 826 final int access, 827 final Type[] args, 828 final int maxLocals) 829 { 830 inputLocals = new int[maxLocals]; 831 inputStack = new int[0]; 832 int i = 0; 833 if ((access & Opcodes.ACC_STATIC) == 0) { 834 if ((access & MethodWriter.ACC_CONSTRUCTOR) == 0) { 835 inputLocals[i++] = OBJECT | cw.addType(cw.thisName); 836 } else { 837 inputLocals[i++] = UNINITIALIZED_THIS; 838 } 839 } 840 for (int j = 0; j < args.length; ++j) { 841 int t = type(cw, args[j].getDescriptor()); 842 inputLocals[i++] = t; 843 if (t == LONG || t == DOUBLE) { 844 inputLocals[i++] = TOP; 845 } 846 } 847 while (i < maxLocals) { 848 inputLocals[i++] = TOP; 849 } 850 } 851 852 /** 853 * Simulates the action of the given instruction on the output stack frame. 854 * 855 * @param opcode the opcode of the instruction. 856 * @param arg the operand of the instruction, if any. 857 * @param cw the class writer to which this label belongs. 858 * @param item the operand of the instructions, if any. 859 */ 860 void execute( 861 final int opcode, 862 final int arg, 863 final ClassWriter cw, 864 final Item item) 865 { 866 int t1, t2, t3, t4; 867 switch (opcode) { 868 case Opcodes.NOP: 869 case Opcodes.INEG: 870 case Opcodes.LNEG: 871 case Opcodes.FNEG: 872 case Opcodes.DNEG: 873 case Opcodes.I2B: 874 case Opcodes.I2C: 875 case Opcodes.I2S: 876 case Opcodes.GOTO: 877 case Opcodes.RETURN: 878 break; 879 case Opcodes.ACONST_NULL: 880 push(NULL); 881 break; 882 case Opcodes.ICONST_M1: 883 case Opcodes.ICONST_0: 884 case Opcodes.ICONST_1: 885 case Opcodes.ICONST_2: 1174 case Opcodes.I2D: 1175 case Opcodes.F2D: 1176 pop(1); 1177 push(DOUBLE); 1178 push(TOP); 1179 break; 1180 case Opcodes.F2I: 1181 case Opcodes.ARRAYLENGTH: 1182 case Opcodes.INSTANCEOF: 1183 pop(1); 1184 push(INTEGER); 1185 break; 1186 case Opcodes.LCMP: 1187 case Opcodes.DCMPL: 1188 case Opcodes.DCMPG: 1189 pop(4); 1190 push(INTEGER); 1191 break; 1192 case Opcodes.JSR: 1193 case Opcodes.RET: 1194 throw new RuntimeException("JSR/RET are not supported with computeFrames option"); 1195 case Opcodes.GETSTATIC: 1196 push(cw, item.strVal3); 1197 break; 1198 case Opcodes.PUTSTATIC: 1199 pop(item.strVal3); 1200 break; 1201 case Opcodes.GETFIELD: 1202 pop(1); 1203 push(cw, item.strVal3); 1204 break; 1205 case Opcodes.PUTFIELD: 1206 pop(item.strVal3); 1207 pop(); 1208 break; 1209 case Opcodes.INVOKEVIRTUAL: 1210 case Opcodes.INVOKESPECIAL: 1211 case Opcodes.INVOKESTATIC: 1212 case Opcodes.INVOKEINTERFACE: 1213 pop(item.strVal3); 1214 if (opcode != Opcodes.INVOKESTATIC) { 1215 t1 = pop(); 1216 if (opcode == Opcodes.INVOKESPECIAL 1217 && item.strVal2.charAt(0) == '<') 1218 { 1219 init(t1); 1220 } 1221 } 1222 push(cw, item.strVal3); 1223 break; 1224 case Opcodes.INVOKEDYNAMIC: 1225 pop(item.strVal2); 1226 push(cw, item.strVal2); 1227 break; 1228 case Opcodes.NEW: 1229 push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg)); 1230 break; 1231 case Opcodes.NEWARRAY: 1232 pop(); 1233 switch (arg) { 1234 case Opcodes.T_BOOLEAN: 1235 push(ARRAY_OF | BOOLEAN); 1236 break; 1237 case Opcodes.T_CHAR: 1238 push(ARRAY_OF | CHAR); 1272 pop(); 1273 if (s.charAt(0) == '[') { 1274 push(cw, s); 1275 } else { 1276 push(OBJECT | cw.addType(s)); 1277 } 1278 break; 1279 // case Opcodes.MULTIANEWARRAY: 1280 default: 1281 pop(arg); 1282 push(cw, item.strVal1); 1283 break; 1284 } 1285 } 1286 1287 /** 1288 * Merges the input frame of the given basic block with the input and output 1289 * frames of this basic block. Returns <tt>true</tt> if the input frame of 1290 * the given label has been changed by this operation. 1291 * 1292 * @param cw the ClassWriter to which this label belongs. 1293 * @param frame the basic block whose input frame must be updated. 1294 * @param edge the kind of the {@link Edge} between this label and 'label'. 1295 * See {@link Edge#info}. 1296 * @return <tt>true</tt> if the input frame of the given label has been 1297 * changed by this operation. 1298 */ 1299 boolean merge(final ClassWriter cw, final Frame frame, final int edge) { 1300 boolean changed = false; 1301 int i, s, dim, kind, t; 1302 1303 int nLocal = inputLocals.length; 1304 int nStack = inputStack.length; 1305 if (frame.inputLocals == null) { 1306 frame.inputLocals = new int[nLocal]; 1307 changed = true; 1308 } 1309 1310 for (i = 0; i < nLocal; ++i) { 1311 if (outputLocals != null && i < outputLocals.length) { 1312 s = outputLocals[i]; 1313 if (s == 0) { 1314 t = inputLocals[i]; 1315 } else { 1316 dim = s & DIM; 1317 kind = s & KIND; 1318 if (kind == BASE) { 1319 t = s; 1320 } else { 1321 if (kind == LOCAL) { 1322 t = dim + inputLocals[s & VALUE]; 1323 } else { 1324 t = dim + inputStack[nStack - (s & VALUE)]; 1325 } 1326 if ((s & TOP_IF_LONG_OR_DOUBLE) != 0 && (t == LONG || t == DOUBLE)) { 1327 t = TOP; 1328 } 1329 } 1330 } 1331 } else { 1332 t = inputLocals[i]; 1333 } 1334 if (initializations != null) { 1335 t = init(cw, t); 1336 } 1337 changed |= merge(cw, t, frame.inputLocals, i); 1338 } 1339 1340 if (edge > 0) { 1341 for (i = 0; i < nLocal; ++i) { 1342 t = inputLocals[i]; 1343 changed |= merge(cw, t, frame.inputLocals, i); 1344 } 1345 if (frame.inputStack == null) { 1346 frame.inputStack = new int[1]; 1358 1359 for (i = 0; i < nInputStack; ++i) { 1360 t = inputStack[i]; 1361 if (initializations != null) { 1362 t = init(cw, t); 1363 } 1364 changed |= merge(cw, t, frame.inputStack, i); 1365 } 1366 for (i = 0; i < outputStackTop; ++i) { 1367 s = outputStack[i]; 1368 dim = s & DIM; 1369 kind = s & KIND; 1370 if (kind == BASE) { 1371 t = s; 1372 } else { 1373 if (kind == LOCAL) { 1374 t = dim + inputLocals[s & VALUE]; 1375 } else { 1376 t = dim + inputStack[nStack - (s & VALUE)]; 1377 } 1378 if ((s & TOP_IF_LONG_OR_DOUBLE) != 0 && (t == LONG || t == DOUBLE)) { 1379 t = TOP; 1380 } 1381 } 1382 if (initializations != null) { 1383 t = init(cw, t); 1384 } 1385 changed |= merge(cw, t, frame.inputStack, nInputStack + i); 1386 } 1387 return changed; 1388 } 1389 1390 /** 1391 * Merges the type at the given index in the given type array with the given 1392 * type. Returns <tt>true</tt> if the type array has been modified by this 1393 * operation. 1394 * 1395 * @param cw the ClassWriter to which this label belongs. 1396 * @param t the type with which the type array element must be merged. 1397 * @param types an array of types. 1398 * @param index the index of the type that must be merged in 'types'. 1399 * @return <tt>true</tt> if the type array has been modified by this 1400 * operation. 1401 */ 1402 private static boolean merge( 1403 final ClassWriter cw, 1404 int t, 1405 final int[] types, 1406 final int index) 1407 { 1408 int u = types[index]; 1409 if (u == t) { 1410 // if the types are equal, merge(u,t)=u, so there is no change 1411 return false; 1412 } 1413 if ((t & ~DIM) == NULL) { 1414 if (u == NULL) { 1415 return false; 1416 } 1417 t = NULL; 1418 } 1419 if (u == 0) { 1420 // if types[index] has never been assigned, merge(u,t)=t 1421 types[index] = t; 1422 return true; 1423 } 1424 int v; 1425 if ((u & BASE_KIND) == OBJECT || (u & DIM) != 0) { 1426 // if u is a reference type of any dimension 1427 if (t == NULL) { | 92 * This explains the rather complicated type format used in output frames. 93 * 94 * This format is the following: DIM KIND VALUE (4, 4 and 24 bits). DIM is a 95 * signed number of array dimensions (from -8 to 7). KIND is either BASE, 96 * LOCAL or STACK. BASE is used for types that are not relative to the input 97 * frame. LOCAL is used for types that are relative to the input local 98 * variable types. STACK is used for types that are relative to the input 99 * stack types. VALUE depends on KIND. For LOCAL types, it is an index in 100 * the input local variable types. For STACK types, it is a position 101 * relatively to the top of input frame stack. For BASE types, it is either 102 * one of the constants defined in FrameVisitor, or for OBJECT and 103 * UNINITIALIZED types, a tag and an index in the type table. 104 * 105 * Output frames can contain types of any kind and with a positive or 106 * negative dimension (and even unassigned types, represented by 0 - which 107 * does not correspond to any valid type value). Input frames can only 108 * contain BASE types of positive or null dimension. In all cases the type 109 * table contains only internal type names (array type descriptors are 110 * forbidden - dimensions must be represented through the DIM field). 111 * 112 * The LONG and DOUBLE types are always represented by using two slots (LONG 113 * + TOP or DOUBLE + TOP), for local variable types as well as in the 114 * operand stack. This is necessary to be able to simulate DUPx_y 115 * instructions, whose effect would be dependent on the actual type values 116 * if types were always represented by a single slot in the stack (and this 117 * is not possible, since actual type values are not always known - cf LOCAL 118 * and STACK type kinds). 119 */ 120 121 /** 122 * Mask to get the dimension of a frame type. This dimension is a signed 123 * integer between -8 and 7. 124 */ 125 static final int DIM = 0xF0000000; 126 127 /** 128 * Constant to be added to a type to get a type with one more dimension. 129 */ 130 static final int ARRAY_OF = 0x10000000; 131 132 /** 133 * Constant to be added to a type to get a type with one less dimension. 134 */ 135 static final int ELEMENT_OF = 0xF0000000; 136 137 /** 138 * Mask to get the kind of a frame type. 139 * 140 * @see #BASE 141 * @see #LOCAL 142 * @see #STACK 143 */ 144 static final int KIND = 0xF000000; 145 146 /** 147 * Flag used for LOCAL and STACK types. Indicates that if this type happens 148 * to be a long or double type (during the computations of input frames), 149 * then it must be set to TOP because the second word of this value has been 150 * reused to store other data in the basic block. Hence the first word no 151 * longer stores a valid long or double value. 152 */ 153 static final int TOP_IF_LONG_OR_DOUBLE = 0x800000; 154 155 /** 156 * Mask to get the value of a frame type. 157 */ 158 static final int VALUE = 0x7FFFFF; 159 160 /** 161 * Mask to get the kind of base types. 162 */ 163 static final int BASE_KIND = 0xFF00000; 164 165 /** 166 * Mask to get the value of base types. 167 */ 168 static final int BASE_VALUE = 0xFFFFF; 169 170 /** 171 * Kind of the types that are not relative to an input stack map frame. 535 private int initializationCount; 536 537 /** 538 * The types that are initialized in the basic block. A constructor 539 * invocation on an UNINITIALIZED or UNINITIALIZED_THIS type must replace 540 * <i>every occurence</i> of this type in the local variables and in the 541 * operand stack. This cannot be done during the first phase of the 542 * algorithm since, during this phase, the local variables and the operand 543 * stack are not completely computed. It is therefore necessary to store the 544 * types on which constructors are invoked in the basic block, in order to 545 * do this replacement during the second phase of the algorithm, where the 546 * frames are fully computed. Note that this array can contain types that 547 * are relative to input locals or to the input stack (see below for the 548 * description of the algorithm). 549 */ 550 private int[] initializations; 551 552 /** 553 * Returns the output frame local variable type at the given index. 554 * 555 * @param local 556 * the index of the local that must be returned. 557 * @return the output frame local variable type at the given index. 558 */ 559 private int get(final int local) { 560 if (outputLocals == null || local >= outputLocals.length) { 561 // this local has never been assigned in this basic block, 562 // so it is still equal to its value in the input frame 563 return LOCAL | local; 564 } else { 565 int type = outputLocals[local]; 566 if (type == 0) { 567 // this local has never been assigned in this basic block, 568 // so it is still equal to its value in the input frame 569 type = outputLocals[local] = LOCAL | local; 570 } 571 return type; 572 } 573 } 574 575 /** 576 * Sets the output frame local variable type at the given index. 577 * 578 * @param local 579 * the index of the local that must be set. 580 * @param type 581 * the value of the local that must be set. 582 */ 583 private void set(final int local, final int type) { 584 // creates and/or resizes the output local variables array if necessary 585 if (outputLocals == null) { 586 outputLocals = new int[10]; 587 } 588 int n = outputLocals.length; 589 if (local >= n) { 590 int[] t = new int[Math.max(local + 1, 2 * n)]; 591 System.arraycopy(outputLocals, 0, t, 0, n); 592 outputLocals = t; 593 } 594 // sets the local variable 595 outputLocals[local] = type; 596 } 597 598 /** 599 * Pushes a new type onto the output frame stack. 600 * 601 * @param type 602 * the type that must be pushed. 603 */ 604 private void push(final int type) { 605 // creates and/or resizes the output stack array if necessary 606 if (outputStack == null) { 607 outputStack = new int[10]; 608 } 609 int n = outputStack.length; 610 if (outputStackTop >= n) { 611 int[] t = new int[Math.max(outputStackTop + 1, 2 * n)]; 612 System.arraycopy(outputStack, 0, t, 0, n); 613 outputStack = t; 614 } 615 // pushes the type on the output stack 616 outputStack[outputStackTop++] = type; 617 // updates the maximun height reached by the output stack, if needed 618 int top = owner.inputStackTop + outputStackTop; 619 if (top > owner.outputStackMax) { 620 owner.outputStackMax = top; 621 } 622 } 623 624 /** 625 * Pushes a new type onto the output frame stack. 626 * 627 * @param cw 628 * the ClassWriter to which this label belongs. 629 * @param desc 630 * the descriptor of the type to be pushed. Can also be a method 631 * descriptor (in this case this method pushes its return type 632 * onto the output frame stack). 633 */ 634 private void push(final ClassWriter cw, final String desc) { 635 int type = type(cw, desc); 636 if (type != 0) { 637 push(type); 638 if (type == LONG || type == DOUBLE) { 639 push(TOP); 640 } 641 } 642 } 643 644 /** 645 * Returns the int encoding of the given type. 646 * 647 * @param cw 648 * the ClassWriter to which this label belongs. 649 * @param desc 650 * a type descriptor. 651 * @return the int encoding of the given type. 652 */ 653 private static int type(final ClassWriter cw, final String desc) { 654 String t; 655 int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0; 656 switch (desc.charAt(index)) { 657 case 'V': 658 return 0; 659 case 'Z': 660 case 'C': 661 case 'B': 662 case 'S': 663 case 'I': 664 return INTEGER; 665 case 'F': 666 return FLOAT; 667 case 'J': 668 return LONG; 669 case 'D': 670 return DOUBLE; 715 } 716 } 717 718 /** 719 * Pops a type from the output frame stack and returns its value. 720 * 721 * @return the type that has been popped from the output frame stack. 722 */ 723 private int pop() { 724 if (outputStackTop > 0) { 725 return outputStack[--outputStackTop]; 726 } else { 727 // if the output frame stack is empty, pops from the input stack 728 return STACK | -(--owner.inputStackTop); 729 } 730 } 731 732 /** 733 * Pops the given number of types from the output frame stack. 734 * 735 * @param elements 736 * the number of types that must be popped. 737 */ 738 private void pop(final int elements) { 739 if (outputStackTop >= elements) { 740 outputStackTop -= elements; 741 } else { 742 // if the number of elements to be popped is greater than the number 743 // of elements in the output stack, clear it, and pops the remaining 744 // elements from the input stack. 745 owner.inputStackTop -= elements - outputStackTop; 746 outputStackTop = 0; 747 } 748 } 749 750 /** 751 * Pops a type from the output frame stack. 752 * 753 * @param desc 754 * the descriptor of the type to be popped. Can also be a method 755 * descriptor (in this case this method pops the types 756 * corresponding to the method arguments). 757 */ 758 private void pop(final String desc) { 759 char c = desc.charAt(0); 760 if (c == '(') { 761 pop((Type.getArgumentsAndReturnSizes(desc) >> 2) - 1); 762 } else if (c == 'J' || c == 'D') { 763 pop(2); 764 } else { 765 pop(1); 766 } 767 } 768 769 /** 770 * Adds a new type to the list of types on which a constructor is invoked in 771 * the basic block. 772 * 773 * @param var 774 * a type on a which a constructor is invoked. 775 */ 776 private void init(final int var) { 777 // creates and/or resizes the initializations array if necessary 778 if (initializations == null) { 779 initializations = new int[2]; 780 } 781 int n = initializations.length; 782 if (initializationCount >= n) { 783 int[] t = new int[Math.max(initializationCount + 1, 2 * n)]; 784 System.arraycopy(initializations, 0, t, 0, n); 785 initializations = t; 786 } 787 // stores the type to be initialized 788 initializations[initializationCount++] = var; 789 } 790 791 /** 792 * Replaces the given type with the appropriate type if it is one of the 793 * types on which a constructor is invoked in the basic block. 794 * 795 * @param cw 796 * the ClassWriter to which this label belongs. 797 * @param t 798 * a type 799 * @return t or, if t is one of the types on which a constructor is invoked 800 * in the basic block, the type corresponding to this constructor. 801 */ 802 private int init(final ClassWriter cw, final int t) { 803 int s; 804 if (t == UNINITIALIZED_THIS) { 805 s = OBJECT | cw.addType(cw.thisName); 806 } else if ((t & (DIM | BASE_KIND)) == UNINITIALIZED) { 807 String type = cw.typeTable[t & BASE_VALUE].strVal1; 808 s = OBJECT | cw.addType(type); 809 } else { 810 return t; 811 } 812 for (int j = 0; j < initializationCount; ++j) { 813 int u = initializations[j]; 814 int dim = u & DIM; 815 int kind = u & KIND; 816 if (kind == LOCAL) { 817 u = dim + inputLocals[u & VALUE]; 818 } else if (kind == STACK) { 819 u = dim + inputStack[inputStack.length - (u & VALUE)]; 820 } 821 if (t == u) { 822 return s; 823 } 824 } 825 return t; 826 } 827 828 /** 829 * Initializes the input frame of the first basic block from the method 830 * descriptor. 831 * 832 * @param cw 833 * the ClassWriter to which this label belongs. 834 * @param access 835 * the access flags of the method to which this label belongs. 836 * @param args 837 * the formal parameter types of this method. 838 * @param maxLocals 839 * the maximum number of local variables of this method. 840 */ 841 void initInputFrame(final ClassWriter cw, final int access, 842 final Type[] args, final int maxLocals) { 843 inputLocals = new int[maxLocals]; 844 inputStack = new int[0]; 845 int i = 0; 846 if ((access & Opcodes.ACC_STATIC) == 0) { 847 if ((access & MethodWriter.ACC_CONSTRUCTOR) == 0) { 848 inputLocals[i++] = OBJECT | cw.addType(cw.thisName); 849 } else { 850 inputLocals[i++] = UNINITIALIZED_THIS; 851 } 852 } 853 for (int j = 0; j < args.length; ++j) { 854 int t = type(cw, args[j].getDescriptor()); 855 inputLocals[i++] = t; 856 if (t == LONG || t == DOUBLE) { 857 inputLocals[i++] = TOP; 858 } 859 } 860 while (i < maxLocals) { 861 inputLocals[i++] = TOP; 862 } 863 } 864 865 /** 866 * Simulates the action of the given instruction on the output stack frame. 867 * 868 * @param opcode 869 * the opcode of the instruction. 870 * @param arg 871 * the operand of the instruction, if any. 872 * @param cw 873 * the class writer to which this label belongs. 874 * @param item 875 * the operand of the instructions, if any. 876 */ 877 void execute(final int opcode, final int arg, final ClassWriter cw, 878 final Item item) { 879 int t1, t2, t3, t4; 880 switch (opcode) { 881 case Opcodes.NOP: 882 case Opcodes.INEG: 883 case Opcodes.LNEG: 884 case Opcodes.FNEG: 885 case Opcodes.DNEG: 886 case Opcodes.I2B: 887 case Opcodes.I2C: 888 case Opcodes.I2S: 889 case Opcodes.GOTO: 890 case Opcodes.RETURN: 891 break; 892 case Opcodes.ACONST_NULL: 893 push(NULL); 894 break; 895 case Opcodes.ICONST_M1: 896 case Opcodes.ICONST_0: 897 case Opcodes.ICONST_1: 898 case Opcodes.ICONST_2: 1187 case Opcodes.I2D: 1188 case Opcodes.F2D: 1189 pop(1); 1190 push(DOUBLE); 1191 push(TOP); 1192 break; 1193 case Opcodes.F2I: 1194 case Opcodes.ARRAYLENGTH: 1195 case Opcodes.INSTANCEOF: 1196 pop(1); 1197 push(INTEGER); 1198 break; 1199 case Opcodes.LCMP: 1200 case Opcodes.DCMPL: 1201 case Opcodes.DCMPG: 1202 pop(4); 1203 push(INTEGER); 1204 break; 1205 case Opcodes.JSR: 1206 case Opcodes.RET: 1207 throw new RuntimeException( 1208 "JSR/RET are not supported with computeFrames option"); 1209 case Opcodes.GETSTATIC: 1210 push(cw, item.strVal3); 1211 break; 1212 case Opcodes.PUTSTATIC: 1213 pop(item.strVal3); 1214 break; 1215 case Opcodes.GETFIELD: 1216 pop(1); 1217 push(cw, item.strVal3); 1218 break; 1219 case Opcodes.PUTFIELD: 1220 pop(item.strVal3); 1221 pop(); 1222 break; 1223 case Opcodes.INVOKEVIRTUAL: 1224 case Opcodes.INVOKESPECIAL: 1225 case Opcodes.INVOKESTATIC: 1226 case Opcodes.INVOKEINTERFACE: 1227 pop(item.strVal3); 1228 if (opcode != Opcodes.INVOKESTATIC) { 1229 t1 = pop(); 1230 if (opcode == Opcodes.INVOKESPECIAL 1231 && item.strVal2.charAt(0) == '<') { 1232 init(t1); 1233 } 1234 } 1235 push(cw, item.strVal3); 1236 break; 1237 case Opcodes.INVOKEDYNAMIC: 1238 pop(item.strVal2); 1239 push(cw, item.strVal2); 1240 break; 1241 case Opcodes.NEW: 1242 push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg)); 1243 break; 1244 case Opcodes.NEWARRAY: 1245 pop(); 1246 switch (arg) { 1247 case Opcodes.T_BOOLEAN: 1248 push(ARRAY_OF | BOOLEAN); 1249 break; 1250 case Opcodes.T_CHAR: 1251 push(ARRAY_OF | CHAR); 1285 pop(); 1286 if (s.charAt(0) == '[') { 1287 push(cw, s); 1288 } else { 1289 push(OBJECT | cw.addType(s)); 1290 } 1291 break; 1292 // case Opcodes.MULTIANEWARRAY: 1293 default: 1294 pop(arg); 1295 push(cw, item.strVal1); 1296 break; 1297 } 1298 } 1299 1300 /** 1301 * Merges the input frame of the given basic block with the input and output 1302 * frames of this basic block. Returns <tt>true</tt> if the input frame of 1303 * the given label has been changed by this operation. 1304 * 1305 * @param cw 1306 * the ClassWriter to which this label belongs. 1307 * @param frame 1308 * the basic block whose input frame must be updated. 1309 * @param edge 1310 * the kind of the {@link Edge} between this label and 'label'. 1311 * See {@link Edge#info}. 1312 * @return <tt>true</tt> if the input frame of the given label has been 1313 * changed by this operation. 1314 */ 1315 boolean merge(final ClassWriter cw, final Frame frame, final int edge) { 1316 boolean changed = false; 1317 int i, s, dim, kind, t; 1318 1319 int nLocal = inputLocals.length; 1320 int nStack = inputStack.length; 1321 if (frame.inputLocals == null) { 1322 frame.inputLocals = new int[nLocal]; 1323 changed = true; 1324 } 1325 1326 for (i = 0; i < nLocal; ++i) { 1327 if (outputLocals != null && i < outputLocals.length) { 1328 s = outputLocals[i]; 1329 if (s == 0) { 1330 t = inputLocals[i]; 1331 } else { 1332 dim = s & DIM; 1333 kind = s & KIND; 1334 if (kind == BASE) { 1335 t = s; 1336 } else { 1337 if (kind == LOCAL) { 1338 t = dim + inputLocals[s & VALUE]; 1339 } else { 1340 t = dim + inputStack[nStack - (s & VALUE)]; 1341 } 1342 if ((s & TOP_IF_LONG_OR_DOUBLE) != 0 1343 && (t == LONG || t == DOUBLE)) { 1344 t = TOP; 1345 } 1346 } 1347 } 1348 } else { 1349 t = inputLocals[i]; 1350 } 1351 if (initializations != null) { 1352 t = init(cw, t); 1353 } 1354 changed |= merge(cw, t, frame.inputLocals, i); 1355 } 1356 1357 if (edge > 0) { 1358 for (i = 0; i < nLocal; ++i) { 1359 t = inputLocals[i]; 1360 changed |= merge(cw, t, frame.inputLocals, i); 1361 } 1362 if (frame.inputStack == null) { 1363 frame.inputStack = new int[1]; 1375 1376 for (i = 0; i < nInputStack; ++i) { 1377 t = inputStack[i]; 1378 if (initializations != null) { 1379 t = init(cw, t); 1380 } 1381 changed |= merge(cw, t, frame.inputStack, i); 1382 } 1383 for (i = 0; i < outputStackTop; ++i) { 1384 s = outputStack[i]; 1385 dim = s & DIM; 1386 kind = s & KIND; 1387 if (kind == BASE) { 1388 t = s; 1389 } else { 1390 if (kind == LOCAL) { 1391 t = dim + inputLocals[s & VALUE]; 1392 } else { 1393 t = dim + inputStack[nStack - (s & VALUE)]; 1394 } 1395 if ((s & TOP_IF_LONG_OR_DOUBLE) != 0 1396 && (t == LONG || t == DOUBLE)) { 1397 t = TOP; 1398 } 1399 } 1400 if (initializations != null) { 1401 t = init(cw, t); 1402 } 1403 changed |= merge(cw, t, frame.inputStack, nInputStack + i); 1404 } 1405 return changed; 1406 } 1407 1408 /** 1409 * Merges the type at the given index in the given type array with the given 1410 * type. Returns <tt>true</tt> if the type array has been modified by this 1411 * operation. 1412 * 1413 * @param cw 1414 * the ClassWriter to which this label belongs. 1415 * @param t 1416 * the type with which the type array element must be merged. 1417 * @param types 1418 * an array of types. 1419 * @param index 1420 * the index of the type that must be merged in 'types'. 1421 * @return <tt>true</tt> if the type array has been modified by this 1422 * operation. 1423 */ 1424 private static boolean merge(final ClassWriter cw, int t, 1425 final int[] types, final int index) { 1426 int u = types[index]; 1427 if (u == t) { 1428 // if the types are equal, merge(u,t)=u, so there is no change 1429 return false; 1430 } 1431 if ((t & ~DIM) == NULL) { 1432 if (u == NULL) { 1433 return false; 1434 } 1435 t = NULL; 1436 } 1437 if (u == 0) { 1438 // if types[index] has never been assigned, merge(u,t)=t 1439 types[index] = t; 1440 return true; 1441 } 1442 int v; 1443 if ((u & BASE_KIND) == OBJECT || (u & DIM) != 0) { 1444 // if u is a reference type of any dimension 1445 if (t == NULL) { |