0001: /***
0002: * ASM: a very small and fast Java bytecode manipulation framework
0003: * Copyright (c) 2000-2005 INRIA, France Telecom
0004: * All rights reserved.
0005: *
0006: * Redistribution and use in source and binary forms, with or without
0007: * modification, are permitted provided that the following conditions
0008: * are met:
0009: * 1. Redistributions of source code must retain the above copyright
0010: * notice, this list of conditions and the following disclaimer.
0011: * 2. Redistributions in binary form must reproduce the above copyright
0012: * notice, this list of conditions and the following disclaimer in the
0013: * documentation and/or other materials provided with the distribution.
0014: * 3. Neither the name of the copyright holders nor the names of its
0015: * contributors may be used to endorse or promote products derived from
0016: * this software without specific prior written permission.
0017: *
0018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0021: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0022: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0023: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0024: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0025: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0026: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0027: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
0028: * THE POSSIBILITY OF SUCH DAMAGE.
0029: */package com.tc.asm;
0030:
0031: /**
0032: * Information about the input and output stack map frames of a basic block.
0033: *
0034: * @author Eric Bruneton
0035: */
0036: final class Frame {
0037:
0038: /*
0039: * Frames are computed in a two steps process: during the visit of each
0040: * instruction, the state of the frame at the end of current basic block is
0041: * updated by simulating the action of the instruction on the previous state
0042: * of this so called "output frame". In visitMaxs, a fix point algorithm is
0043: * used to compute the "input frame" of each basic block, i.e. the stack map
0044: * frame at the begining of the basic block, starting from the input frame
0045: * of the first basic block (which is computed from the method descriptor),
0046: * and by using the previously computed output frames to compute the input
0047: * state of the other blocks.
0048: *
0049: * All output and input frames are stored as arrays of integers. Reference
0050: * and array types are represented by an index into a type table (which is
0051: * not the same as the constant pool of the class, in order to avoid adding
0052: * unnecessary constants in the pool - not all computed frames will end up
0053: * being stored in the stack map table). This allows very fast type
0054: * comparisons.
0055: *
0056: * Output stack map frames are computed relatively to the input frame of the
0057: * basic block, which is not yet known when output frames are computed. It
0058: * is therefore necessary to be able to represent abstract types such as
0059: * "the type at position x in the input frame locals" or "the type at
0060: * position x from the top of the input frame stack" or even "the type at
0061: * position x in the input frame, with y more (or less) array dimensions".
0062: * This explains the rather complicated type format used in output frames.
0063: *
0064: * This format is the following: DIM KIND VALUE (4, 4 and 24 bits). DIM is a
0065: * signed number of array dimensions (from -8 to 7). KIND is either BASE,
0066: * LOCAL or STACK. BASE is used for types that are not relative to the input
0067: * frame. LOCAL is used for types that are relative to the input local
0068: * variable types. STACK is used for types that are relative to the input
0069: * stack types. VALUE depends on KIND. For LOCAL types, it is an index in
0070: * the input local variable types. For STACK types, it is a position
0071: * relatively to the top of input frame stack. For BASE types, it is either
0072: * one of the constants defined in FrameVisitor, or for OBJECT and
0073: * UNINITIALIZED types, a tag and an index in the type table.
0074: *
0075: * Output frames can contain types of any kind and with a positive or
0076: * negative dimension (and even unassigned types, represented by 0 - which
0077: * does not correspond to any valid type value). Input frames can only
0078: * contain BASE types of positive or null dimension. In all cases the type
0079: * table contains only internal type names (array type descriptors are
0080: * forbidden - dimensions must be represented through the DIM field).
0081: *
0082: * The LONG and DOUBLE types are always represented by using two slots (LONG +
0083: * TOP or DOUBLE + TOP), for local variable types as well as in the operand
0084: * stack. This is necessary to be able to simulate DUPx_y instructions,
0085: * whose effect would be dependent on the actual type values if types were
0086: * always represented by a single slot in the stack (and this is not
0087: * possible, since actual type values are not always known - cf LOCAL and
0088: * STACK type kinds).
0089: */
0090:
0091: /**
0092: * Mask to get the dimension of a frame type. This dimension is a signed
0093: * integer between -8 and 7.
0094: */
0095: final static int DIM = 0xF0000000;
0096:
0097: /**
0098: * Constant to be added to a type to get a type with one more dimension.
0099: */
0100: final static int ARRAY_OF = 0x10000000;
0101:
0102: /**
0103: * Constant to be added to a type to get a type with one less dimension.
0104: */
0105: final static int ELEMENT_OF = 0xF0000000;
0106:
0107: /**
0108: * Mask to get the kind of a frame type.
0109: *
0110: * @see #BASE
0111: * @see #LOCAL
0112: * @see #STACK
0113: */
0114: final static int KIND = 0xF000000;
0115:
0116: /**
0117: * Mask to get the value of a frame type.
0118: */
0119: final static int VALUE = 0xFFFFFF;
0120:
0121: /**
0122: * Mask to get the kind of base types.
0123: */
0124: final static int BASE_KIND = 0xFF00000;
0125:
0126: /**
0127: * Mask to get the value of base types.
0128: */
0129: final static int BASE_VALUE = 0xFFFFF;
0130:
0131: /**
0132: * Kind of the types that are not relative to an input stack map frame.
0133: */
0134: final static int BASE = 0x1000000;
0135:
0136: /**
0137: * Base kind of the base reference types. The BASE_VALUE of such types is an
0138: * index into the type table.
0139: */
0140: final static int OBJECT = BASE | 0x700000;
0141:
0142: /**
0143: * Base kind of the uninitialized base types. The BASE_VALUE of such types
0144: * in an index into the type table (the Item at that index contains both an
0145: * instruction offset and an internal class name).
0146: */
0147: final static int UNINITIALIZED = BASE | 0x800000;
0148:
0149: /**
0150: * Kind of the types that are relative to the local variable types of an
0151: * input stack map frame. The value of such types is a local variable index.
0152: */
0153: private final static int LOCAL = 0x2000000;
0154:
0155: /**
0156: * Kind of the the types that are relative to the stack of an input stack
0157: * map frame. The value of such types is a position relatively to the top of
0158: * this stack.
0159: */
0160: private final static int STACK = 0x3000000;
0161:
0162: /**
0163: * The TOP type. This is a BASE type.
0164: */
0165: final static int TOP = BASE | 0;
0166:
0167: /**
0168: * The BOOLEAN type. This is a BASE type mainly used for array types.
0169: */
0170: final static int BOOLEAN = BASE | 9;
0171:
0172: /**
0173: * The BYTE type. This is a BASE type mainly used for array types.
0174: */
0175: final static int BYTE = BASE | 10;
0176:
0177: /**
0178: * The CHAR type. This is a BASE type mainly used for array types.
0179: */
0180: final static int CHAR = BASE | 11;
0181:
0182: /**
0183: * The SHORT type. This is a BASE type mainly used for array types.
0184: */
0185: final static int SHORT = BASE | 12;
0186:
0187: /**
0188: * The INTEGER type. This is a BASE type.
0189: */
0190: final static int INTEGER = BASE | 1;
0191:
0192: /**
0193: * The FLOAT type. This is a BASE type.
0194: */
0195: final static int FLOAT = BASE | 2;
0196:
0197: /**
0198: * The DOUBLE type. This is a BASE type.
0199: */
0200: final static int DOUBLE = BASE | 3;
0201:
0202: /**
0203: * The LONG type. This is a BASE type.
0204: */
0205: final static int LONG = BASE | 4;
0206:
0207: /**
0208: * The NULL type. This is a BASE type.
0209: */
0210: final static int NULL = BASE | 5;
0211:
0212: /**
0213: * The UNINITIALIZED_THIS type. This is a BASE type.
0214: */
0215: final static int UNINITIALIZED_THIS = BASE | 6;
0216:
0217: /**
0218: * The stack size variation corresponding to each JVM instruction. This
0219: * stack variation is equal to the size of the values produced by an
0220: * instruction, minus the size of the values consumed by this instruction.
0221: */
0222: final static int[] SIZE;
0223:
0224: /**
0225: * Computes the stack size variation corresponding to each JVM instruction.
0226: */
0227: static {
0228: int i;
0229: int[] b = new int[202];
0230: String s = "EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDD"
0231: + "CDCDEEEEEEEEEEEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCD"
0232: + "CDCEEEEDDDDDDDCDCDCEFEFDDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFED"
0233: + "DDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE";
0234: for (i = 0; i < b.length; ++i) {
0235: b[i] = s.charAt(i) - 'E';
0236: }
0237: SIZE = b;
0238:
0239: // code to generate the above string
0240: //
0241: // int NA = 0; // not applicable (unused opcode or variable size opcode)
0242: //
0243: // b = new int[] {
0244: // 0, //NOP, // visitInsn
0245: // 1, //ACONST_NULL, // -
0246: // 1, //ICONST_M1, // -
0247: // 1, //ICONST_0, // -
0248: // 1, //ICONST_1, // -
0249: // 1, //ICONST_2, // -
0250: // 1, //ICONST_3, // -
0251: // 1, //ICONST_4, // -
0252: // 1, //ICONST_5, // -
0253: // 2, //LCONST_0, // -
0254: // 2, //LCONST_1, // -
0255: // 1, //FCONST_0, // -
0256: // 1, //FCONST_1, // -
0257: // 1, //FCONST_2, // -
0258: // 2, //DCONST_0, // -
0259: // 2, //DCONST_1, // -
0260: // 1, //BIPUSH, // visitIntInsn
0261: // 1, //SIPUSH, // -
0262: // 1, //LDC, // visitLdcInsn
0263: // NA, //LDC_W, // -
0264: // NA, //LDC2_W, // -
0265: // 1, //ILOAD, // visitVarInsn
0266: // 2, //LLOAD, // -
0267: // 1, //FLOAD, // -
0268: // 2, //DLOAD, // -
0269: // 1, //ALOAD, // -
0270: // NA, //ILOAD_0, // -
0271: // NA, //ILOAD_1, // -
0272: // NA, //ILOAD_2, // -
0273: // NA, //ILOAD_3, // -
0274: // NA, //LLOAD_0, // -
0275: // NA, //LLOAD_1, // -
0276: // NA, //LLOAD_2, // -
0277: // NA, //LLOAD_3, // -
0278: // NA, //FLOAD_0, // -
0279: // NA, //FLOAD_1, // -
0280: // NA, //FLOAD_2, // -
0281: // NA, //FLOAD_3, // -
0282: // NA, //DLOAD_0, // -
0283: // NA, //DLOAD_1, // -
0284: // NA, //DLOAD_2, // -
0285: // NA, //DLOAD_3, // -
0286: // NA, //ALOAD_0, // -
0287: // NA, //ALOAD_1, // -
0288: // NA, //ALOAD_2, // -
0289: // NA, //ALOAD_3, // -
0290: // -1, //IALOAD, // visitInsn
0291: // 0, //LALOAD, // -
0292: // -1, //FALOAD, // -
0293: // 0, //DALOAD, // -
0294: // -1, //AALOAD, // -
0295: // -1, //BALOAD, // -
0296: // -1, //CALOAD, // -
0297: // -1, //SALOAD, // -
0298: // -1, //ISTORE, // visitVarInsn
0299: // -2, //LSTORE, // -
0300: // -1, //FSTORE, // -
0301: // -2, //DSTORE, // -
0302: // -1, //ASTORE, // -
0303: // NA, //ISTORE_0, // -
0304: // NA, //ISTORE_1, // -
0305: // NA, //ISTORE_2, // -
0306: // NA, //ISTORE_3, // -
0307: // NA, //LSTORE_0, // -
0308: // NA, //LSTORE_1, // -
0309: // NA, //LSTORE_2, // -
0310: // NA, //LSTORE_3, // -
0311: // NA, //FSTORE_0, // -
0312: // NA, //FSTORE_1, // -
0313: // NA, //FSTORE_2, // -
0314: // NA, //FSTORE_3, // -
0315: // NA, //DSTORE_0, // -
0316: // NA, //DSTORE_1, // -
0317: // NA, //DSTORE_2, // -
0318: // NA, //DSTORE_3, // -
0319: // NA, //ASTORE_0, // -
0320: // NA, //ASTORE_1, // -
0321: // NA, //ASTORE_2, // -
0322: // NA, //ASTORE_3, // -
0323: // -3, //IASTORE, // visitInsn
0324: // -4, //LASTORE, // -
0325: // -3, //FASTORE, // -
0326: // -4, //DASTORE, // -
0327: // -3, //AASTORE, // -
0328: // -3, //BASTORE, // -
0329: // -3, //CASTORE, // -
0330: // -3, //SASTORE, // -
0331: // -1, //POP, // -
0332: // -2, //POP2, // -
0333: // 1, //DUP, // -
0334: // 1, //DUP_X1, // -
0335: // 1, //DUP_X2, // -
0336: // 2, //DUP2, // -
0337: // 2, //DUP2_X1, // -
0338: // 2, //DUP2_X2, // -
0339: // 0, //SWAP, // -
0340: // -1, //IADD, // -
0341: // -2, //LADD, // -
0342: // -1, //FADD, // -
0343: // -2, //DADD, // -
0344: // -1, //ISUB, // -
0345: // -2, //LSUB, // -
0346: // -1, //FSUB, // -
0347: // -2, //DSUB, // -
0348: // -1, //IMUL, // -
0349: // -2, //LMUL, // -
0350: // -1, //FMUL, // -
0351: // -2, //DMUL, // -
0352: // -1, //IDIV, // -
0353: // -2, //LDIV, // -
0354: // -1, //FDIV, // -
0355: // -2, //DDIV, // -
0356: // -1, //IREM, // -
0357: // -2, //LREM, // -
0358: // -1, //FREM, // -
0359: // -2, //DREM, // -
0360: // 0, //INEG, // -
0361: // 0, //LNEG, // -
0362: // 0, //FNEG, // -
0363: // 0, //DNEG, // -
0364: // -1, //ISHL, // -
0365: // -1, //LSHL, // -
0366: // -1, //ISHR, // -
0367: // -1, //LSHR, // -
0368: // -1, //IUSHR, // -
0369: // -1, //LUSHR, // -
0370: // -1, //IAND, // -
0371: // -2, //LAND, // -
0372: // -1, //IOR, // -
0373: // -2, //LOR, // -
0374: // -1, //IXOR, // -
0375: // -2, //LXOR, // -
0376: // 0, //IINC, // visitIincInsn
0377: // 1, //I2L, // visitInsn
0378: // 0, //I2F, // -
0379: // 1, //I2D, // -
0380: // -1, //L2I, // -
0381: // -1, //L2F, // -
0382: // 0, //L2D, // -
0383: // 0, //F2I, // -
0384: // 1, //F2L, // -
0385: // 1, //F2D, // -
0386: // -1, //D2I, // -
0387: // 0, //D2L, // -
0388: // -1, //D2F, // -
0389: // 0, //I2B, // -
0390: // 0, //I2C, // -
0391: // 0, //I2S, // -
0392: // -3, //LCMP, // -
0393: // -1, //FCMPL, // -
0394: // -1, //FCMPG, // -
0395: // -3, //DCMPL, // -
0396: // -3, //DCMPG, // -
0397: // -1, //IFEQ, // visitJumpInsn
0398: // -1, //IFNE, // -
0399: // -1, //IFLT, // -
0400: // -1, //IFGE, // -
0401: // -1, //IFGT, // -
0402: // -1, //IFLE, // -
0403: // -2, //IF_ICMPEQ, // -
0404: // -2, //IF_ICMPNE, // -
0405: // -2, //IF_ICMPLT, // -
0406: // -2, //IF_ICMPGE, // -
0407: // -2, //IF_ICMPGT, // -
0408: // -2, //IF_ICMPLE, // -
0409: // -2, //IF_ACMPEQ, // -
0410: // -2, //IF_ACMPNE, // -
0411: // 0, //GOTO, // -
0412: // 1, //JSR, // -
0413: // 0, //RET, // visitVarInsn
0414: // -1, //TABLESWITCH, // visiTableSwitchInsn
0415: // -1, //LOOKUPSWITCH, // visitLookupSwitch
0416: // -1, //IRETURN, // visitInsn
0417: // -2, //LRETURN, // -
0418: // -1, //FRETURN, // -
0419: // -2, //DRETURN, // -
0420: // -1, //ARETURN, // -
0421: // 0, //RETURN, // -
0422: // NA, //GETSTATIC, // visitFieldInsn
0423: // NA, //PUTSTATIC, // -
0424: // NA, //GETFIELD, // -
0425: // NA, //PUTFIELD, // -
0426: // NA, //INVOKEVIRTUAL, // visitMethodInsn
0427: // NA, //INVOKESPECIAL, // -
0428: // NA, //INVOKESTATIC, // -
0429: // NA, //INVOKEINTERFACE, // -
0430: // NA, //UNUSED, // NOT VISITED
0431: // 1, //NEW, // visitTypeInsn
0432: // 0, //NEWARRAY, // visitIntInsn
0433: // 0, //ANEWARRAY, // visitTypeInsn
0434: // 0, //ARRAYLENGTH, // visitInsn
0435: // NA, //ATHROW, // -
0436: // 0, //CHECKCAST, // visitTypeInsn
0437: // 0, //INSTANCEOF, // -
0438: // -1, //MONITORENTER, // visitInsn
0439: // -1, //MONITOREXIT, // -
0440: // NA, //WIDE, // NOT VISITED
0441: // NA, //MULTIANEWARRAY, // visitMultiANewArrayInsn
0442: // -1, //IFNULL, // visitJumpInsn
0443: // -1, //IFNONNULL, // -
0444: // NA, //GOTO_W, // -
0445: // NA, //JSR_W, // -
0446: // };
0447: // for (i = 0; i < b.length; ++i) {
0448: // System.err.print((char)('E' + b[i]));
0449: // }
0450: // System.err.println();
0451: }
0452:
0453: /**
0454: * The label (i.e. basic block) to which these input and output stack map
0455: * frames correspond.
0456: */
0457: Label owner;
0458:
0459: /**
0460: * The input stack map frame locals.
0461: */
0462: int[] inputLocals;
0463:
0464: /**
0465: * The input stack map frame stack.
0466: */
0467: int[] inputStack;
0468:
0469: /**
0470: * The output stack map frame locals.
0471: */
0472: private int[] outputLocals;
0473:
0474: /**
0475: * The output stack map frame stack.
0476: */
0477: private int[] outputStack;
0478:
0479: /**
0480: * Relative size of the output stack. The exact semantics of this field
0481: * depends on the algorithm that is used.
0482: *
0483: * When only the maximum stack size is computed, this field is the size of
0484: * the output stack relatively to the top of the input stack.
0485: *
0486: * When the stack map frames are completely computed, this field is the
0487: * actual number of types in {@link #outputStack}.
0488: */
0489: private int outputStackTop;
0490:
0491: /**
0492: * Number of types that are initialized in the basic block.
0493: *
0494: * @see #initializations
0495: */
0496: private int initializationCount;
0497:
0498: /**
0499: * The types that are initialized in the basic block. A constructor
0500: * invocation on an UNINITIALIZED or UNINITIALIZED_THIS type must replace
0501: * <i>every occurence</i> of this type in the local variables and in the
0502: * operand stack. This cannot be done during the first phase of the
0503: * algorithm since, during this phase, the local variables and the operand
0504: * stack are not completely computed. It is therefore necessary to store the
0505: * types on which constructors are invoked in the basic block, in order to
0506: * do this replacement during the second phase of the algorithm, where the
0507: * frames are fully computed. Note that this array can contain types that
0508: * are relative to input locals or to the input stack (see below for the
0509: * description of the algorithm).
0510: */
0511: private int[] initializations;
0512:
0513: /**
0514: * Returns the output frame local variable type at the given index.
0515: *
0516: * @param local the index of the local that must be returned.
0517: * @return the output frame local variable type at the given index.
0518: */
0519: private int get(final int local) {
0520: if (outputLocals == null || local >= outputLocals.length) {
0521: // this local has never been assigned in this basic block,
0522: // so it is still equal to its value in the input frame
0523: return LOCAL | local;
0524: } else {
0525: int type = outputLocals[local];
0526: if (type == 0) {
0527: // this local has never been assigned in this basic block,
0528: // so it is still equal to its value in the input frame
0529: type = outputLocals[local] = LOCAL | local;
0530: }
0531: return type;
0532: }
0533: }
0534:
0535: /**
0536: * Sets the output frame local variable type at the given index.
0537: *
0538: * @param local the index of the local that must be set.
0539: * @param type the value of the local that must be set.
0540: */
0541: private void set(final int local, final int type) {
0542: // creates and/or resizes the output local variables array if necessary
0543: if (outputLocals == null) {
0544: outputLocals = new int[10];
0545: }
0546: int n = outputLocals.length;
0547: if (local >= n) {
0548: int[] t = new int[Math.max(local + 1, 2 * n)];
0549: System.arraycopy(outputLocals, 0, t, 0, n);
0550: outputLocals = t;
0551: }
0552: // sets the local variable
0553: outputLocals[local] = type;
0554: }
0555:
0556: /**
0557: * Pushes a new type onto the output frame stack.
0558: *
0559: * @param type the type that must be pushed.
0560: */
0561: private void push(final int type) {
0562: // creates and/or resizes the output stack array if necessary
0563: if (outputStack == null) {
0564: outputStack = new int[10];
0565: }
0566: int n = outputStack.length;
0567: if (outputStackTop >= n) {
0568: int[] t = new int[Math.max(outputStackTop + 1, 2 * n)];
0569: System.arraycopy(outputStack, 0, t, 0, n);
0570: outputStack = t;
0571: }
0572: // pushes the type on the output stack
0573: outputStack[outputStackTop++] = type;
0574: // updates the maximun height reached by the output stack, if needed
0575: int top = owner.inputStackTop + outputStackTop;
0576: if (top > owner.outputStackMax) {
0577: owner.outputStackMax = top;
0578: }
0579: }
0580:
0581: /**
0582: * Pushes a new type onto the output frame stack.
0583: *
0584: * @param cw the ClassWriter to which this label belongs.
0585: * @param desc the descriptor of the type to be pushed. Can also be a method
0586: * descriptor (in this case this method pushes its return type onto
0587: * the output frame stack).
0588: */
0589: private void push(final ClassWriter cw, final String desc) {
0590: int type = type(cw, desc);
0591: if (type != 0) {
0592: push(type);
0593: if (type == LONG || type == DOUBLE) {
0594: push(TOP);
0595: }
0596: }
0597: }
0598:
0599: /**
0600: * Returns the int encoding of the given type.
0601: *
0602: * @param cw the ClassWriter to which this label belongs.
0603: * @param desc a type descriptor.
0604: * @return the int encoding of the given type.
0605: */
0606: private int type(final ClassWriter cw, final String desc) {
0607: String t;
0608: int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
0609: switch (desc.charAt(index)) {
0610: case 'V':
0611: return 0;
0612: case 'Z':
0613: case 'C':
0614: case 'B':
0615: case 'S':
0616: case 'I':
0617: return INTEGER;
0618: case 'F':
0619: return FLOAT;
0620: case 'J':
0621: return LONG;
0622: case 'D':
0623: return DOUBLE;
0624: case 'L':
0625: // stores the internal name, not the descriptor!
0626: t = desc.substring(index + 1, desc.length() - 1);
0627: return OBJECT | cw.addType(t);
0628: // case '[':
0629: default:
0630: // extracts the dimensions and the element type
0631: int data;
0632: int dims = index + 1;
0633: while (desc.charAt(dims) == '[') {
0634: ++dims;
0635: }
0636: switch (desc.charAt(dims)) {
0637: case 'Z':
0638: data = BOOLEAN;
0639: break;
0640: case 'C':
0641: data = CHAR;
0642: break;
0643: case 'B':
0644: data = BYTE;
0645: break;
0646: case 'S':
0647: data = SHORT;
0648: break;
0649: case 'I':
0650: data = INTEGER;
0651: break;
0652: case 'F':
0653: data = FLOAT;
0654: break;
0655: case 'J':
0656: data = LONG;
0657: break;
0658: case 'D':
0659: data = DOUBLE;
0660: break;
0661: // case 'L':
0662: default:
0663: // stores the internal name, not the descriptor
0664: t = desc.substring(dims + 1, desc.length() - 1);
0665: data = OBJECT | cw.addType(t);
0666: }
0667: return (dims - index) << 28 | data;
0668: }
0669: }
0670:
0671: /**
0672: * Pops a type from the output frame stack and returns its value.
0673: *
0674: * @return the type that has been popped from the output frame stack.
0675: */
0676: private int pop() {
0677: if (outputStackTop > 0) {
0678: return outputStack[--outputStackTop];
0679: } else {
0680: // if the output frame stack is empty, pops from the input stack
0681: return STACK | -(--owner.inputStackTop);
0682: }
0683: }
0684:
0685: /**
0686: * Pops the given number of types from the output frame stack.
0687: *
0688: * @param elements the number of types that must be popped.
0689: */
0690: private void pop(final int elements) {
0691: if (outputStackTop >= elements) {
0692: outputStackTop -= elements;
0693: } else {
0694: // if the number of elements to be popped is greater than the number
0695: // of elements in the output stack, clear it, and pops the remaining
0696: // elements from the input stack.
0697: owner.inputStackTop -= elements - outputStackTop;
0698: outputStackTop = 0;
0699: }
0700: }
0701:
0702: /**
0703: * Pops a type from the output frame stack.
0704: *
0705: * @param desc the descriptor of the type to be popped. Can also be a method
0706: * descriptor (in this case this method pops the types corresponding
0707: * to the method arguments).
0708: */
0709: private void pop(final String desc) {
0710: char c = desc.charAt(0);
0711: if (c == '(') {
0712: pop((MethodWriter.getArgumentsAndReturnSizes(desc) >> 2) - 1);
0713: } else if (c == 'J' || c == 'D') {
0714: pop(2);
0715: } else {
0716: pop(1);
0717: }
0718: }
0719:
0720: /**
0721: * Adds a new type to the list of types on which a constructor is invoked in
0722: * the basic block.
0723: *
0724: * @param var a type on a which a constructor is invoked.
0725: */
0726: private void init(final int var) {
0727: // creates and/or resizes the initializations array if necessary
0728: if (initializations == null) {
0729: initializations = new int[2];
0730: }
0731: int n = initializations.length;
0732: if (initializationCount >= n) {
0733: int[] t = new int[Math.max(initializationCount + 1, 2 * n)];
0734: System.arraycopy(initializations, 0, t, 0, n);
0735: initializations = t;
0736: }
0737: // stores the type to be initialized
0738: initializations[initializationCount++] = var;
0739: }
0740:
0741: /**
0742: * Replaces the given type with the appropriate type if it is one of the
0743: * types on which a constructor is invoked in the basic block.
0744: *
0745: * @param cw the ClassWriter to which this label belongs.
0746: * @param t a type
0747: * @return t or, if t is one of the types on which a constructor is invoked
0748: * in the basic block, the type corresponding to this constructor.
0749: */
0750: private int init(final ClassWriter cw, final int t) {
0751: int s;
0752: if (t == UNINITIALIZED_THIS) {
0753: s = OBJECT | cw.addType(cw.this Name);
0754: } else if ((t & (DIM | BASE_KIND)) == UNINITIALIZED) {
0755: String type = cw.typeTable[t & BASE_VALUE].strVal1;
0756: s = OBJECT | cw.addType(type);
0757: } else {
0758: return t;
0759: }
0760: for (int j = 0; j < initializationCount; ++j) {
0761: int u = initializations[j];
0762: int dim = u & DIM;
0763: int kind = u & KIND;
0764: if (kind == LOCAL) {
0765: u = dim + inputLocals[u & VALUE];
0766: } else if (kind == STACK) {
0767: u = dim + inputStack[inputStack.length - (u & VALUE)];
0768: }
0769: if (t == u) {
0770: return s;
0771: }
0772: }
0773: return t;
0774: }
0775:
0776: /**
0777: * Initializes the input frame of the first basic block from the method
0778: * descriptor.
0779: *
0780: * @param cw the ClassWriter to which this label belongs.
0781: * @param access the access flags of the method to which this label belongs.
0782: * @param args the formal parameter types of this method.
0783: * @param maxLocals the maximum number of local variables of this method.
0784: */
0785: void initInputFrame(final ClassWriter cw, final int access,
0786: final Type[] args, final int maxLocals) {
0787: inputLocals = new int[maxLocals];
0788: inputStack = new int[0];
0789: int i = 0;
0790: if ((access & Opcodes.ACC_STATIC) == 0) {
0791: if ((access & MethodWriter.ACC_CONSTRUCTOR) == 0) {
0792: inputLocals[i++] = OBJECT | cw.addType(cw.this Name);
0793: } else {
0794: inputLocals[i++] = UNINITIALIZED_THIS;
0795: }
0796: }
0797: for (int j = 0; j < args.length; ++j) {
0798: int t = type(cw, args[j].getDescriptor());
0799: inputLocals[i++] = t;
0800: if (t == LONG || t == DOUBLE) {
0801: inputLocals[i++] = TOP;
0802: }
0803: }
0804: while (i < maxLocals) {
0805: inputLocals[i++] = TOP;
0806: }
0807: }
0808:
0809: /**
0810: * Simulates the action of the given instruction on the output stack frame.
0811: *
0812: * @param opcode the opcode of the instruction.
0813: * @param arg the operand of the instruction, if any.
0814: * @param cw the class writer to which this label belongs.
0815: * @param item the operand of the instructions, if any.
0816: */
0817: void execute(final int opcode, final int arg, final ClassWriter cw,
0818: final Item item) {
0819: int t1, t2, t3, t4;
0820: switch (opcode) {
0821: case Opcodes.NOP:
0822: case Opcodes.INEG:
0823: case Opcodes.LNEG:
0824: case Opcodes.FNEG:
0825: case Opcodes.DNEG:
0826: case Opcodes.I2B:
0827: case Opcodes.I2C:
0828: case Opcodes.I2S:
0829: case Opcodes.GOTO:
0830: case Opcodes.RETURN:
0831: break;
0832: case Opcodes.ACONST_NULL:
0833: push(NULL);
0834: break;
0835: case Opcodes.ICONST_M1:
0836: case Opcodes.ICONST_0:
0837: case Opcodes.ICONST_1:
0838: case Opcodes.ICONST_2:
0839: case Opcodes.ICONST_3:
0840: case Opcodes.ICONST_4:
0841: case Opcodes.ICONST_5:
0842: case Opcodes.BIPUSH:
0843: case Opcodes.SIPUSH:
0844: case Opcodes.ILOAD:
0845: push(INTEGER);
0846: break;
0847: case Opcodes.LCONST_0:
0848: case Opcodes.LCONST_1:
0849: case Opcodes.LLOAD:
0850: push(LONG);
0851: push(TOP);
0852: break;
0853: case Opcodes.FCONST_0:
0854: case Opcodes.FCONST_1:
0855: case Opcodes.FCONST_2:
0856: case Opcodes.FLOAD:
0857: push(FLOAT);
0858: break;
0859: case Opcodes.DCONST_0:
0860: case Opcodes.DCONST_1:
0861: case Opcodes.DLOAD:
0862: push(DOUBLE);
0863: push(TOP);
0864: break;
0865: case Opcodes.LDC:
0866: switch (item.type) {
0867: case ClassWriter.INT:
0868: push(INTEGER);
0869: break;
0870: case ClassWriter.LONG:
0871: push(LONG);
0872: push(TOP);
0873: break;
0874: case ClassWriter.FLOAT:
0875: push(FLOAT);
0876: break;
0877: case ClassWriter.DOUBLE:
0878: push(DOUBLE);
0879: push(TOP);
0880: break;
0881: case ClassWriter.CLASS:
0882: push(OBJECT | cw.addType("java/lang/Class"));
0883: break;
0884: // case ClassWriter.STR:
0885: default:
0886: push(OBJECT | cw.addType("java/lang/String"));
0887: }
0888: break;
0889: case Opcodes.ALOAD:
0890: push(get(arg));
0891: break;
0892: case Opcodes.IALOAD:
0893: case Opcodes.BALOAD:
0894: case Opcodes.CALOAD:
0895: case Opcodes.SALOAD:
0896: pop(2);
0897: push(INTEGER);
0898: break;
0899: case Opcodes.LALOAD:
0900: case Opcodes.D2L:
0901: pop(2);
0902: push(LONG);
0903: push(TOP);
0904: break;
0905: case Opcodes.FALOAD:
0906: pop(2);
0907: push(FLOAT);
0908: break;
0909: case Opcodes.DALOAD:
0910: case Opcodes.L2D:
0911: pop(2);
0912: push(DOUBLE);
0913: push(TOP);
0914: break;
0915: case Opcodes.AALOAD:
0916: pop(1);
0917: t1 = pop();
0918: push(ELEMENT_OF + t1);
0919: break;
0920: case Opcodes.ISTORE:
0921: case Opcodes.FSTORE:
0922: case Opcodes.ASTORE:
0923: t1 = pop();
0924: set(arg, t1);
0925: if (arg > 0) {
0926: t2 = get(arg - 1);
0927: // if t2 is of kind STACK or LOCAL we cannot know its size!
0928: if (t2 == LONG || t2 == DOUBLE) {
0929: set(arg - 1, TOP);
0930: }
0931: }
0932: break;
0933: case Opcodes.LSTORE:
0934: case Opcodes.DSTORE:
0935: pop(1);
0936: t1 = pop();
0937: set(arg, t1);
0938: set(arg + 1, TOP);
0939: if (arg > 0) {
0940: t2 = get(arg - 1);
0941: // if t2 is of kind STACK or LOCAL we cannot know its size!
0942: if (t2 == LONG || t2 == DOUBLE) {
0943: set(arg - 1, TOP);
0944: }
0945: }
0946: break;
0947: case Opcodes.IASTORE:
0948: case Opcodes.BASTORE:
0949: case Opcodes.CASTORE:
0950: case Opcodes.SASTORE:
0951: case Opcodes.FASTORE:
0952: case Opcodes.AASTORE:
0953: pop(3);
0954: break;
0955: case Opcodes.LASTORE:
0956: case Opcodes.DASTORE:
0957: pop(4);
0958: break;
0959: case Opcodes.POP:
0960: case Opcodes.IFEQ:
0961: case Opcodes.IFNE:
0962: case Opcodes.IFLT:
0963: case Opcodes.IFGE:
0964: case Opcodes.IFGT:
0965: case Opcodes.IFLE:
0966: case Opcodes.IRETURN:
0967: case Opcodes.FRETURN:
0968: case Opcodes.ARETURN:
0969: case Opcodes.TABLESWITCH:
0970: case Opcodes.LOOKUPSWITCH:
0971: case Opcodes.ATHROW:
0972: case Opcodes.MONITORENTER:
0973: case Opcodes.MONITOREXIT:
0974: case Opcodes.IFNULL:
0975: case Opcodes.IFNONNULL:
0976: pop(1);
0977: break;
0978: case Opcodes.POP2:
0979: case Opcodes.IF_ICMPEQ:
0980: case Opcodes.IF_ICMPNE:
0981: case Opcodes.IF_ICMPLT:
0982: case Opcodes.IF_ICMPGE:
0983: case Opcodes.IF_ICMPGT:
0984: case Opcodes.IF_ICMPLE:
0985: case Opcodes.IF_ACMPEQ:
0986: case Opcodes.IF_ACMPNE:
0987: case Opcodes.LRETURN:
0988: case Opcodes.DRETURN:
0989: pop(2);
0990: break;
0991: case Opcodes.DUP:
0992: t1 = pop();
0993: push(t1);
0994: push(t1);
0995: break;
0996: case Opcodes.DUP_X1:
0997: t1 = pop();
0998: t2 = pop();
0999: push(t1);
1000: push(t2);
1001: push(t1);
1002: break;
1003: case Opcodes.DUP_X2:
1004: t1 = pop();
1005: t2 = pop();
1006: t3 = pop();
1007: push(t1);
1008: push(t3);
1009: push(t2);
1010: push(t1);
1011: break;
1012: case Opcodes.DUP2:
1013: t1 = pop();
1014: t2 = pop();
1015: push(t2);
1016: push(t1);
1017: push(t2);
1018: push(t1);
1019: break;
1020: case Opcodes.DUP2_X1:
1021: t1 = pop();
1022: t2 = pop();
1023: t3 = pop();
1024: push(t2);
1025: push(t1);
1026: push(t3);
1027: push(t2);
1028: push(t1);
1029: break;
1030: case Opcodes.DUP2_X2:
1031: t1 = pop();
1032: t2 = pop();
1033: t3 = pop();
1034: t4 = pop();
1035: push(t2);
1036: push(t1);
1037: push(t4);
1038: push(t3);
1039: push(t2);
1040: push(t1);
1041: break;
1042: case Opcodes.SWAP:
1043: t1 = pop();
1044: t2 = pop();
1045: push(t1);
1046: push(t2);
1047: break;
1048: case Opcodes.IADD:
1049: case Opcodes.ISUB:
1050: case Opcodes.IMUL:
1051: case Opcodes.IDIV:
1052: case Opcodes.IREM:
1053: case Opcodes.IAND:
1054: case Opcodes.IOR:
1055: case Opcodes.IXOR:
1056: case Opcodes.ISHL:
1057: case Opcodes.ISHR:
1058: case Opcodes.IUSHR:
1059: case Opcodes.L2I:
1060: case Opcodes.D2I:
1061: case Opcodes.FCMPL:
1062: case Opcodes.FCMPG:
1063: pop(2);
1064: push(INTEGER);
1065: break;
1066: case Opcodes.LADD:
1067: case Opcodes.LSUB:
1068: case Opcodes.LMUL:
1069: case Opcodes.LDIV:
1070: case Opcodes.LREM:
1071: case Opcodes.LAND:
1072: case Opcodes.LOR:
1073: case Opcodes.LXOR:
1074: pop(4);
1075: push(LONG);
1076: push(TOP);
1077: break;
1078: case Opcodes.FADD:
1079: case Opcodes.FSUB:
1080: case Opcodes.FMUL:
1081: case Opcodes.FDIV:
1082: case Opcodes.FREM:
1083: case Opcodes.L2F:
1084: case Opcodes.D2F:
1085: pop(2);
1086: push(FLOAT);
1087: break;
1088: case Opcodes.DADD:
1089: case Opcodes.DSUB:
1090: case Opcodes.DMUL:
1091: case Opcodes.DDIV:
1092: case Opcodes.DREM:
1093: pop(4);
1094: push(DOUBLE);
1095: push(TOP);
1096: break;
1097: case Opcodes.LSHL:
1098: case Opcodes.LSHR:
1099: case Opcodes.LUSHR:
1100: pop(3);
1101: push(LONG);
1102: push(TOP);
1103: break;
1104: case Opcodes.IINC:
1105: set(arg, INTEGER);
1106: break;
1107: case Opcodes.I2L:
1108: case Opcodes.F2L:
1109: pop(1);
1110: push(LONG);
1111: push(TOP);
1112: break;
1113: case Opcodes.I2F:
1114: pop(1);
1115: push(FLOAT);
1116: break;
1117: case Opcodes.I2D:
1118: case Opcodes.F2D:
1119: pop(1);
1120: push(DOUBLE);
1121: push(TOP);
1122: break;
1123: case Opcodes.F2I:
1124: case Opcodes.ARRAYLENGTH:
1125: case Opcodes.INSTANCEOF:
1126: pop(1);
1127: push(INTEGER);
1128: break;
1129: case Opcodes.LCMP:
1130: case Opcodes.DCMPL:
1131: case Opcodes.DCMPG:
1132: pop(4);
1133: push(INTEGER);
1134: break;
1135: case Opcodes.JSR:
1136: case Opcodes.RET:
1137: throw new RuntimeException(
1138: "JSR/RET are not supported with computeFrames option");
1139: case Opcodes.GETSTATIC:
1140: push(cw, item.strVal3);
1141: break;
1142: case Opcodes.PUTSTATIC:
1143: pop(item.strVal3);
1144: break;
1145: case Opcodes.GETFIELD:
1146: pop(1);
1147: push(cw, item.strVal3);
1148: break;
1149: case Opcodes.PUTFIELD:
1150: pop(item.strVal3);
1151: pop();
1152: break;
1153: case Opcodes.INVOKEVIRTUAL:
1154: case Opcodes.INVOKESPECIAL:
1155: case Opcodes.INVOKESTATIC:
1156: case Opcodes.INVOKEINTERFACE:
1157: pop(item.strVal3);
1158: if (opcode != Opcodes.INVOKESTATIC) {
1159: t1 = pop();
1160: if (opcode == Opcodes.INVOKESPECIAL
1161: && item.strVal2.charAt(0) == '<') {
1162: init(t1);
1163: }
1164: }
1165: push(cw, item.strVal3);
1166: break;
1167: case Opcodes.NEW:
1168: push(UNINITIALIZED
1169: | cw.addUninitializedType(item.strVal1, arg));
1170: break;
1171: case Opcodes.NEWARRAY:
1172: pop();
1173: switch (arg) {
1174: case Opcodes.T_BOOLEAN:
1175: push(ARRAY_OF | BOOLEAN);
1176: break;
1177: case Opcodes.T_CHAR:
1178: push(ARRAY_OF | CHAR);
1179: break;
1180: case Opcodes.T_BYTE:
1181: push(ARRAY_OF | BYTE);
1182: break;
1183: case Opcodes.T_SHORT:
1184: push(ARRAY_OF | SHORT);
1185: break;
1186: case Opcodes.T_INT:
1187: push(ARRAY_OF | INTEGER);
1188: break;
1189: case Opcodes.T_FLOAT:
1190: push(ARRAY_OF | FLOAT);
1191: break;
1192: case Opcodes.T_DOUBLE:
1193: push(ARRAY_OF | DOUBLE);
1194: break;
1195: // case Opcodes.T_LONG:
1196: default:
1197: push(ARRAY_OF | LONG);
1198: break;
1199: }
1200: break;
1201: case Opcodes.ANEWARRAY:
1202: String s = item.strVal1;
1203: pop();
1204: if (s.charAt(0) == '[') {
1205: push(cw, "[" + s);
1206: } else {
1207: push(ARRAY_OF | OBJECT | cw.addType(s));
1208: }
1209: break;
1210: case Opcodes.CHECKCAST:
1211: s = item.strVal1;
1212: pop();
1213: if (s.charAt(0) == '[') {
1214: push(cw, s);
1215: } else {
1216: push(OBJECT | cw.addType(s));
1217: }
1218: break;
1219: // case Opcodes.MULTIANEWARRAY:
1220: default:
1221: pop(arg);
1222: push(cw, item.strVal1);
1223: break;
1224: }
1225: }
1226:
1227: /**
1228: * Merges the input frame of the given basic block with the input and output
1229: * frames of this basic block. Returns <tt>true</tt> if the input frame of
1230: * the given label has been changed by this operation.
1231: *
1232: * @param cw the ClassWriter to which this label belongs.
1233: * @param frame the basic block whose input frame must be updated.
1234: * @param edge the kind of the {@link Edge} between this label and 'label'.
1235: * See {@link Edge#info}.
1236: * @return <tt>true</tt> if the input frame of the given label has been
1237: * changed by this operation.
1238: */
1239: boolean merge(final ClassWriter cw, final Frame frame,
1240: final int edge) {
1241: boolean changed = false;
1242: int i, s, dim, kind, t;
1243:
1244: int nLocal = inputLocals.length;
1245: int nStack = inputStack.length;
1246: if (frame.inputLocals == null) {
1247: frame.inputLocals = new int[nLocal];
1248: changed = true;
1249: }
1250:
1251: for (i = 0; i < nLocal; ++i) {
1252: if (outputLocals != null && i < outputLocals.length) {
1253: s = outputLocals[i];
1254: if (s == 0) {
1255: t = inputLocals[i];
1256: } else {
1257: dim = s & DIM;
1258: kind = s & KIND;
1259: if (kind == LOCAL) {
1260: t = dim + inputLocals[s & VALUE];
1261: } else if (kind == STACK) {
1262: t = dim + inputStack[nStack - (s & VALUE)];
1263: } else {
1264: t = s;
1265: }
1266: }
1267: } else {
1268: t = inputLocals[i];
1269: }
1270: if (initializations != null) {
1271: t = init(cw, t);
1272: }
1273: changed |= merge(cw, t, frame.inputLocals, i);
1274: }
1275:
1276: if (edge > 0) {
1277: for (i = 0; i < nLocal; ++i) {
1278: t = inputLocals[i];
1279: changed |= merge(cw, t, frame.inputLocals, i);
1280: }
1281: if (frame.inputStack == null) {
1282: frame.inputStack = new int[1];
1283: changed = true;
1284: }
1285: changed |= merge(cw, edge, frame.inputStack, 0);
1286: return changed;
1287: }
1288:
1289: int nInputStack = inputStack.length + owner.inputStackTop;
1290: if (frame.inputStack == null) {
1291: frame.inputStack = new int[nInputStack + outputStackTop];
1292: changed = true;
1293: }
1294:
1295: for (i = 0; i < nInputStack; ++i) {
1296: t = inputStack[i];
1297: if (initializations != null) {
1298: t = init(cw, t);
1299: }
1300: changed |= merge(cw, t, frame.inputStack, i);
1301: }
1302: for (i = 0; i < outputStackTop; ++i) {
1303: s = outputStack[i];
1304: dim = s & DIM;
1305: kind = s & KIND;
1306: if (kind == LOCAL) {
1307: t = dim + inputLocals[s & VALUE];
1308: } else if (kind == STACK) {
1309: t = dim + inputStack[nStack - (s & VALUE)];
1310: } else {
1311: t = s;
1312: }
1313: if (initializations != null) {
1314: t = init(cw, t);
1315: }
1316: changed |= merge(cw, t, frame.inputStack, nInputStack + i);
1317: }
1318: return changed;
1319: }
1320:
1321: /**
1322: * Merges the type at the given index in the given type array with the given
1323: * type. Returns <tt>true</tt> if the type array has been modified by this
1324: * operation.
1325: *
1326: * @param cw the ClassWriter to which this label belongs.
1327: * @param t the type with which the type array element must be merged.
1328: * @param types an array of types.
1329: * @param index the index of the type that must be merged in 'types'.
1330: * @return <tt>true</tt> if the type array has been modified by this
1331: * operation.
1332: */
1333: private boolean merge(final ClassWriter cw, int t,
1334: final int[] types, final int index) {
1335: int u = types[index];
1336: if (u == t) {
1337: // if the types are equal, merge(u,t)=u, so there is no change
1338: return false;
1339: }
1340: if ((t & ~DIM) == NULL) {
1341: if (u == NULL) {
1342: return false;
1343: }
1344: t = NULL;
1345: }
1346: if (u == 0) {
1347: // if types[index] has never been assigned, merge(u,t)=t
1348: types[index] = t;
1349: return true;
1350: }
1351: int v;
1352: if ((u & BASE_KIND) == OBJECT || (u & DIM) != 0) {
1353: // if u is a reference type of any dimension
1354: if (t == NULL) {
1355: // if t is the NULL type, merge(u,t)=u, so there is no change
1356: return false;
1357: } else if ((t & (DIM | BASE_KIND)) == (u & (DIM | BASE_KIND))) {
1358: if ((u & BASE_KIND) == OBJECT) {
1359: // if t is also a reference type, and if u and t have the
1360: // same dimension merge(u,t) = dim(t) | common parent of the
1361: // element types of u and t
1362: v = (t & DIM)
1363: | OBJECT
1364: | cw.getMergedType(t & BASE_VALUE, u
1365: & BASE_VALUE);
1366: } else {
1367: // if u and t are array types, but not with the same element
1368: // type, merge(u,t)=java/lang/Object
1369: v = OBJECT | cw.addType("java/lang/Object");
1370: }
1371: } else if ((t & BASE_KIND) == OBJECT || (t & DIM) != 0) {
1372: // if t is any other reference or array type,
1373: // merge(u,t)=java/lang/Object
1374: v = OBJECT | cw.addType("java/lang/Object");
1375: } else {
1376: // if t is any other type, merge(u,t)=TOP
1377: v = TOP;
1378: }
1379: } else if (u == NULL) {
1380: // if u is the NULL type, merge(u,t)=t,
1381: // or TOP if t is not a reference type
1382: v = (t & BASE_KIND) == OBJECT || (t & DIM) != 0 ? t : TOP;
1383: } else {
1384: // if u is any other type, merge(u,t)=TOP whatever t
1385: v = TOP;
1386: }
1387: if (u != v) {
1388: types[index] = v;
1389: return true;
1390: }
1391: return false;
1392: }
1393: }
|