diff src/clojure/asm/Frame.java @ 10:ef7dbbd6452c

added clojure source goodness
author Robert McIntyre <rlm@mit.edu>
date Sat, 21 Aug 2010 06:25:44 -0400
parents
children
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/clojure/asm/Frame.java	Sat Aug 21 06:25:44 2010 -0400
     1.3 @@ -0,0 +1,1506 @@
     1.4 +/***
     1.5 + * ASM: a very small and fast Java bytecode manipulation framework
     1.6 + * Copyright (c) 2000-2005 INRIA, France Telecom
     1.7 + * All rights reserved.
     1.8 + *
     1.9 + * Redistribution and use in source and binary forms, with or without
    1.10 + * modification, are permitted provided that the following conditions
    1.11 + * are met:
    1.12 + * 1. Redistributions of source code must retain the above copyright
    1.13 + *    notice, this list of conditions and the following disclaimer.
    1.14 + * 2. Redistributions in binary form must reproduce the above copyright
    1.15 + *    notice, this list of conditions and the following disclaimer in the
    1.16 + *    documentation and/or other materials provided with the distribution.
    1.17 + * 3. Neither the name of the copyright holders nor the names of its
    1.18 + *    contributors may be used to endorse or promote products derived from
    1.19 + *    this software without specific prior written permission.
    1.20 + *
    1.21 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    1.22 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    1.23 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    1.24 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
    1.25 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    1.26 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    1.27 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    1.28 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    1.29 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    1.30 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
    1.31 + * THE POSSIBILITY OF SUCH DAMAGE.
    1.32 + */
    1.33 +package clojure.asm;
    1.34 +
    1.35 +/**
    1.36 + * Information about the input and output stack map frames of a basic block.
    1.37 + *
    1.38 + * @author Eric Bruneton
    1.39 + */
    1.40 +final class Frame{
    1.41 +
    1.42 +/*
    1.43 +	 * Frames are computed in a two steps process: during the visit of each
    1.44 +	 * instruction, the state of the frame at the end of current basic block is
    1.45 +	 * updated by simulating the action of the instruction on the previous state
    1.46 +	 * of this so called "output frame". In visitMaxs, a fix point algorithm is
    1.47 +	 * used to compute the "input frame" of each basic block, i.e. the stack map
    1.48 +	 * frame at the begining of the basic block, starting from the input frame
    1.49 +	 * of the first basic block (which is computed from the method descriptor),
    1.50 +	 * and by using the previously computed output frames to compute the input
    1.51 +	 * state of the other blocks.
    1.52 +	 *
    1.53 +	 * All output and input frames are stored as arrays of integers. Reference
    1.54 +	 * and array types are represented by an index into a type table (which is
    1.55 +	 * not the same as the constant pool of the class, in order to avoid adding
    1.56 +	 * unnecessary constants in the pool - not all computed frames will end up
    1.57 +	 * being stored in the stack map table). This allows very fast type
    1.58 +	 * comparisons.
    1.59 +	 *
    1.60 +	 * Output stack map frames are computed relatively to the input frame of the
    1.61 +	 * basic block, which is not yet known when output frames are computed. It
    1.62 +	 * is therefore necessary to be able to represent abstract types such as
    1.63 +	 * "the type at position x in the input frame locals" or "the type at
    1.64 +	 * position x from the top of the input frame stack" or even "the type at
    1.65 +	 * position x in the input frame, with y more (or less) array dimensions".
    1.66 +	 * This explains the rather complicated type format used in output frames.
    1.67 +	 *
    1.68 +	 * This format is the following: DIM KIND VALUE (4, 4 and 24 bits). DIM is a
    1.69 +	 * signed number of array dimensions (from -8 to 7). KIND is either BASE,
    1.70 +	 * LOCAL or STACK. BASE is used for types that are not relative to the input
    1.71 +	 * frame. LOCAL is used for types that are relative to the input local
    1.72 +	 * variable types. STACK is used for types that are relative to the input
    1.73 +	 * stack types. VALUE depends on KIND. For LOCAL types, it is an index in
    1.74 +	 * the input local variable types. For STACK types, it is a position
    1.75 +	 * relatively to the top of input frame stack. For BASE types, it is either
    1.76 +	 * one of the constants defined in FrameVisitor, or for OBJECT and
    1.77 +	 * UNINITIALIZED types, a tag and an index in the type table.
    1.78 +	 *
    1.79 +	 * Output frames can contain types of any kind and with a positive or
    1.80 +	 * negative dimension (and even unassigned types, represented by 0 - which
    1.81 +	 * does not correspond to any valid type value). Input frames can only
    1.82 +	 * contain BASE types of positive or null dimension. In all cases the type
    1.83 +	 * table contains only internal type names (array type descriptors are
    1.84 +	 * forbidden - dimensions must be represented through the DIM field).
    1.85 +	 *
    1.86 +	 * The LONG and DOUBLE types are always represented by using two slots (LONG +
    1.87 +	 * TOP or DOUBLE + TOP), for local variable types as well as in the operand
    1.88 +	 * stack. This is necessary to be able to simulate DUPx_y instructions,
    1.89 +	 * whose effect would be dependent on the actual type values if types were
    1.90 +	 * always represented by a single slot in the stack (and this is not
    1.91 +	 * possible, since actual type values are not always known - cf LOCAL and
    1.92 +	 * STACK type kinds).
    1.93 +	 */
    1.94 +
    1.95 +/**
    1.96 + * Mask to get the dimension of a frame type. This dimension is a signed
    1.97 + * integer between -8 and 7.
    1.98 + */
    1.99 +final static int DIM = 0xF0000000;
   1.100 +
   1.101 +/**
   1.102 + * Constant to be added to a type to get a type with one more dimension.
   1.103 + */
   1.104 +final static int ARRAY_OF = 0x10000000;
   1.105 +
   1.106 +/**
   1.107 + * Constant to be added to a type to get a type with one less dimension.
   1.108 + */
   1.109 +final static int ELEMENT_OF = 0xF0000000;
   1.110 +
   1.111 +/**
   1.112 + * Mask to get the kind of a frame type.
   1.113 + *
   1.114 + * @see #BASE
   1.115 + * @see #LOCAL
   1.116 + * @see #STACK
   1.117 + */
   1.118 +final static int KIND = 0xF000000;
   1.119 +
   1.120 +/**
   1.121 + * Mask to get the value of a frame type.
   1.122 + */
   1.123 +final static int VALUE = 0xFFFFFF;
   1.124 +
   1.125 +/**
   1.126 + * Mask to get the kind of base types.
   1.127 + */
   1.128 +final static int BASE_KIND = 0xFF00000;
   1.129 +
   1.130 +/**
   1.131 + * Mask to get the value of base types.
   1.132 + */
   1.133 +final static int BASE_VALUE = 0xFFFFF;
   1.134 +
   1.135 +/**
   1.136 + * Kind of the types that are not relative to an input stack map frame.
   1.137 + */
   1.138 +final static int BASE = 0x1000000;
   1.139 +
   1.140 +/**
   1.141 + * Base kind of the base reference types. The BASE_VALUE of such types is an
   1.142 + * index into the type table.
   1.143 + */
   1.144 +final static int OBJECT = BASE | 0x700000;
   1.145 +
   1.146 +/**
   1.147 + * Base kind of the uninitialized base types. The BASE_VALUE of such types
   1.148 + * in an index into the type table (the Item at that index contains both an
   1.149 + * instruction offset and an internal class name).
   1.150 + */
   1.151 +final static int UNINITIALIZED = BASE | 0x800000;
   1.152 +
   1.153 +/**
   1.154 + * Kind of the types that are relative to the local variable types of an
   1.155 + * input stack map frame. The value of such types is a local variable index.
   1.156 + */
   1.157 +private final static int LOCAL = 0x2000000;
   1.158 +
   1.159 +/**
   1.160 + * Kind of the the types that are relative to the stack of an input stack
   1.161 + * map frame. The value of such types is a position relatively to the top of
   1.162 + * this stack.
   1.163 + */
   1.164 +private final static int STACK = 0x3000000;
   1.165 +
   1.166 +/**
   1.167 + * The TOP type. This is a BASE type.
   1.168 + */
   1.169 +final static int TOP = BASE | 0;
   1.170 +
   1.171 +/**
   1.172 + * The BOOLEAN type. This is a BASE type mainly used for array types.
   1.173 + */
   1.174 +final static int BOOLEAN = BASE | 9;
   1.175 +
   1.176 +/**
   1.177 + * The BYTE type. This is a BASE type mainly used for array types.
   1.178 + */
   1.179 +final static int BYTE = BASE | 10;
   1.180 +
   1.181 +/**
   1.182 + * The CHAR type. This is a BASE type mainly used for array types.
   1.183 + */
   1.184 +final static int CHAR = BASE | 11;
   1.185 +
   1.186 +/**
   1.187 + * The SHORT type. This is a BASE type mainly used for array types.
   1.188 + */
   1.189 +final static int SHORT = BASE | 12;
   1.190 +
   1.191 +/**
   1.192 + * The INTEGER type. This is a BASE type.
   1.193 + */
   1.194 +final static int INTEGER = BASE | 1;
   1.195 +
   1.196 +/**
   1.197 + * The FLOAT type. This is a BASE type.
   1.198 + */
   1.199 +final static int FLOAT = BASE | 2;
   1.200 +
   1.201 +/**
   1.202 + * The DOUBLE type. This is a BASE type.
   1.203 + */
   1.204 +final static int DOUBLE = BASE | 3;
   1.205 +
   1.206 +/**
   1.207 + * The LONG type. This is a BASE type.
   1.208 + */
   1.209 +final static int LONG = BASE | 4;
   1.210 +
   1.211 +/**
   1.212 + * The NULL type. This is a BASE type.
   1.213 + */
   1.214 +final static int NULL = BASE | 5;
   1.215 +
   1.216 +/**
   1.217 + * The UNINITIALIZED_THIS type. This is a BASE type.
   1.218 + */
   1.219 +final static int UNINITIALIZED_THIS = BASE | 6;
   1.220 +
   1.221 +/**
   1.222 + * The stack size variation corresponding to each JVM instruction. This
   1.223 + * stack variation is equal to the size of the values produced by an
   1.224 + * instruction, minus the size of the values consumed by this instruction.
   1.225 + */
   1.226 +final static int[] SIZE;
   1.227 +
   1.228 +/**
   1.229 + * Computes the stack size variation corresponding to each JVM instruction.
   1.230 + */
   1.231 +static
   1.232 +	{
   1.233 +	int i;
   1.234 +	int[] b = new int[202];
   1.235 +	String s = "EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDD"
   1.236 +	           + "CDCDEEEEEEEEEEEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCD"
   1.237 +	           + "CDCEEEEDDDDDDDCDCDCEFEFDDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFED"
   1.238 +	           + "DDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE";
   1.239 +	for(i = 0; i < b.length; ++i)
   1.240 +		{
   1.241 +		b[i] = s.charAt(i) - 'E';
   1.242 +		}
   1.243 +	SIZE = b;
   1.244 +
   1.245 +	// code to generate the above string
   1.246 +	//
   1.247 +	// int NA = 0; // not applicable (unused opcode or variable size opcode)
   1.248 +	//
   1.249 +	// b = new int[] {
   1.250 +	// 0, //NOP, // visitInsn
   1.251 +	// 1, //ACONST_NULL, // -
   1.252 +	// 1, //ICONST_M1, // -
   1.253 +	// 1, //ICONST_0, // -
   1.254 +	// 1, //ICONST_1, // -
   1.255 +	// 1, //ICONST_2, // -
   1.256 +	// 1, //ICONST_3, // -
   1.257 +	// 1, //ICONST_4, // -
   1.258 +	// 1, //ICONST_5, // -
   1.259 +	// 2, //LCONST_0, // -
   1.260 +	// 2, //LCONST_1, // -
   1.261 +	// 1, //FCONST_0, // -
   1.262 +	// 1, //FCONST_1, // -
   1.263 +	// 1, //FCONST_2, // -
   1.264 +	// 2, //DCONST_0, // -
   1.265 +	// 2, //DCONST_1, // -
   1.266 +	// 1, //BIPUSH, // visitIntInsn
   1.267 +	// 1, //SIPUSH, // -
   1.268 +	// 1, //LDC, // visitLdcInsn
   1.269 +	// NA, //LDC_W, // -
   1.270 +	// NA, //LDC2_W, // -
   1.271 +	// 1, //ILOAD, // visitVarInsn
   1.272 +	// 2, //LLOAD, // -
   1.273 +	// 1, //FLOAD, // -
   1.274 +	// 2, //DLOAD, // -
   1.275 +	// 1, //ALOAD, // -
   1.276 +	// NA, //ILOAD_0, // -
   1.277 +	// NA, //ILOAD_1, // -
   1.278 +	// NA, //ILOAD_2, // -
   1.279 +	// NA, //ILOAD_3, // -
   1.280 +	// NA, //LLOAD_0, // -
   1.281 +	// NA, //LLOAD_1, // -
   1.282 +	// NA, //LLOAD_2, // -
   1.283 +	// NA, //LLOAD_3, // -
   1.284 +	// NA, //FLOAD_0, // -
   1.285 +	// NA, //FLOAD_1, // -
   1.286 +	// NA, //FLOAD_2, // -
   1.287 +	// NA, //FLOAD_3, // -
   1.288 +	// NA, //DLOAD_0, // -
   1.289 +	// NA, //DLOAD_1, // -
   1.290 +	// NA, //DLOAD_2, // -
   1.291 +	// NA, //DLOAD_3, // -
   1.292 +	// NA, //ALOAD_0, // -
   1.293 +	// NA, //ALOAD_1, // -
   1.294 +	// NA, //ALOAD_2, // -
   1.295 +	// NA, //ALOAD_3, // -
   1.296 +	// -1, //IALOAD, // visitInsn
   1.297 +	// 0, //LALOAD, // -
   1.298 +	// -1, //FALOAD, // -
   1.299 +	// 0, //DALOAD, // -
   1.300 +	// -1, //AALOAD, // -
   1.301 +	// -1, //BALOAD, // -
   1.302 +	// -1, //CALOAD, // -
   1.303 +	// -1, //SALOAD, // -
   1.304 +	// -1, //ISTORE, // visitVarInsn
   1.305 +	// -2, //LSTORE, // -
   1.306 +	// -1, //FSTORE, // -
   1.307 +	// -2, //DSTORE, // -
   1.308 +	// -1, //ASTORE, // -
   1.309 +	// NA, //ISTORE_0, // -
   1.310 +	// NA, //ISTORE_1, // -
   1.311 +	// NA, //ISTORE_2, // -
   1.312 +	// NA, //ISTORE_3, // -
   1.313 +	// NA, //LSTORE_0, // -
   1.314 +	// NA, //LSTORE_1, // -
   1.315 +	// NA, //LSTORE_2, // -
   1.316 +	// NA, //LSTORE_3, // -
   1.317 +	// NA, //FSTORE_0, // -
   1.318 +	// NA, //FSTORE_1, // -
   1.319 +	// NA, //FSTORE_2, // -
   1.320 +	// NA, //FSTORE_3, // -
   1.321 +	// NA, //DSTORE_0, // -
   1.322 +	// NA, //DSTORE_1, // -
   1.323 +	// NA, //DSTORE_2, // -
   1.324 +	// NA, //DSTORE_3, // -
   1.325 +	// NA, //ASTORE_0, // -
   1.326 +	// NA, //ASTORE_1, // -
   1.327 +	// NA, //ASTORE_2, // -
   1.328 +	// NA, //ASTORE_3, // -
   1.329 +	// -3, //IASTORE, // visitInsn
   1.330 +	// -4, //LASTORE, // -
   1.331 +	// -3, //FASTORE, // -
   1.332 +	// -4, //DASTORE, // -
   1.333 +	// -3, //AASTORE, // -
   1.334 +	// -3, //BASTORE, // -
   1.335 +	// -3, //CASTORE, // -
   1.336 +	// -3, //SASTORE, // -
   1.337 +	// -1, //POP, // -
   1.338 +	// -2, //POP2, // -
   1.339 +	// 1, //DUP, // -
   1.340 +	// 1, //DUP_X1, // -
   1.341 +	// 1, //DUP_X2, // -
   1.342 +	// 2, //DUP2, // -
   1.343 +	// 2, //DUP2_X1, // -
   1.344 +	// 2, //DUP2_X2, // -
   1.345 +	// 0, //SWAP, // -
   1.346 +	// -1, //IADD, // -
   1.347 +	// -2, //LADD, // -
   1.348 +	// -1, //FADD, // -
   1.349 +	// -2, //DADD, // -
   1.350 +	// -1, //ISUB, // -
   1.351 +	// -2, //LSUB, // -
   1.352 +	// -1, //FSUB, // -
   1.353 +	// -2, //DSUB, // -
   1.354 +	// -1, //IMUL, // -
   1.355 +	// -2, //LMUL, // -
   1.356 +	// -1, //FMUL, // -
   1.357 +	// -2, //DMUL, // -
   1.358 +	// -1, //IDIV, // -
   1.359 +	// -2, //LDIV, // -
   1.360 +	// -1, //FDIV, // -
   1.361 +	// -2, //DDIV, // -
   1.362 +	// -1, //IREM, // -
   1.363 +	// -2, //LREM, // -
   1.364 +	// -1, //FREM, // -
   1.365 +	// -2, //DREM, // -
   1.366 +	// 0, //INEG, // -
   1.367 +	// 0, //LNEG, // -
   1.368 +	// 0, //FNEG, // -
   1.369 +	// 0, //DNEG, // -
   1.370 +	// -1, //ISHL, // -
   1.371 +	// -1, //LSHL, // -
   1.372 +	// -1, //ISHR, // -
   1.373 +	// -1, //LSHR, // -
   1.374 +	// -1, //IUSHR, // -
   1.375 +	// -1, //LUSHR, // -
   1.376 +	// -1, //IAND, // -
   1.377 +	// -2, //LAND, // -
   1.378 +	// -1, //IOR, // -
   1.379 +	// -2, //LOR, // -
   1.380 +	// -1, //IXOR, // -
   1.381 +	// -2, //LXOR, // -
   1.382 +	// 0, //IINC, // visitIincInsn
   1.383 +	// 1, //I2L, // visitInsn
   1.384 +	// 0, //I2F, // -
   1.385 +	// 1, //I2D, // -
   1.386 +	// -1, //L2I, // -
   1.387 +	// -1, //L2F, // -
   1.388 +	// 0, //L2D, // -
   1.389 +	// 0, //F2I, // -
   1.390 +	// 1, //F2L, // -
   1.391 +	// 1, //F2D, // -
   1.392 +	// -1, //D2I, // -
   1.393 +	// 0, //D2L, // -
   1.394 +	// -1, //D2F, // -
   1.395 +	// 0, //I2B, // -
   1.396 +	// 0, //I2C, // -
   1.397 +	// 0, //I2S, // -
   1.398 +	// -3, //LCMP, // -
   1.399 +	// -1, //FCMPL, // -
   1.400 +	// -1, //FCMPG, // -
   1.401 +	// -3, //DCMPL, // -
   1.402 +	// -3, //DCMPG, // -
   1.403 +	// -1, //IFEQ, // visitJumpInsn
   1.404 +	// -1, //IFNE, // -
   1.405 +	// -1, //IFLT, // -
   1.406 +	// -1, //IFGE, // -
   1.407 +	// -1, //IFGT, // -
   1.408 +	// -1, //IFLE, // -
   1.409 +	// -2, //IF_ICMPEQ, // -
   1.410 +	// -2, //IF_ICMPNE, // -
   1.411 +	// -2, //IF_ICMPLT, // -
   1.412 +	// -2, //IF_ICMPGE, // -
   1.413 +	// -2, //IF_ICMPGT, // -
   1.414 +	// -2, //IF_ICMPLE, // -
   1.415 +	// -2, //IF_ACMPEQ, // -
   1.416 +	// -2, //IF_ACMPNE, // -
   1.417 +	// 0, //GOTO, // -
   1.418 +	// 1, //JSR, // -
   1.419 +	// 0, //RET, // visitVarInsn
   1.420 +	// -1, //TABLESWITCH, // visiTableSwitchInsn
   1.421 +	// -1, //LOOKUPSWITCH, // visitLookupSwitch
   1.422 +	// -1, //IRETURN, // visitInsn
   1.423 +	// -2, //LRETURN, // -
   1.424 +	// -1, //FRETURN, // -
   1.425 +	// -2, //DRETURN, // -
   1.426 +	// -1, //ARETURN, // -
   1.427 +	// 0, //RETURN, // -
   1.428 +	// NA, //GETSTATIC, // visitFieldInsn
   1.429 +	// NA, //PUTSTATIC, // -
   1.430 +	// NA, //GETFIELD, // -
   1.431 +	// NA, //PUTFIELD, // -
   1.432 +	// NA, //INVOKEVIRTUAL, // visitMethodInsn
   1.433 +	// NA, //INVOKESPECIAL, // -
   1.434 +	// NA, //INVOKESTATIC, // -
   1.435 +	// NA, //INVOKEINTERFACE, // -
   1.436 +	// NA, //UNUSED, // NOT VISITED
   1.437 +	// 1, //NEW, // visitTypeInsn
   1.438 +	// 0, //NEWARRAY, // visitIntInsn
   1.439 +	// 0, //ANEWARRAY, // visitTypeInsn
   1.440 +	// 0, //ARRAYLENGTH, // visitInsn
   1.441 +	// NA, //ATHROW, // -
   1.442 +	// 0, //CHECKCAST, // visitTypeInsn
   1.443 +	// 0, //INSTANCEOF, // -
   1.444 +	// -1, //MONITORENTER, // visitInsn
   1.445 +	// -1, //MONITOREXIT, // -
   1.446 +	// NA, //WIDE, // NOT VISITED
   1.447 +	// NA, //MULTIANEWARRAY, // visitMultiANewArrayInsn
   1.448 +	// -1, //IFNULL, // visitJumpInsn
   1.449 +	// -1, //IFNONNULL, // -
   1.450 +	// NA, //GOTO_W, // -
   1.451 +	// NA, //JSR_W, // -
   1.452 +	// };
   1.453 +	// for (i = 0; i < b.length; ++i) {
   1.454 +	// System.err.print((char)('E' + b[i]));
   1.455 +	// }
   1.456 +	// System.err.println();
   1.457 +	}
   1.458 +
   1.459 +/**
   1.460 + * The label (i.e. basic block) to which these input and output stack map
   1.461 + * frames correspond.
   1.462 + */
   1.463 +Label owner;
   1.464 +
   1.465 +/**
   1.466 + * The input stack map frame locals.
   1.467 + */
   1.468 +int[] inputLocals;
   1.469 +
   1.470 +/**
   1.471 + * The input stack map frame stack.
   1.472 + */
   1.473 +int[] inputStack;
   1.474 +
   1.475 +/**
   1.476 + * The output stack map frame locals.
   1.477 + */
   1.478 +private int[] outputLocals;
   1.479 +
   1.480 +/**
   1.481 + * The output stack map frame stack.
   1.482 + */
   1.483 +private int[] outputStack;
   1.484 +
   1.485 +/**
   1.486 + * Relative size of the output stack. The exact semantics of this field
   1.487 + * depends on the algorithm that is used.
   1.488 + * <p/>
   1.489 + * When only the maximum stack size is computed, this field is the size of
   1.490 + * the output stack relatively to the top of the input stack.
   1.491 + * <p/>
   1.492 + * When the stack map frames are completely computed, this field is the
   1.493 + * actual number of types in {@link #outputStack}.
   1.494 + */
   1.495 +private int outputStackTop;
   1.496 +
   1.497 +/**
   1.498 + * Number of types that are initialized in the basic block.
   1.499 + *
   1.500 + * @see #initializations
   1.501 + */
   1.502 +private int initializationCount;
   1.503 +
   1.504 +/**
   1.505 + * The types that are initialized in the basic block. A constructor
   1.506 + * invocation on an UNINITIALIZED or UNINITIALIZED_THIS type must replace
   1.507 + * <i>every occurence</i> of this type in the local variables and in the
   1.508 + * operand stack. This cannot be done during the first phase of the
   1.509 + * algorithm since, during this phase, the local variables and the operand
   1.510 + * stack are not completely computed. It is therefore necessary to store the
   1.511 + * types on which constructors are invoked in the basic block, in order to
   1.512 + * do this replacement during the second phase of the algorithm, where the
   1.513 + * frames are fully computed. Note that this array can contain types that
   1.514 + * are relative to input locals or to the input stack (see below for the
   1.515 + * description of the algorithm).
   1.516 + */
   1.517 +private int[] initializations;
   1.518 +
   1.519 +/**
   1.520 + * Returns the output frame local variable type at the given index.
   1.521 + *
   1.522 + * @param local the index of the local that must be returned.
   1.523 + * @return the output frame local variable type at the given index.
   1.524 + */
   1.525 +private int get(final int local){
   1.526 +	if(outputLocals == null || local >= outputLocals.length)
   1.527 +		{
   1.528 +		// this local has never been assigned in this basic block,
   1.529 +		// so it is still equal to its value in the input frame
   1.530 +		return LOCAL | local;
   1.531 +		}
   1.532 +	else
   1.533 +		{
   1.534 +		int type = outputLocals[local];
   1.535 +		if(type == 0)
   1.536 +			{
   1.537 +			// this local has never been assigned in this basic block,
   1.538 +			// so it is still equal to its value in the input frame
   1.539 +			type = outputLocals[local] = LOCAL | local;
   1.540 +			}
   1.541 +		return type;
   1.542 +		}
   1.543 +}
   1.544 +
   1.545 +/**
   1.546 + * Sets the output frame local variable type at the given index.
   1.547 + *
   1.548 + * @param local the index of the local that must be set.
   1.549 + * @param type  the value of the local that must be set.
   1.550 + */
   1.551 +private void set(final int local, final int type){
   1.552 +	// creates and/or resizes the output local variables array if necessary
   1.553 +	if(outputLocals == null)
   1.554 +		{
   1.555 +		outputLocals = new int[10];
   1.556 +		}
   1.557 +	int n = outputLocals.length;
   1.558 +	if(local >= n)
   1.559 +		{
   1.560 +		int[] t = new int[Math.max(local + 1, 2 * n)];
   1.561 +		System.arraycopy(outputLocals, 0, t, 0, n);
   1.562 +		outputLocals = t;
   1.563 +		}
   1.564 +	// sets the local variable
   1.565 +	outputLocals[local] = type;
   1.566 +}
   1.567 +
   1.568 +/**
   1.569 + * Pushes a new type onto the output frame stack.
   1.570 + *
   1.571 + * @param type the type that must be pushed.
   1.572 + */
   1.573 +private void push(final int type){
   1.574 +	// creates and/or resizes the output stack array if necessary
   1.575 +	if(outputStack == null)
   1.576 +		{
   1.577 +		outputStack = new int[10];
   1.578 +		}
   1.579 +	int n = outputStack.length;
   1.580 +	if(outputStackTop >= n)
   1.581 +		{
   1.582 +		int[] t = new int[Math.max(outputStackTop + 1, 2 * n)];
   1.583 +		System.arraycopy(outputStack, 0, t, 0, n);
   1.584 +		outputStack = t;
   1.585 +		}
   1.586 +	// pushes the type on the output stack
   1.587 +	outputStack[outputStackTop++] = type;
   1.588 +	// updates the maximun height reached by the output stack, if needed
   1.589 +	int top = owner.inputStackTop + outputStackTop;
   1.590 +	if(top > owner.outputStackMax)
   1.591 +		{
   1.592 +		owner.outputStackMax = top;
   1.593 +		}
   1.594 +}
   1.595 +
   1.596 +/**
   1.597 + * Pushes a new type onto the output frame stack.
   1.598 + *
   1.599 + * @param cw   the ClassWriter to which this label belongs.
   1.600 + * @param desc the descriptor of the type to be pushed. Can also be a method
   1.601 + *             descriptor (in this case this method pushes its return type onto
   1.602 + *             the output frame stack).
   1.603 + */
   1.604 +private void push(final ClassWriter cw, final String desc){
   1.605 +	int type = type(cw, desc);
   1.606 +	if(type != 0)
   1.607 +		{
   1.608 +		push(type);
   1.609 +		if(type == LONG || type == DOUBLE)
   1.610 +			{
   1.611 +			push(TOP);
   1.612 +			}
   1.613 +		}
   1.614 +}
   1.615 +
   1.616 +/**
   1.617 + * Returns the int encoding of the given type.
   1.618 + *
   1.619 + * @param cw   the ClassWriter to which this label belongs.
   1.620 + * @param desc a type descriptor.
   1.621 + * @return the int encoding of the given type.
   1.622 + */
   1.623 +private int type(final ClassWriter cw, final String desc){
   1.624 +	String t;
   1.625 +	int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
   1.626 +	switch(desc.charAt(index))
   1.627 +		{
   1.628 +		case'V':
   1.629 +			return 0;
   1.630 +		case'Z':
   1.631 +		case'C':
   1.632 +		case'B':
   1.633 +		case'S':
   1.634 +		case'I':
   1.635 +			return INTEGER;
   1.636 +		case'F':
   1.637 +			return FLOAT;
   1.638 +		case'J':
   1.639 +			return LONG;
   1.640 +		case'D':
   1.641 +			return DOUBLE;
   1.642 +		case'L':
   1.643 +			// stores the internal name, not the descriptor!
   1.644 +			t = desc.substring(index + 1, desc.length() - 1);
   1.645 +			return OBJECT | cw.addType(t);
   1.646 +			// case '[':
   1.647 +		default:
   1.648 +			// extracts the dimensions and the element type
   1.649 +			int data;
   1.650 +			int dims = index + 1;
   1.651 +			while(desc.charAt(dims) == '[')
   1.652 +				{
   1.653 +				++dims;
   1.654 +				}
   1.655 +			switch(desc.charAt(dims))
   1.656 +				{
   1.657 +				case'Z':
   1.658 +					data = BOOLEAN;
   1.659 +					break;
   1.660 +				case'C':
   1.661 +					data = CHAR;
   1.662 +					break;
   1.663 +				case'B':
   1.664 +					data = BYTE;
   1.665 +					break;
   1.666 +				case'S':
   1.667 +					data = SHORT;
   1.668 +					break;
   1.669 +				case'I':
   1.670 +					data = INTEGER;
   1.671 +					break;
   1.672 +				case'F':
   1.673 +					data = FLOAT;
   1.674 +					break;
   1.675 +				case'J':
   1.676 +					data = LONG;
   1.677 +					break;
   1.678 +				case'D':
   1.679 +					data = DOUBLE;
   1.680 +					break;
   1.681 +					// case 'L':
   1.682 +				default:
   1.683 +					// stores the internal name, not the descriptor
   1.684 +					t = desc.substring(dims + 1, desc.length() - 1);
   1.685 +					data = OBJECT | cw.addType(t);
   1.686 +				}
   1.687 +			return (dims - index) << 28 | data;
   1.688 +		}
   1.689 +}
   1.690 +
   1.691 +/**
   1.692 + * Pops a type from the output frame stack and returns its value.
   1.693 + *
   1.694 + * @return the type that has been popped from the output frame stack.
   1.695 + */
   1.696 +private int pop(){
   1.697 +	if(outputStackTop > 0)
   1.698 +		{
   1.699 +		return outputStack[--outputStackTop];
   1.700 +		}
   1.701 +	else
   1.702 +		{
   1.703 +		// if the output frame stack is empty, pops from the input stack
   1.704 +		return STACK | -(--owner.inputStackTop);
   1.705 +		}
   1.706 +}
   1.707 +
   1.708 +/**
   1.709 + * Pops the given number of types from the output frame stack.
   1.710 + *
   1.711 + * @param elements the number of types that must be popped.
   1.712 + */
   1.713 +private void pop(final int elements){
   1.714 +	if(outputStackTop >= elements)
   1.715 +		{
   1.716 +		outputStackTop -= elements;
   1.717 +		}
   1.718 +	else
   1.719 +		{
   1.720 +		// if the number of elements to be popped is greater than the number
   1.721 +		// of elements in the output stack, clear it, and pops the remaining
   1.722 +		// elements from the input stack.
   1.723 +		owner.inputStackTop -= elements - outputStackTop;
   1.724 +		outputStackTop = 0;
   1.725 +		}
   1.726 +}
   1.727 +
   1.728 +/**
   1.729 + * Pops a type from the output frame stack.
   1.730 + *
   1.731 + * @param desc the descriptor of the type to be popped. Can also be a method
   1.732 + *             descriptor (in this case this method pops the types corresponding
   1.733 + *             to the method arguments).
   1.734 + */
   1.735 +private void pop(final String desc){
   1.736 +	char c = desc.charAt(0);
   1.737 +	if(c == '(')
   1.738 +		{
   1.739 +		pop((MethodWriter.getArgumentsAndReturnSizes(desc) >> 2) - 1);
   1.740 +		}
   1.741 +	else if(c == 'J' || c == 'D')
   1.742 +		{
   1.743 +		pop(2);
   1.744 +		}
   1.745 +	else
   1.746 +		{
   1.747 +		pop(1);
   1.748 +		}
   1.749 +}
   1.750 +
   1.751 +/**
   1.752 + * Adds a new type to the list of types on which a constructor is invoked in
   1.753 + * the basic block.
   1.754 + *
   1.755 + * @param var a type on a which a constructor is invoked.
   1.756 + */
   1.757 +private void init(final int var){
   1.758 +	// creates and/or resizes the initializations array if necessary
   1.759 +	if(initializations == null)
   1.760 +		{
   1.761 +		initializations = new int[2];
   1.762 +		}
   1.763 +	int n = initializations.length;
   1.764 +	if(initializationCount >= n)
   1.765 +		{
   1.766 +		int[] t = new int[Math.max(initializationCount + 1, 2 * n)];
   1.767 +		System.arraycopy(initializations, 0, t, 0, n);
   1.768 +		initializations = t;
   1.769 +		}
   1.770 +	// stores the type to be initialized
   1.771 +	initializations[initializationCount++] = var;
   1.772 +}
   1.773 +
   1.774 +/**
   1.775 + * Replaces the given type with the appropriate type if it is one of the
   1.776 + * types on which a constructor is invoked in the basic block.
   1.777 + *
   1.778 + * @param cw the ClassWriter to which this label belongs.
   1.779 + * @param t  a type
   1.780 + * @return t or, if t is one of the types on which a constructor is invoked
   1.781 + *         in the basic block, the type corresponding to this constructor.
   1.782 + */
   1.783 +private int init(final ClassWriter cw, final int t){
   1.784 +	int s;
   1.785 +	if(t == UNINITIALIZED_THIS)
   1.786 +		{
   1.787 +		s = OBJECT | cw.addType(cw.thisName);
   1.788 +		}
   1.789 +	else if((t & (DIM | BASE_KIND)) == UNINITIALIZED)
   1.790 +		{
   1.791 +		String type = cw.typeTable[t & BASE_VALUE].strVal1;
   1.792 +		s = OBJECT | cw.addType(type);
   1.793 +		}
   1.794 +	else
   1.795 +		{
   1.796 +		return t;
   1.797 +		}
   1.798 +	for(int j = 0; j < initializationCount; ++j)
   1.799 +		{
   1.800 +		int u = initializations[j];
   1.801 +		int dim = u & DIM;
   1.802 +		int kind = u & KIND;
   1.803 +		if(kind == LOCAL)
   1.804 +			{
   1.805 +			u = dim + inputLocals[u & VALUE];
   1.806 +			}
   1.807 +		else if(kind == STACK)
   1.808 +			{
   1.809 +			u = dim + inputStack[inputStack.length - (u & VALUE)];
   1.810 +			}
   1.811 +		if(t == u)
   1.812 +			{
   1.813 +			return s;
   1.814 +			}
   1.815 +		}
   1.816 +	return t;
   1.817 +}
   1.818 +
   1.819 +/**
   1.820 + * Initializes the input frame of the first basic block from the method
   1.821 + * descriptor.
   1.822 + *
   1.823 + * @param cw        the ClassWriter to which this label belongs.
   1.824 + * @param access    the access flags of the method to which this label belongs.
   1.825 + * @param args      the formal parameter types of this method.
   1.826 + * @param maxLocals the maximum number of local variables of this method.
   1.827 + */
   1.828 +void initInputFrame(
   1.829 +		final ClassWriter cw,
   1.830 +		final int access,
   1.831 +		final Type[] args,
   1.832 +		final int maxLocals){
   1.833 +	inputLocals = new int[maxLocals];
   1.834 +	inputStack = new int[0];
   1.835 +	int i = 0;
   1.836 +	if((access & Opcodes.ACC_STATIC) == 0)
   1.837 +		{
   1.838 +		if((access & MethodWriter.ACC_CONSTRUCTOR) == 0)
   1.839 +			{
   1.840 +			inputLocals[i++] = OBJECT | cw.addType(cw.thisName);
   1.841 +			}
   1.842 +		else
   1.843 +			{
   1.844 +			inputLocals[i++] = UNINITIALIZED_THIS;
   1.845 +			}
   1.846 +		}
   1.847 +	for(int j = 0; j < args.length; ++j)
   1.848 +		{
   1.849 +		int t = type(cw, args[j].getDescriptor());
   1.850 +		inputLocals[i++] = t;
   1.851 +		if(t == LONG || t == DOUBLE)
   1.852 +			{
   1.853 +			inputLocals[i++] = TOP;
   1.854 +			}
   1.855 +		}
   1.856 +	while(i < maxLocals)
   1.857 +		{
   1.858 +		inputLocals[i++] = TOP;
   1.859 +		}
   1.860 +}
   1.861 +
   1.862 +/**
   1.863 + * Simulates the action of the given instruction on the output stack frame.
   1.864 + *
   1.865 + * @param opcode the opcode of the instruction.
   1.866 + * @param arg    the operand of the instruction, if any.
   1.867 + * @param cw     the class writer to which this label belongs.
   1.868 + * @param item   the operand of the instructions, if any.
   1.869 + */
   1.870 +void execute(
   1.871 +		final int opcode,
   1.872 +		final int arg,
   1.873 +		final ClassWriter cw,
   1.874 +		final Item item){
   1.875 +	int t1, t2, t3, t4;
   1.876 +	switch(opcode)
   1.877 +		{
   1.878 +		case Opcodes.NOP:
   1.879 +		case Opcodes.INEG:
   1.880 +		case Opcodes.LNEG:
   1.881 +		case Opcodes.FNEG:
   1.882 +		case Opcodes.DNEG:
   1.883 +		case Opcodes.I2B:
   1.884 +		case Opcodes.I2C:
   1.885 +		case Opcodes.I2S:
   1.886 +		case Opcodes.GOTO:
   1.887 +		case Opcodes.RETURN:
   1.888 +			break;
   1.889 +		case Opcodes.ACONST_NULL:
   1.890 +			push(NULL);
   1.891 +			break;
   1.892 +		case Opcodes.ICONST_M1:
   1.893 +		case Opcodes.ICONST_0:
   1.894 +		case Opcodes.ICONST_1:
   1.895 +		case Opcodes.ICONST_2:
   1.896 +		case Opcodes.ICONST_3:
   1.897 +		case Opcodes.ICONST_4:
   1.898 +		case Opcodes.ICONST_5:
   1.899 +		case Opcodes.BIPUSH:
   1.900 +		case Opcodes.SIPUSH:
   1.901 +		case Opcodes.ILOAD:
   1.902 +			push(INTEGER);
   1.903 +			break;
   1.904 +		case Opcodes.LCONST_0:
   1.905 +		case Opcodes.LCONST_1:
   1.906 +		case Opcodes.LLOAD:
   1.907 +			push(LONG);
   1.908 +			push(TOP);
   1.909 +			break;
   1.910 +		case Opcodes.FCONST_0:
   1.911 +		case Opcodes.FCONST_1:
   1.912 +		case Opcodes.FCONST_2:
   1.913 +		case Opcodes.FLOAD:
   1.914 +			push(FLOAT);
   1.915 +			break;
   1.916 +		case Opcodes.DCONST_0:
   1.917 +		case Opcodes.DCONST_1:
   1.918 +		case Opcodes.DLOAD:
   1.919 +			push(DOUBLE);
   1.920 +			push(TOP);
   1.921 +			break;
   1.922 +		case Opcodes.LDC:
   1.923 +			switch(item.type)
   1.924 +				{
   1.925 +				case ClassWriter.INT:
   1.926 +					push(INTEGER);
   1.927 +					break;
   1.928 +				case ClassWriter.LONG:
   1.929 +					push(LONG);
   1.930 +					push(TOP);
   1.931 +					break;
   1.932 +				case ClassWriter.FLOAT:
   1.933 +					push(FLOAT);
   1.934 +					break;
   1.935 +				case ClassWriter.DOUBLE:
   1.936 +					push(DOUBLE);
   1.937 +					push(TOP);
   1.938 +					break;
   1.939 +				case ClassWriter.CLASS:
   1.940 +					push(OBJECT | cw.addType("java/lang/Class"));
   1.941 +					break;
   1.942 +					// case ClassWriter.STR:
   1.943 +				default:
   1.944 +					push(OBJECT | cw.addType("java/lang/String"));
   1.945 +				}
   1.946 +			break;
   1.947 +		case Opcodes.ALOAD:
   1.948 +			push(get(arg));
   1.949 +			break;
   1.950 +		case Opcodes.IALOAD:
   1.951 +		case Opcodes.BALOAD:
   1.952 +		case Opcodes.CALOAD:
   1.953 +		case Opcodes.SALOAD:
   1.954 +			pop(2);
   1.955 +			push(INTEGER);
   1.956 +			break;
   1.957 +		case Opcodes.LALOAD:
   1.958 +		case Opcodes.D2L:
   1.959 +			pop(2);
   1.960 +			push(LONG);
   1.961 +			push(TOP);
   1.962 +			break;
   1.963 +		case Opcodes.FALOAD:
   1.964 +			pop(2);
   1.965 +			push(FLOAT);
   1.966 +			break;
   1.967 +		case Opcodes.DALOAD:
   1.968 +		case Opcodes.L2D:
   1.969 +			pop(2);
   1.970 +			push(DOUBLE);
   1.971 +			push(TOP);
   1.972 +			break;
   1.973 +		case Opcodes.AALOAD:
   1.974 +			pop(1);
   1.975 +			t1 = pop();
   1.976 +			push(ELEMENT_OF + t1);
   1.977 +			break;
   1.978 +		case Opcodes.ISTORE:
   1.979 +		case Opcodes.FSTORE:
   1.980 +		case Opcodes.ASTORE:
   1.981 +			t1 = pop();
   1.982 +			set(arg, t1);
   1.983 +			if(arg > 0)
   1.984 +				{
   1.985 +				t2 = get(arg - 1);
   1.986 +				// if t2 is of kind STACK or LOCAL we cannot know its size!
   1.987 +				if(t2 == LONG || t2 == DOUBLE)
   1.988 +					{
   1.989 +					set(arg - 1, TOP);
   1.990 +					}
   1.991 +				}
   1.992 +			break;
   1.993 +		case Opcodes.LSTORE:
   1.994 +		case Opcodes.DSTORE:
   1.995 +			pop(1);
   1.996 +			t1 = pop();
   1.997 +			set(arg, t1);
   1.998 +			set(arg + 1, TOP);
   1.999 +			if(arg > 0)
  1.1000 +				{
  1.1001 +				t2 = get(arg - 1);
  1.1002 +				// if t2 is of kind STACK or LOCAL we cannot know its size!
  1.1003 +				if(t2 == LONG || t2 == DOUBLE)
  1.1004 +					{
  1.1005 +					set(arg - 1, TOP);
  1.1006 +					}
  1.1007 +				}
  1.1008 +			break;
  1.1009 +		case Opcodes.IASTORE:
  1.1010 +		case Opcodes.BASTORE:
  1.1011 +		case Opcodes.CASTORE:
  1.1012 +		case Opcodes.SASTORE:
  1.1013 +		case Opcodes.FASTORE:
  1.1014 +		case Opcodes.AASTORE:
  1.1015 +			pop(3);
  1.1016 +			break;
  1.1017 +		case Opcodes.LASTORE:
  1.1018 +		case Opcodes.DASTORE:
  1.1019 +			pop(4);
  1.1020 +			break;
  1.1021 +		case Opcodes.POP:
  1.1022 +		case Opcodes.IFEQ:
  1.1023 +		case Opcodes.IFNE:
  1.1024 +		case Opcodes.IFLT:
  1.1025 +		case Opcodes.IFGE:
  1.1026 +		case Opcodes.IFGT:
  1.1027 +		case Opcodes.IFLE:
  1.1028 +		case Opcodes.IRETURN:
  1.1029 +		case Opcodes.FRETURN:
  1.1030 +		case Opcodes.ARETURN:
  1.1031 +		case Opcodes.TABLESWITCH:
  1.1032 +		case Opcodes.LOOKUPSWITCH:
  1.1033 +		case Opcodes.ATHROW:
  1.1034 +		case Opcodes.MONITORENTER:
  1.1035 +		case Opcodes.MONITOREXIT:
  1.1036 +		case Opcodes.IFNULL:
  1.1037 +		case Opcodes.IFNONNULL:
  1.1038 +			pop(1);
  1.1039 +			break;
  1.1040 +		case Opcodes.POP2:
  1.1041 +		case Opcodes.IF_ICMPEQ:
  1.1042 +		case Opcodes.IF_ICMPNE:
  1.1043 +		case Opcodes.IF_ICMPLT:
  1.1044 +		case Opcodes.IF_ICMPGE:
  1.1045 +		case Opcodes.IF_ICMPGT:
  1.1046 +		case Opcodes.IF_ICMPLE:
  1.1047 +		case Opcodes.IF_ACMPEQ:
  1.1048 +		case Opcodes.IF_ACMPNE:
  1.1049 +		case Opcodes.LRETURN:
  1.1050 +		case Opcodes.DRETURN:
  1.1051 +			pop(2);
  1.1052 +			break;
  1.1053 +		case Opcodes.DUP:
  1.1054 +			t1 = pop();
  1.1055 +			push(t1);
  1.1056 +			push(t1);
  1.1057 +			break;
  1.1058 +		case Opcodes.DUP_X1:
  1.1059 +			t1 = pop();
  1.1060 +			t2 = pop();
  1.1061 +			push(t1);
  1.1062 +			push(t2);
  1.1063 +			push(t1);
  1.1064 +			break;
  1.1065 +		case Opcodes.DUP_X2:
  1.1066 +			t1 = pop();
  1.1067 +			t2 = pop();
  1.1068 +			t3 = pop();
  1.1069 +			push(t1);
  1.1070 +			push(t3);
  1.1071 +			push(t2);
  1.1072 +			push(t1);
  1.1073 +			break;
  1.1074 +		case Opcodes.DUP2:
  1.1075 +			t1 = pop();
  1.1076 +			t2 = pop();
  1.1077 +			push(t2);
  1.1078 +			push(t1);
  1.1079 +			push(t2);
  1.1080 +			push(t1);
  1.1081 +			break;
  1.1082 +		case Opcodes.DUP2_X1:
  1.1083 +			t1 = pop();
  1.1084 +			t2 = pop();
  1.1085 +			t3 = pop();
  1.1086 +			push(t2);
  1.1087 +			push(t1);
  1.1088 +			push(t3);
  1.1089 +			push(t2);
  1.1090 +			push(t1);
  1.1091 +			break;
  1.1092 +		case Opcodes.DUP2_X2:
  1.1093 +			t1 = pop();
  1.1094 +			t2 = pop();
  1.1095 +			t3 = pop();
  1.1096 +			t4 = pop();
  1.1097 +			push(t2);
  1.1098 +			push(t1);
  1.1099 +			push(t4);
  1.1100 +			push(t3);
  1.1101 +			push(t2);
  1.1102 +			push(t1);
  1.1103 +			break;
  1.1104 +		case Opcodes.SWAP:
  1.1105 +			t1 = pop();
  1.1106 +			t2 = pop();
  1.1107 +			push(t1);
  1.1108 +			push(t2);
  1.1109 +			break;
  1.1110 +		case Opcodes.IADD:
  1.1111 +		case Opcodes.ISUB:
  1.1112 +		case Opcodes.IMUL:
  1.1113 +		case Opcodes.IDIV:
  1.1114 +		case Opcodes.IREM:
  1.1115 +		case Opcodes.IAND:
  1.1116 +		case Opcodes.IOR:
  1.1117 +		case Opcodes.IXOR:
  1.1118 +		case Opcodes.ISHL:
  1.1119 +		case Opcodes.ISHR:
  1.1120 +		case Opcodes.IUSHR:
  1.1121 +		case Opcodes.L2I:
  1.1122 +		case Opcodes.D2I:
  1.1123 +		case Opcodes.FCMPL:
  1.1124 +		case Opcodes.FCMPG:
  1.1125 +			pop(2);
  1.1126 +			push(INTEGER);
  1.1127 +			break;
  1.1128 +		case Opcodes.LADD:
  1.1129 +		case Opcodes.LSUB:
  1.1130 +		case Opcodes.LMUL:
  1.1131 +		case Opcodes.LDIV:
  1.1132 +		case Opcodes.LREM:
  1.1133 +		case Opcodes.LAND:
  1.1134 +		case Opcodes.LOR:
  1.1135 +		case Opcodes.LXOR:
  1.1136 +			pop(4);
  1.1137 +			push(LONG);
  1.1138 +			push(TOP);
  1.1139 +			break;
  1.1140 +		case Opcodes.FADD:
  1.1141 +		case Opcodes.FSUB:
  1.1142 +		case Opcodes.FMUL:
  1.1143 +		case Opcodes.FDIV:
  1.1144 +		case Opcodes.FREM:
  1.1145 +		case Opcodes.L2F:
  1.1146 +		case Opcodes.D2F:
  1.1147 +			pop(2);
  1.1148 +			push(FLOAT);
  1.1149 +			break;
  1.1150 +		case Opcodes.DADD:
  1.1151 +		case Opcodes.DSUB:
  1.1152 +		case Opcodes.DMUL:
  1.1153 +		case Opcodes.DDIV:
  1.1154 +		case Opcodes.DREM:
  1.1155 +			pop(4);
  1.1156 +			push(DOUBLE);
  1.1157 +			push(TOP);
  1.1158 +			break;
  1.1159 +		case Opcodes.LSHL:
  1.1160 +		case Opcodes.LSHR:
  1.1161 +		case Opcodes.LUSHR:
  1.1162 +			pop(3);
  1.1163 +			push(LONG);
  1.1164 +			push(TOP);
  1.1165 +			break;
  1.1166 +		case Opcodes.IINC:
  1.1167 +			set(arg, INTEGER);
  1.1168 +			break;
  1.1169 +		case Opcodes.I2L:
  1.1170 +		case Opcodes.F2L:
  1.1171 +			pop(1);
  1.1172 +			push(LONG);
  1.1173 +			push(TOP);
  1.1174 +			break;
  1.1175 +		case Opcodes.I2F:
  1.1176 +			pop(1);
  1.1177 +			push(FLOAT);
  1.1178 +			break;
  1.1179 +		case Opcodes.I2D:
  1.1180 +		case Opcodes.F2D:
  1.1181 +			pop(1);
  1.1182 +			push(DOUBLE);
  1.1183 +			push(TOP);
  1.1184 +			break;
  1.1185 +		case Opcodes.F2I:
  1.1186 +		case Opcodes.ARRAYLENGTH:
  1.1187 +		case Opcodes.INSTANCEOF:
  1.1188 +			pop(1);
  1.1189 +			push(INTEGER);
  1.1190 +			break;
  1.1191 +		case Opcodes.LCMP:
  1.1192 +		case Opcodes.DCMPL:
  1.1193 +		case Opcodes.DCMPG:
  1.1194 +			pop(4);
  1.1195 +			push(INTEGER);
  1.1196 +			break;
  1.1197 +		case Opcodes.JSR:
  1.1198 +		case Opcodes.RET:
  1.1199 +			throw new RuntimeException("JSR/RET are not supported with computeFrames option");
  1.1200 +		case Opcodes.GETSTATIC:
  1.1201 +			push(cw, item.strVal3);
  1.1202 +			break;
  1.1203 +		case Opcodes.PUTSTATIC:
  1.1204 +			pop(item.strVal3);
  1.1205 +			break;
  1.1206 +		case Opcodes.GETFIELD:
  1.1207 +			pop(1);
  1.1208 +			push(cw, item.strVal3);
  1.1209 +			break;
  1.1210 +		case Opcodes.PUTFIELD:
  1.1211 +			pop(item.strVal3);
  1.1212 +			pop();
  1.1213 +			break;
  1.1214 +		case Opcodes.INVOKEVIRTUAL:
  1.1215 +		case Opcodes.INVOKESPECIAL:
  1.1216 +		case Opcodes.INVOKESTATIC:
  1.1217 +		case Opcodes.INVOKEINTERFACE:
  1.1218 +			pop(item.strVal3);
  1.1219 +			if(opcode != Opcodes.INVOKESTATIC)
  1.1220 +				{
  1.1221 +				t1 = pop();
  1.1222 +				if(opcode == Opcodes.INVOKESPECIAL
  1.1223 +				   && item.strVal2.charAt(0) == '<')
  1.1224 +					{
  1.1225 +					init(t1);
  1.1226 +					}
  1.1227 +				}
  1.1228 +			push(cw, item.strVal3);
  1.1229 +			break;
  1.1230 +		case Opcodes.NEW:
  1.1231 +			push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg));
  1.1232 +			break;
  1.1233 +		case Opcodes.NEWARRAY:
  1.1234 +			pop();
  1.1235 +			switch(arg)
  1.1236 +				{
  1.1237 +				case Opcodes.T_BOOLEAN:
  1.1238 +					push(ARRAY_OF | BOOLEAN);
  1.1239 +					break;
  1.1240 +				case Opcodes.T_CHAR:
  1.1241 +					push(ARRAY_OF | CHAR);
  1.1242 +					break;
  1.1243 +				case Opcodes.T_BYTE:
  1.1244 +					push(ARRAY_OF | BYTE);
  1.1245 +					break;
  1.1246 +				case Opcodes.T_SHORT:
  1.1247 +					push(ARRAY_OF | SHORT);
  1.1248 +					break;
  1.1249 +				case Opcodes.T_INT:
  1.1250 +					push(ARRAY_OF | INTEGER);
  1.1251 +					break;
  1.1252 +				case Opcodes.T_FLOAT:
  1.1253 +					push(ARRAY_OF | FLOAT);
  1.1254 +					break;
  1.1255 +				case Opcodes.T_DOUBLE:
  1.1256 +					push(ARRAY_OF | DOUBLE);
  1.1257 +					break;
  1.1258 +					// case Opcodes.T_LONG:
  1.1259 +				default:
  1.1260 +					push(ARRAY_OF | LONG);
  1.1261 +					break;
  1.1262 +				}
  1.1263 +			break;
  1.1264 +		case Opcodes.ANEWARRAY:
  1.1265 +			String s = item.strVal1;
  1.1266 +			pop();
  1.1267 +			if(s.charAt(0) == '[')
  1.1268 +				{
  1.1269 +				push(cw, "[" + s);
  1.1270 +				}
  1.1271 +			else
  1.1272 +				{
  1.1273 +				push(ARRAY_OF | OBJECT | cw.addType(s));
  1.1274 +				}
  1.1275 +			break;
  1.1276 +		case Opcodes.CHECKCAST:
  1.1277 +			s = item.strVal1;
  1.1278 +			pop();
  1.1279 +			if(s.charAt(0) == '[')
  1.1280 +				{
  1.1281 +				push(cw, s);
  1.1282 +				}
  1.1283 +			else
  1.1284 +				{
  1.1285 +				push(OBJECT | cw.addType(s));
  1.1286 +				}
  1.1287 +			break;
  1.1288 +			// case Opcodes.MULTIANEWARRAY:
  1.1289 +		default:
  1.1290 +			pop(arg);
  1.1291 +			push(cw, item.strVal1);
  1.1292 +			break;
  1.1293 +		}
  1.1294 +}
  1.1295 +
  1.1296 +/**
  1.1297 + * Merges the input frame of the given basic block with the input and output
  1.1298 + * frames of this basic block. Returns <tt>true</tt> if the input frame of
  1.1299 + * the given label has been changed by this operation.
  1.1300 + *
  1.1301 + * @param cw    the ClassWriter to which this label belongs.
  1.1302 + * @param frame the basic block whose input frame must be updated.
  1.1303 + * @param edge  the kind of the {@link Edge} between this label and 'label'.
  1.1304 + *              See {@link Edge#info}.
  1.1305 + * @return <tt>true</tt> if the input frame of the given label has been
  1.1306 + *         changed by this operation.
  1.1307 + */
  1.1308 +boolean merge(final ClassWriter cw, final Frame frame, final int edge){
  1.1309 +	boolean changed = false;
  1.1310 +	int i, s, dim, kind, t;
  1.1311 +
  1.1312 +	int nLocal = inputLocals.length;
  1.1313 +	int nStack = inputStack.length;
  1.1314 +	if(frame.inputLocals == null)
  1.1315 +		{
  1.1316 +		frame.inputLocals = new int[nLocal];
  1.1317 +		changed = true;
  1.1318 +		}
  1.1319 +
  1.1320 +	for(i = 0; i < nLocal; ++i)
  1.1321 +		{
  1.1322 +		if(outputLocals != null && i < outputLocals.length)
  1.1323 +			{
  1.1324 +			s = outputLocals[i];
  1.1325 +			if(s == 0)
  1.1326 +				{
  1.1327 +				t = inputLocals[i];
  1.1328 +				}
  1.1329 +			else
  1.1330 +				{
  1.1331 +				dim = s & DIM;
  1.1332 +				kind = s & KIND;
  1.1333 +				if(kind == LOCAL)
  1.1334 +					{
  1.1335 +					t = dim + inputLocals[s & VALUE];
  1.1336 +					}
  1.1337 +				else if(kind == STACK)
  1.1338 +					{
  1.1339 +					t = dim + inputStack[nStack - (s & VALUE)];
  1.1340 +					}
  1.1341 +				else
  1.1342 +					{
  1.1343 +					t = s;
  1.1344 +					}
  1.1345 +				}
  1.1346 +			}
  1.1347 +		else
  1.1348 +			{
  1.1349 +			t = inputLocals[i];
  1.1350 +			}
  1.1351 +		if(initializations != null)
  1.1352 +			{
  1.1353 +			t = init(cw, t);
  1.1354 +			}
  1.1355 +		changed |= merge(cw, t, frame.inputLocals, i);
  1.1356 +		}
  1.1357 +
  1.1358 +	if(edge > 0)
  1.1359 +		{
  1.1360 +		for(i = 0; i < nLocal; ++i)
  1.1361 +			{
  1.1362 +			t = inputLocals[i];
  1.1363 +			changed |= merge(cw, t, frame.inputLocals, i);
  1.1364 +			}
  1.1365 +		if(frame.inputStack == null)
  1.1366 +			{
  1.1367 +			frame.inputStack = new int[1];
  1.1368 +			changed = true;
  1.1369 +			}
  1.1370 +		changed |= merge(cw, edge, frame.inputStack, 0);
  1.1371 +		return changed;
  1.1372 +		}
  1.1373 +
  1.1374 +	int nInputStack = inputStack.length + owner.inputStackTop;
  1.1375 +	if(frame.inputStack == null)
  1.1376 +		{
  1.1377 +		frame.inputStack = new int[nInputStack + outputStackTop];
  1.1378 +		changed = true;
  1.1379 +		}
  1.1380 +
  1.1381 +	for(i = 0; i < nInputStack; ++i)
  1.1382 +		{
  1.1383 +		t = inputStack[i];
  1.1384 +		if(initializations != null)
  1.1385 +			{
  1.1386 +			t = init(cw, t);
  1.1387 +			}
  1.1388 +		changed |= merge(cw, t, frame.inputStack, i);
  1.1389 +		}
  1.1390 +	for(i = 0; i < outputStackTop; ++i)
  1.1391 +		{
  1.1392 +		s = outputStack[i];
  1.1393 +		dim = s & DIM;
  1.1394 +		kind = s & KIND;
  1.1395 +		if(kind == LOCAL)
  1.1396 +			{
  1.1397 +			t = dim + inputLocals[s & VALUE];
  1.1398 +			}
  1.1399 +		else if(kind == STACK)
  1.1400 +			{
  1.1401 +			t = dim + inputStack[nStack - (s & VALUE)];
  1.1402 +			}
  1.1403 +		else
  1.1404 +			{
  1.1405 +			t = s;
  1.1406 +			}
  1.1407 +		if(initializations != null)
  1.1408 +			{
  1.1409 +			t = init(cw, t);
  1.1410 +			}
  1.1411 +		changed |= merge(cw, t, frame.inputStack, nInputStack + i);
  1.1412 +		}
  1.1413 +	return changed;
  1.1414 +}
  1.1415 +
  1.1416 +/**
  1.1417 + * Merges the type at the given index in the given type array with the given
  1.1418 + * type. Returns <tt>true</tt> if the type array has been modified by this
  1.1419 + * operation.
  1.1420 + *
  1.1421 + * @param cw    the ClassWriter to which this label belongs.
  1.1422 + * @param t     the type with which the type array element must be merged.
  1.1423 + * @param types an array of types.
  1.1424 + * @param index the index of the type that must be merged in 'types'.
  1.1425 + * @return <tt>true</tt> if the type array has been modified by this
  1.1426 + *         operation.
  1.1427 + */
  1.1428 +private boolean merge(
  1.1429 +		final ClassWriter cw,
  1.1430 +		int t,
  1.1431 +		final int[] types,
  1.1432 +		final int index){
  1.1433 +	int u = types[index];
  1.1434 +	if(u == t)
  1.1435 +		{
  1.1436 +		// if the types are equal, merge(u,t)=u, so there is no change
  1.1437 +		return false;
  1.1438 +		}
  1.1439 +	if((t & ~DIM) == NULL)
  1.1440 +		{
  1.1441 +		if(u == NULL)
  1.1442 +			{
  1.1443 +			return false;
  1.1444 +			}
  1.1445 +		t = NULL;
  1.1446 +		}
  1.1447 +	if(u == 0)
  1.1448 +		{
  1.1449 +		// if types[index] has never been assigned, merge(u,t)=t
  1.1450 +		types[index] = t;
  1.1451 +		return true;
  1.1452 +		}
  1.1453 +	int v;
  1.1454 +	if((u & BASE_KIND) == OBJECT || (u & DIM) != 0)
  1.1455 +		{
  1.1456 +		// if u is a reference type of any dimension
  1.1457 +		if(t == NULL)
  1.1458 +			{
  1.1459 +			// if t is the NULL type, merge(u,t)=u, so there is no change
  1.1460 +			return false;
  1.1461 +			}
  1.1462 +		else if((t & (DIM | BASE_KIND)) == (u & (DIM | BASE_KIND)))
  1.1463 +			{
  1.1464 +			if((u & BASE_KIND) == OBJECT)
  1.1465 +				{
  1.1466 +				// if t is also a reference type, and if u and t have the
  1.1467 +				// same dimension merge(u,t) = dim(t) | common parent of the
  1.1468 +				// element types of u and t
  1.1469 +				v = (t & DIM) | OBJECT
  1.1470 +				    | cw.getMergedType(t & BASE_VALUE, u & BASE_VALUE);
  1.1471 +				}
  1.1472 +			else
  1.1473 +				{
  1.1474 +				// if u and t are array types, but not with the same element
  1.1475 +				// type, merge(u,t)=java/lang/Object
  1.1476 +				v = OBJECT | cw.addType("java/lang/Object");
  1.1477 +				}
  1.1478 +			}
  1.1479 +		else if((t & BASE_KIND) == OBJECT || (t & DIM) != 0)
  1.1480 +			{
  1.1481 +			// if t is any other reference or array type,
  1.1482 +			// merge(u,t)=java/lang/Object
  1.1483 +			v = OBJECT | cw.addType("java/lang/Object");
  1.1484 +			}
  1.1485 +		else
  1.1486 +			{
  1.1487 +			// if t is any other type, merge(u,t)=TOP
  1.1488 +			v = TOP;
  1.1489 +			}
  1.1490 +		}
  1.1491 +	else if(u == NULL)
  1.1492 +		{
  1.1493 +		// if u is the NULL type, merge(u,t)=t,
  1.1494 +		// or TOP if t is not a reference type
  1.1495 +		v = (t & BASE_KIND) == OBJECT || (t & DIM) != 0 ? t : TOP;
  1.1496 +		}
  1.1497 +	else
  1.1498 +		{
  1.1499 +		// if u is any other type, merge(u,t)=TOP whatever t
  1.1500 +		v = TOP;
  1.1501 +		}
  1.1502 +	if(u != v)
  1.1503 +		{
  1.1504 +		types[index] = v;
  1.1505 +		return true;
  1.1506 +		}
  1.1507 +	return false;
  1.1508 +}
  1.1509 +}