annotate 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
rev   line source
rlm@10 1 /***
rlm@10 2 * ASM: a very small and fast Java bytecode manipulation framework
rlm@10 3 * Copyright (c) 2000-2005 INRIA, France Telecom
rlm@10 4 * All rights reserved.
rlm@10 5 *
rlm@10 6 * Redistribution and use in source and binary forms, with or without
rlm@10 7 * modification, are permitted provided that the following conditions
rlm@10 8 * are met:
rlm@10 9 * 1. Redistributions of source code must retain the above copyright
rlm@10 10 * notice, this list of conditions and the following disclaimer.
rlm@10 11 * 2. Redistributions in binary form must reproduce the above copyright
rlm@10 12 * notice, this list of conditions and the following disclaimer in the
rlm@10 13 * documentation and/or other materials provided with the distribution.
rlm@10 14 * 3. Neither the name of the copyright holders nor the names of its
rlm@10 15 * contributors may be used to endorse or promote products derived from
rlm@10 16 * this software without specific prior written permission.
rlm@10 17 *
rlm@10 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
rlm@10 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
rlm@10 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
rlm@10 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
rlm@10 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
rlm@10 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
rlm@10 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
rlm@10 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
rlm@10 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
rlm@10 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
rlm@10 28 * THE POSSIBILITY OF SUCH DAMAGE.
rlm@10 29 */
rlm@10 30 package clojure.asm;
rlm@10 31
rlm@10 32 /**
rlm@10 33 * Information about the input and output stack map frames of a basic block.
rlm@10 34 *
rlm@10 35 * @author Eric Bruneton
rlm@10 36 */
rlm@10 37 final class Frame{
rlm@10 38
rlm@10 39 /*
rlm@10 40 * Frames are computed in a two steps process: during the visit of each
rlm@10 41 * instruction, the state of the frame at the end of current basic block is
rlm@10 42 * updated by simulating the action of the instruction on the previous state
rlm@10 43 * of this so called "output frame". In visitMaxs, a fix point algorithm is
rlm@10 44 * used to compute the "input frame" of each basic block, i.e. the stack map
rlm@10 45 * frame at the begining of the basic block, starting from the input frame
rlm@10 46 * of the first basic block (which is computed from the method descriptor),
rlm@10 47 * and by using the previously computed output frames to compute the input
rlm@10 48 * state of the other blocks.
rlm@10 49 *
rlm@10 50 * All output and input frames are stored as arrays of integers. Reference
rlm@10 51 * and array types are represented by an index into a type table (which is
rlm@10 52 * not the same as the constant pool of the class, in order to avoid adding
rlm@10 53 * unnecessary constants in the pool - not all computed frames will end up
rlm@10 54 * being stored in the stack map table). This allows very fast type
rlm@10 55 * comparisons.
rlm@10 56 *
rlm@10 57 * Output stack map frames are computed relatively to the input frame of the
rlm@10 58 * basic block, which is not yet known when output frames are computed. It
rlm@10 59 * is therefore necessary to be able to represent abstract types such as
rlm@10 60 * "the type at position x in the input frame locals" or "the type at
rlm@10 61 * position x from the top of the input frame stack" or even "the type at
rlm@10 62 * position x in the input frame, with y more (or less) array dimensions".
rlm@10 63 * This explains the rather complicated type format used in output frames.
rlm@10 64 *
rlm@10 65 * This format is the following: DIM KIND VALUE (4, 4 and 24 bits). DIM is a
rlm@10 66 * signed number of array dimensions (from -8 to 7). KIND is either BASE,
rlm@10 67 * LOCAL or STACK. BASE is used for types that are not relative to the input
rlm@10 68 * frame. LOCAL is used for types that are relative to the input local
rlm@10 69 * variable types. STACK is used for types that are relative to the input
rlm@10 70 * stack types. VALUE depends on KIND. For LOCAL types, it is an index in
rlm@10 71 * the input local variable types. For STACK types, it is a position
rlm@10 72 * relatively to the top of input frame stack. For BASE types, it is either
rlm@10 73 * one of the constants defined in FrameVisitor, or for OBJECT and
rlm@10 74 * UNINITIALIZED types, a tag and an index in the type table.
rlm@10 75 *
rlm@10 76 * Output frames can contain types of any kind and with a positive or
rlm@10 77 * negative dimension (and even unassigned types, represented by 0 - which
rlm@10 78 * does not correspond to any valid type value). Input frames can only
rlm@10 79 * contain BASE types of positive or null dimension. In all cases the type
rlm@10 80 * table contains only internal type names (array type descriptors are
rlm@10 81 * forbidden - dimensions must be represented through the DIM field).
rlm@10 82 *
rlm@10 83 * The LONG and DOUBLE types are always represented by using two slots (LONG +
rlm@10 84 * TOP or DOUBLE + TOP), for local variable types as well as in the operand
rlm@10 85 * stack. This is necessary to be able to simulate DUPx_y instructions,
rlm@10 86 * whose effect would be dependent on the actual type values if types were
rlm@10 87 * always represented by a single slot in the stack (and this is not
rlm@10 88 * possible, since actual type values are not always known - cf LOCAL and
rlm@10 89 * STACK type kinds).
rlm@10 90 */
rlm@10 91
rlm@10 92 /**
rlm@10 93 * Mask to get the dimension of a frame type. This dimension is a signed
rlm@10 94 * integer between -8 and 7.
rlm@10 95 */
rlm@10 96 final static int DIM = 0xF0000000;
rlm@10 97
rlm@10 98 /**
rlm@10 99 * Constant to be added to a type to get a type with one more dimension.
rlm@10 100 */
rlm@10 101 final static int ARRAY_OF = 0x10000000;
rlm@10 102
rlm@10 103 /**
rlm@10 104 * Constant to be added to a type to get a type with one less dimension.
rlm@10 105 */
rlm@10 106 final static int ELEMENT_OF = 0xF0000000;
rlm@10 107
rlm@10 108 /**
rlm@10 109 * Mask to get the kind of a frame type.
rlm@10 110 *
rlm@10 111 * @see #BASE
rlm@10 112 * @see #LOCAL
rlm@10 113 * @see #STACK
rlm@10 114 */
rlm@10 115 final static int KIND = 0xF000000;
rlm@10 116
rlm@10 117 /**
rlm@10 118 * Mask to get the value of a frame type.
rlm@10 119 */
rlm@10 120 final static int VALUE = 0xFFFFFF;
rlm@10 121
rlm@10 122 /**
rlm@10 123 * Mask to get the kind of base types.
rlm@10 124 */
rlm@10 125 final static int BASE_KIND = 0xFF00000;
rlm@10 126
rlm@10 127 /**
rlm@10 128 * Mask to get the value of base types.
rlm@10 129 */
rlm@10 130 final static int BASE_VALUE = 0xFFFFF;
rlm@10 131
rlm@10 132 /**
rlm@10 133 * Kind of the types that are not relative to an input stack map frame.
rlm@10 134 */
rlm@10 135 final static int BASE = 0x1000000;
rlm@10 136
rlm@10 137 /**
rlm@10 138 * Base kind of the base reference types. The BASE_VALUE of such types is an
rlm@10 139 * index into the type table.
rlm@10 140 */
rlm@10 141 final static int OBJECT = BASE | 0x700000;
rlm@10 142
rlm@10 143 /**
rlm@10 144 * Base kind of the uninitialized base types. The BASE_VALUE of such types
rlm@10 145 * in an index into the type table (the Item at that index contains both an
rlm@10 146 * instruction offset and an internal class name).
rlm@10 147 */
rlm@10 148 final static int UNINITIALIZED = BASE | 0x800000;
rlm@10 149
rlm@10 150 /**
rlm@10 151 * Kind of the types that are relative to the local variable types of an
rlm@10 152 * input stack map frame. The value of such types is a local variable index.
rlm@10 153 */
rlm@10 154 private final static int LOCAL = 0x2000000;
rlm@10 155
rlm@10 156 /**
rlm@10 157 * Kind of the the types that are relative to the stack of an input stack
rlm@10 158 * map frame. The value of such types is a position relatively to the top of
rlm@10 159 * this stack.
rlm@10 160 */
rlm@10 161 private final static int STACK = 0x3000000;
rlm@10 162
rlm@10 163 /**
rlm@10 164 * The TOP type. This is a BASE type.
rlm@10 165 */
rlm@10 166 final static int TOP = BASE | 0;
rlm@10 167
rlm@10 168 /**
rlm@10 169 * The BOOLEAN type. This is a BASE type mainly used for array types.
rlm@10 170 */
rlm@10 171 final static int BOOLEAN = BASE | 9;
rlm@10 172
rlm@10 173 /**
rlm@10 174 * The BYTE type. This is a BASE type mainly used for array types.
rlm@10 175 */
rlm@10 176 final static int BYTE = BASE | 10;
rlm@10 177
rlm@10 178 /**
rlm@10 179 * The CHAR type. This is a BASE type mainly used for array types.
rlm@10 180 */
rlm@10 181 final static int CHAR = BASE | 11;
rlm@10 182
rlm@10 183 /**
rlm@10 184 * The SHORT type. This is a BASE type mainly used for array types.
rlm@10 185 */
rlm@10 186 final static int SHORT = BASE | 12;
rlm@10 187
rlm@10 188 /**
rlm@10 189 * The INTEGER type. This is a BASE type.
rlm@10 190 */
rlm@10 191 final static int INTEGER = BASE | 1;
rlm@10 192
rlm@10 193 /**
rlm@10 194 * The FLOAT type. This is a BASE type.
rlm@10 195 */
rlm@10 196 final static int FLOAT = BASE | 2;
rlm@10 197
rlm@10 198 /**
rlm@10 199 * The DOUBLE type. This is a BASE type.
rlm@10 200 */
rlm@10 201 final static int DOUBLE = BASE | 3;
rlm@10 202
rlm@10 203 /**
rlm@10 204 * The LONG type. This is a BASE type.
rlm@10 205 */
rlm@10 206 final static int LONG = BASE | 4;
rlm@10 207
rlm@10 208 /**
rlm@10 209 * The NULL type. This is a BASE type.
rlm@10 210 */
rlm@10 211 final static int NULL = BASE | 5;
rlm@10 212
rlm@10 213 /**
rlm@10 214 * The UNINITIALIZED_THIS type. This is a BASE type.
rlm@10 215 */
rlm@10 216 final static int UNINITIALIZED_THIS = BASE | 6;
rlm@10 217
rlm@10 218 /**
rlm@10 219 * The stack size variation corresponding to each JVM instruction. This
rlm@10 220 * stack variation is equal to the size of the values produced by an
rlm@10 221 * instruction, minus the size of the values consumed by this instruction.
rlm@10 222 */
rlm@10 223 final static int[] SIZE;
rlm@10 224
rlm@10 225 /**
rlm@10 226 * Computes the stack size variation corresponding to each JVM instruction.
rlm@10 227 */
rlm@10 228 static
rlm@10 229 {
rlm@10 230 int i;
rlm@10 231 int[] b = new int[202];
rlm@10 232 String s = "EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDD"
rlm@10 233 + "CDCDEEEEEEEEEEEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCD"
rlm@10 234 + "CDCEEEEDDDDDDDCDCDCEFEFDDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFED"
rlm@10 235 + "DDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE";
rlm@10 236 for(i = 0; i < b.length; ++i)
rlm@10 237 {
rlm@10 238 b[i] = s.charAt(i) - 'E';
rlm@10 239 }
rlm@10 240 SIZE = b;
rlm@10 241
rlm@10 242 // code to generate the above string
rlm@10 243 //
rlm@10 244 // int NA = 0; // not applicable (unused opcode or variable size opcode)
rlm@10 245 //
rlm@10 246 // b = new int[] {
rlm@10 247 // 0, //NOP, // visitInsn
rlm@10 248 // 1, //ACONST_NULL, // -
rlm@10 249 // 1, //ICONST_M1, // -
rlm@10 250 // 1, //ICONST_0, // -
rlm@10 251 // 1, //ICONST_1, // -
rlm@10 252 // 1, //ICONST_2, // -
rlm@10 253 // 1, //ICONST_3, // -
rlm@10 254 // 1, //ICONST_4, // -
rlm@10 255 // 1, //ICONST_5, // -
rlm@10 256 // 2, //LCONST_0, // -
rlm@10 257 // 2, //LCONST_1, // -
rlm@10 258 // 1, //FCONST_0, // -
rlm@10 259 // 1, //FCONST_1, // -
rlm@10 260 // 1, //FCONST_2, // -
rlm@10 261 // 2, //DCONST_0, // -
rlm@10 262 // 2, //DCONST_1, // -
rlm@10 263 // 1, //BIPUSH, // visitIntInsn
rlm@10 264 // 1, //SIPUSH, // -
rlm@10 265 // 1, //LDC, // visitLdcInsn
rlm@10 266 // NA, //LDC_W, // -
rlm@10 267 // NA, //LDC2_W, // -
rlm@10 268 // 1, //ILOAD, // visitVarInsn
rlm@10 269 // 2, //LLOAD, // -
rlm@10 270 // 1, //FLOAD, // -
rlm@10 271 // 2, //DLOAD, // -
rlm@10 272 // 1, //ALOAD, // -
rlm@10 273 // NA, //ILOAD_0, // -
rlm@10 274 // NA, //ILOAD_1, // -
rlm@10 275 // NA, //ILOAD_2, // -
rlm@10 276 // NA, //ILOAD_3, // -
rlm@10 277 // NA, //LLOAD_0, // -
rlm@10 278 // NA, //LLOAD_1, // -
rlm@10 279 // NA, //LLOAD_2, // -
rlm@10 280 // NA, //LLOAD_3, // -
rlm@10 281 // NA, //FLOAD_0, // -
rlm@10 282 // NA, //FLOAD_1, // -
rlm@10 283 // NA, //FLOAD_2, // -
rlm@10 284 // NA, //FLOAD_3, // -
rlm@10 285 // NA, //DLOAD_0, // -
rlm@10 286 // NA, //DLOAD_1, // -
rlm@10 287 // NA, //DLOAD_2, // -
rlm@10 288 // NA, //DLOAD_3, // -
rlm@10 289 // NA, //ALOAD_0, // -
rlm@10 290 // NA, //ALOAD_1, // -
rlm@10 291 // NA, //ALOAD_2, // -
rlm@10 292 // NA, //ALOAD_3, // -
rlm@10 293 // -1, //IALOAD, // visitInsn
rlm@10 294 // 0, //LALOAD, // -
rlm@10 295 // -1, //FALOAD, // -
rlm@10 296 // 0, //DALOAD, // -
rlm@10 297 // -1, //AALOAD, // -
rlm@10 298 // -1, //BALOAD, // -
rlm@10 299 // -1, //CALOAD, // -
rlm@10 300 // -1, //SALOAD, // -
rlm@10 301 // -1, //ISTORE, // visitVarInsn
rlm@10 302 // -2, //LSTORE, // -
rlm@10 303 // -1, //FSTORE, // -
rlm@10 304 // -2, //DSTORE, // -
rlm@10 305 // -1, //ASTORE, // -
rlm@10 306 // NA, //ISTORE_0, // -
rlm@10 307 // NA, //ISTORE_1, // -
rlm@10 308 // NA, //ISTORE_2, // -
rlm@10 309 // NA, //ISTORE_3, // -
rlm@10 310 // NA, //LSTORE_0, // -
rlm@10 311 // NA, //LSTORE_1, // -
rlm@10 312 // NA, //LSTORE_2, // -
rlm@10 313 // NA, //LSTORE_3, // -
rlm@10 314 // NA, //FSTORE_0, // -
rlm@10 315 // NA, //FSTORE_1, // -
rlm@10 316 // NA, //FSTORE_2, // -
rlm@10 317 // NA, //FSTORE_3, // -
rlm@10 318 // NA, //DSTORE_0, // -
rlm@10 319 // NA, //DSTORE_1, // -
rlm@10 320 // NA, //DSTORE_2, // -
rlm@10 321 // NA, //DSTORE_3, // -
rlm@10 322 // NA, //ASTORE_0, // -
rlm@10 323 // NA, //ASTORE_1, // -
rlm@10 324 // NA, //ASTORE_2, // -
rlm@10 325 // NA, //ASTORE_3, // -
rlm@10 326 // -3, //IASTORE, // visitInsn
rlm@10 327 // -4, //LASTORE, // -
rlm@10 328 // -3, //FASTORE, // -
rlm@10 329 // -4, //DASTORE, // -
rlm@10 330 // -3, //AASTORE, // -
rlm@10 331 // -3, //BASTORE, // -
rlm@10 332 // -3, //CASTORE, // -
rlm@10 333 // -3, //SASTORE, // -
rlm@10 334 // -1, //POP, // -
rlm@10 335 // -2, //POP2, // -
rlm@10 336 // 1, //DUP, // -
rlm@10 337 // 1, //DUP_X1, // -
rlm@10 338 // 1, //DUP_X2, // -
rlm@10 339 // 2, //DUP2, // -
rlm@10 340 // 2, //DUP2_X1, // -
rlm@10 341 // 2, //DUP2_X2, // -
rlm@10 342 // 0, //SWAP, // -
rlm@10 343 // -1, //IADD, // -
rlm@10 344 // -2, //LADD, // -
rlm@10 345 // -1, //FADD, // -
rlm@10 346 // -2, //DADD, // -
rlm@10 347 // -1, //ISUB, // -
rlm@10 348 // -2, //LSUB, // -
rlm@10 349 // -1, //FSUB, // -
rlm@10 350 // -2, //DSUB, // -
rlm@10 351 // -1, //IMUL, // -
rlm@10 352 // -2, //LMUL, // -
rlm@10 353 // -1, //FMUL, // -
rlm@10 354 // -2, //DMUL, // -
rlm@10 355 // -1, //IDIV, // -
rlm@10 356 // -2, //LDIV, // -
rlm@10 357 // -1, //FDIV, // -
rlm@10 358 // -2, //DDIV, // -
rlm@10 359 // -1, //IREM, // -
rlm@10 360 // -2, //LREM, // -
rlm@10 361 // -1, //FREM, // -
rlm@10 362 // -2, //DREM, // -
rlm@10 363 // 0, //INEG, // -
rlm@10 364 // 0, //LNEG, // -
rlm@10 365 // 0, //FNEG, // -
rlm@10 366 // 0, //DNEG, // -
rlm@10 367 // -1, //ISHL, // -
rlm@10 368 // -1, //LSHL, // -
rlm@10 369 // -1, //ISHR, // -
rlm@10 370 // -1, //LSHR, // -
rlm@10 371 // -1, //IUSHR, // -
rlm@10 372 // -1, //LUSHR, // -
rlm@10 373 // -1, //IAND, // -
rlm@10 374 // -2, //LAND, // -
rlm@10 375 // -1, //IOR, // -
rlm@10 376 // -2, //LOR, // -
rlm@10 377 // -1, //IXOR, // -
rlm@10 378 // -2, //LXOR, // -
rlm@10 379 // 0, //IINC, // visitIincInsn
rlm@10 380 // 1, //I2L, // visitInsn
rlm@10 381 // 0, //I2F, // -
rlm@10 382 // 1, //I2D, // -
rlm@10 383 // -1, //L2I, // -
rlm@10 384 // -1, //L2F, // -
rlm@10 385 // 0, //L2D, // -
rlm@10 386 // 0, //F2I, // -
rlm@10 387 // 1, //F2L, // -
rlm@10 388 // 1, //F2D, // -
rlm@10 389 // -1, //D2I, // -
rlm@10 390 // 0, //D2L, // -
rlm@10 391 // -1, //D2F, // -
rlm@10 392 // 0, //I2B, // -
rlm@10 393 // 0, //I2C, // -
rlm@10 394 // 0, //I2S, // -
rlm@10 395 // -3, //LCMP, // -
rlm@10 396 // -1, //FCMPL, // -
rlm@10 397 // -1, //FCMPG, // -
rlm@10 398 // -3, //DCMPL, // -
rlm@10 399 // -3, //DCMPG, // -
rlm@10 400 // -1, //IFEQ, // visitJumpInsn
rlm@10 401 // -1, //IFNE, // -
rlm@10 402 // -1, //IFLT, // -
rlm@10 403 // -1, //IFGE, // -
rlm@10 404 // -1, //IFGT, // -
rlm@10 405 // -1, //IFLE, // -
rlm@10 406 // -2, //IF_ICMPEQ, // -
rlm@10 407 // -2, //IF_ICMPNE, // -
rlm@10 408 // -2, //IF_ICMPLT, // -
rlm@10 409 // -2, //IF_ICMPGE, // -
rlm@10 410 // -2, //IF_ICMPGT, // -
rlm@10 411 // -2, //IF_ICMPLE, // -
rlm@10 412 // -2, //IF_ACMPEQ, // -
rlm@10 413 // -2, //IF_ACMPNE, // -
rlm@10 414 // 0, //GOTO, // -
rlm@10 415 // 1, //JSR, // -
rlm@10 416 // 0, //RET, // visitVarInsn
rlm@10 417 // -1, //TABLESWITCH, // visiTableSwitchInsn
rlm@10 418 // -1, //LOOKUPSWITCH, // visitLookupSwitch
rlm@10 419 // -1, //IRETURN, // visitInsn
rlm@10 420 // -2, //LRETURN, // -
rlm@10 421 // -1, //FRETURN, // -
rlm@10 422 // -2, //DRETURN, // -
rlm@10 423 // -1, //ARETURN, // -
rlm@10 424 // 0, //RETURN, // -
rlm@10 425 // NA, //GETSTATIC, // visitFieldInsn
rlm@10 426 // NA, //PUTSTATIC, // -
rlm@10 427 // NA, //GETFIELD, // -
rlm@10 428 // NA, //PUTFIELD, // -
rlm@10 429 // NA, //INVOKEVIRTUAL, // visitMethodInsn
rlm@10 430 // NA, //INVOKESPECIAL, // -
rlm@10 431 // NA, //INVOKESTATIC, // -
rlm@10 432 // NA, //INVOKEINTERFACE, // -
rlm@10 433 // NA, //UNUSED, // NOT VISITED
rlm@10 434 // 1, //NEW, // visitTypeInsn
rlm@10 435 // 0, //NEWARRAY, // visitIntInsn
rlm@10 436 // 0, //ANEWARRAY, // visitTypeInsn
rlm@10 437 // 0, //ARRAYLENGTH, // visitInsn
rlm@10 438 // NA, //ATHROW, // -
rlm@10 439 // 0, //CHECKCAST, // visitTypeInsn
rlm@10 440 // 0, //INSTANCEOF, // -
rlm@10 441 // -1, //MONITORENTER, // visitInsn
rlm@10 442 // -1, //MONITOREXIT, // -
rlm@10 443 // NA, //WIDE, // NOT VISITED
rlm@10 444 // NA, //MULTIANEWARRAY, // visitMultiANewArrayInsn
rlm@10 445 // -1, //IFNULL, // visitJumpInsn
rlm@10 446 // -1, //IFNONNULL, // -
rlm@10 447 // NA, //GOTO_W, // -
rlm@10 448 // NA, //JSR_W, // -
rlm@10 449 // };
rlm@10 450 // for (i = 0; i < b.length; ++i) {
rlm@10 451 // System.err.print((char)('E' + b[i]));
rlm@10 452 // }
rlm@10 453 // System.err.println();
rlm@10 454 }
rlm@10 455
rlm@10 456 /**
rlm@10 457 * The label (i.e. basic block) to which these input and output stack map
rlm@10 458 * frames correspond.
rlm@10 459 */
rlm@10 460 Label owner;
rlm@10 461
rlm@10 462 /**
rlm@10 463 * The input stack map frame locals.
rlm@10 464 */
rlm@10 465 int[] inputLocals;
rlm@10 466
rlm@10 467 /**
rlm@10 468 * The input stack map frame stack.
rlm@10 469 */
rlm@10 470 int[] inputStack;
rlm@10 471
rlm@10 472 /**
rlm@10 473 * The output stack map frame locals.
rlm@10 474 */
rlm@10 475 private int[] outputLocals;
rlm@10 476
rlm@10 477 /**
rlm@10 478 * The output stack map frame stack.
rlm@10 479 */
rlm@10 480 private int[] outputStack;
rlm@10 481
rlm@10 482 /**
rlm@10 483 * Relative size of the output stack. The exact semantics of this field
rlm@10 484 * depends on the algorithm that is used.
rlm@10 485 * <p/>
rlm@10 486 * When only the maximum stack size is computed, this field is the size of
rlm@10 487 * the output stack relatively to the top of the input stack.
rlm@10 488 * <p/>
rlm@10 489 * When the stack map frames are completely computed, this field is the
rlm@10 490 * actual number of types in {@link #outputStack}.
rlm@10 491 */
rlm@10 492 private int outputStackTop;
rlm@10 493
rlm@10 494 /**
rlm@10 495 * Number of types that are initialized in the basic block.
rlm@10 496 *
rlm@10 497 * @see #initializations
rlm@10 498 */
rlm@10 499 private int initializationCount;
rlm@10 500
rlm@10 501 /**
rlm@10 502 * The types that are initialized in the basic block. A constructor
rlm@10 503 * invocation on an UNINITIALIZED or UNINITIALIZED_THIS type must replace
rlm@10 504 * <i>every occurence</i> of this type in the local variables and in the
rlm@10 505 * operand stack. This cannot be done during the first phase of the
rlm@10 506 * algorithm since, during this phase, the local variables and the operand
rlm@10 507 * stack are not completely computed. It is therefore necessary to store the
rlm@10 508 * types on which constructors are invoked in the basic block, in order to
rlm@10 509 * do this replacement during the second phase of the algorithm, where the
rlm@10 510 * frames are fully computed. Note that this array can contain types that
rlm@10 511 * are relative to input locals or to the input stack (see below for the
rlm@10 512 * description of the algorithm).
rlm@10 513 */
rlm@10 514 private int[] initializations;
rlm@10 515
rlm@10 516 /**
rlm@10 517 * Returns the output frame local variable type at the given index.
rlm@10 518 *
rlm@10 519 * @param local the index of the local that must be returned.
rlm@10 520 * @return the output frame local variable type at the given index.
rlm@10 521 */
rlm@10 522 private int get(final int local){
rlm@10 523 if(outputLocals == null || local >= outputLocals.length)
rlm@10 524 {
rlm@10 525 // this local has never been assigned in this basic block,
rlm@10 526 // so it is still equal to its value in the input frame
rlm@10 527 return LOCAL | local;
rlm@10 528 }
rlm@10 529 else
rlm@10 530 {
rlm@10 531 int type = outputLocals[local];
rlm@10 532 if(type == 0)
rlm@10 533 {
rlm@10 534 // this local has never been assigned in this basic block,
rlm@10 535 // so it is still equal to its value in the input frame
rlm@10 536 type = outputLocals[local] = LOCAL | local;
rlm@10 537 }
rlm@10 538 return type;
rlm@10 539 }
rlm@10 540 }
rlm@10 541
rlm@10 542 /**
rlm@10 543 * Sets the output frame local variable type at the given index.
rlm@10 544 *
rlm@10 545 * @param local the index of the local that must be set.
rlm@10 546 * @param type the value of the local that must be set.
rlm@10 547 */
rlm@10 548 private void set(final int local, final int type){
rlm@10 549 // creates and/or resizes the output local variables array if necessary
rlm@10 550 if(outputLocals == null)
rlm@10 551 {
rlm@10 552 outputLocals = new int[10];
rlm@10 553 }
rlm@10 554 int n = outputLocals.length;
rlm@10 555 if(local >= n)
rlm@10 556 {
rlm@10 557 int[] t = new int[Math.max(local + 1, 2 * n)];
rlm@10 558 System.arraycopy(outputLocals, 0, t, 0, n);
rlm@10 559 outputLocals = t;
rlm@10 560 }
rlm@10 561 // sets the local variable
rlm@10 562 outputLocals[local] = type;
rlm@10 563 }
rlm@10 564
rlm@10 565 /**
rlm@10 566 * Pushes a new type onto the output frame stack.
rlm@10 567 *
rlm@10 568 * @param type the type that must be pushed.
rlm@10 569 */
rlm@10 570 private void push(final int type){
rlm@10 571 // creates and/or resizes the output stack array if necessary
rlm@10 572 if(outputStack == null)
rlm@10 573 {
rlm@10 574 outputStack = new int[10];
rlm@10 575 }
rlm@10 576 int n = outputStack.length;
rlm@10 577 if(outputStackTop >= n)
rlm@10 578 {
rlm@10 579 int[] t = new int[Math.max(outputStackTop + 1, 2 * n)];
rlm@10 580 System.arraycopy(outputStack, 0, t, 0, n);
rlm@10 581 outputStack = t;
rlm@10 582 }
rlm@10 583 // pushes the type on the output stack
rlm@10 584 outputStack[outputStackTop++] = type;
rlm@10 585 // updates the maximun height reached by the output stack, if needed
rlm@10 586 int top = owner.inputStackTop + outputStackTop;
rlm@10 587 if(top > owner.outputStackMax)
rlm@10 588 {
rlm@10 589 owner.outputStackMax = top;
rlm@10 590 }
rlm@10 591 }
rlm@10 592
rlm@10 593 /**
rlm@10 594 * Pushes a new type onto the output frame stack.
rlm@10 595 *
rlm@10 596 * @param cw the ClassWriter to which this label belongs.
rlm@10 597 * @param desc the descriptor of the type to be pushed. Can also be a method
rlm@10 598 * descriptor (in this case this method pushes its return type onto
rlm@10 599 * the output frame stack).
rlm@10 600 */
rlm@10 601 private void push(final ClassWriter cw, final String desc){
rlm@10 602 int type = type(cw, desc);
rlm@10 603 if(type != 0)
rlm@10 604 {
rlm@10 605 push(type);
rlm@10 606 if(type == LONG || type == DOUBLE)
rlm@10 607 {
rlm@10 608 push(TOP);
rlm@10 609 }
rlm@10 610 }
rlm@10 611 }
rlm@10 612
rlm@10 613 /**
rlm@10 614 * Returns the int encoding of the given type.
rlm@10 615 *
rlm@10 616 * @param cw the ClassWriter to which this label belongs.
rlm@10 617 * @param desc a type descriptor.
rlm@10 618 * @return the int encoding of the given type.
rlm@10 619 */
rlm@10 620 private int type(final ClassWriter cw, final String desc){
rlm@10 621 String t;
rlm@10 622 int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
rlm@10 623 switch(desc.charAt(index))
rlm@10 624 {
rlm@10 625 case'V':
rlm@10 626 return 0;
rlm@10 627 case'Z':
rlm@10 628 case'C':
rlm@10 629 case'B':
rlm@10 630 case'S':
rlm@10 631 case'I':
rlm@10 632 return INTEGER;
rlm@10 633 case'F':
rlm@10 634 return FLOAT;
rlm@10 635 case'J':
rlm@10 636 return LONG;
rlm@10 637 case'D':
rlm@10 638 return DOUBLE;
rlm@10 639 case'L':
rlm@10 640 // stores the internal name, not the descriptor!
rlm@10 641 t = desc.substring(index + 1, desc.length() - 1);
rlm@10 642 return OBJECT | cw.addType(t);
rlm@10 643 // case '[':
rlm@10 644 default:
rlm@10 645 // extracts the dimensions and the element type
rlm@10 646 int data;
rlm@10 647 int dims = index + 1;
rlm@10 648 while(desc.charAt(dims) == '[')
rlm@10 649 {
rlm@10 650 ++dims;
rlm@10 651 }
rlm@10 652 switch(desc.charAt(dims))
rlm@10 653 {
rlm@10 654 case'Z':
rlm@10 655 data = BOOLEAN;
rlm@10 656 break;
rlm@10 657 case'C':
rlm@10 658 data = CHAR;
rlm@10 659 break;
rlm@10 660 case'B':
rlm@10 661 data = BYTE;
rlm@10 662 break;
rlm@10 663 case'S':
rlm@10 664 data = SHORT;
rlm@10 665 break;
rlm@10 666 case'I':
rlm@10 667 data = INTEGER;
rlm@10 668 break;
rlm@10 669 case'F':
rlm@10 670 data = FLOAT;
rlm@10 671 break;
rlm@10 672 case'J':
rlm@10 673 data = LONG;
rlm@10 674 break;
rlm@10 675 case'D':
rlm@10 676 data = DOUBLE;
rlm@10 677 break;
rlm@10 678 // case 'L':
rlm@10 679 default:
rlm@10 680 // stores the internal name, not the descriptor
rlm@10 681 t = desc.substring(dims + 1, desc.length() - 1);
rlm@10 682 data = OBJECT | cw.addType(t);
rlm@10 683 }
rlm@10 684 return (dims - index) << 28 | data;
rlm@10 685 }
rlm@10 686 }
rlm@10 687
rlm@10 688 /**
rlm@10 689 * Pops a type from the output frame stack and returns its value.
rlm@10 690 *
rlm@10 691 * @return the type that has been popped from the output frame stack.
rlm@10 692 */
rlm@10 693 private int pop(){
rlm@10 694 if(outputStackTop > 0)
rlm@10 695 {
rlm@10 696 return outputStack[--outputStackTop];
rlm@10 697 }
rlm@10 698 else
rlm@10 699 {
rlm@10 700 // if the output frame stack is empty, pops from the input stack
rlm@10 701 return STACK | -(--owner.inputStackTop);
rlm@10 702 }
rlm@10 703 }
rlm@10 704
rlm@10 705 /**
rlm@10 706 * Pops the given number of types from the output frame stack.
rlm@10 707 *
rlm@10 708 * @param elements the number of types that must be popped.
rlm@10 709 */
rlm@10 710 private void pop(final int elements){
rlm@10 711 if(outputStackTop >= elements)
rlm@10 712 {
rlm@10 713 outputStackTop -= elements;
rlm@10 714 }
rlm@10 715 else
rlm@10 716 {
rlm@10 717 // if the number of elements to be popped is greater than the number
rlm@10 718 // of elements in the output stack, clear it, and pops the remaining
rlm@10 719 // elements from the input stack.
rlm@10 720 owner.inputStackTop -= elements - outputStackTop;
rlm@10 721 outputStackTop = 0;
rlm@10 722 }
rlm@10 723 }
rlm@10 724
rlm@10 725 /**
rlm@10 726 * Pops a type from the output frame stack.
rlm@10 727 *
rlm@10 728 * @param desc the descriptor of the type to be popped. Can also be a method
rlm@10 729 * descriptor (in this case this method pops the types corresponding
rlm@10 730 * to the method arguments).
rlm@10 731 */
rlm@10 732 private void pop(final String desc){
rlm@10 733 char c = desc.charAt(0);
rlm@10 734 if(c == '(')
rlm@10 735 {
rlm@10 736 pop((MethodWriter.getArgumentsAndReturnSizes(desc) >> 2) - 1);
rlm@10 737 }
rlm@10 738 else if(c == 'J' || c == 'D')
rlm@10 739 {
rlm@10 740 pop(2);
rlm@10 741 }
rlm@10 742 else
rlm@10 743 {
rlm@10 744 pop(1);
rlm@10 745 }
rlm@10 746 }
rlm@10 747
rlm@10 748 /**
rlm@10 749 * Adds a new type to the list of types on which a constructor is invoked in
rlm@10 750 * the basic block.
rlm@10 751 *
rlm@10 752 * @param var a type on a which a constructor is invoked.
rlm@10 753 */
rlm@10 754 private void init(final int var){
rlm@10 755 // creates and/or resizes the initializations array if necessary
rlm@10 756 if(initializations == null)
rlm@10 757 {
rlm@10 758 initializations = new int[2];
rlm@10 759 }
rlm@10 760 int n = initializations.length;
rlm@10 761 if(initializationCount >= n)
rlm@10 762 {
rlm@10 763 int[] t = new int[Math.max(initializationCount + 1, 2 * n)];
rlm@10 764 System.arraycopy(initializations, 0, t, 0, n);
rlm@10 765 initializations = t;
rlm@10 766 }
rlm@10 767 // stores the type to be initialized
rlm@10 768 initializations[initializationCount++] = var;
rlm@10 769 }
rlm@10 770
rlm@10 771 /**
rlm@10 772 * Replaces the given type with the appropriate type if it is one of the
rlm@10 773 * types on which a constructor is invoked in the basic block.
rlm@10 774 *
rlm@10 775 * @param cw the ClassWriter to which this label belongs.
rlm@10 776 * @param t a type
rlm@10 777 * @return t or, if t is one of the types on which a constructor is invoked
rlm@10 778 * in the basic block, the type corresponding to this constructor.
rlm@10 779 */
rlm@10 780 private int init(final ClassWriter cw, final int t){
rlm@10 781 int s;
rlm@10 782 if(t == UNINITIALIZED_THIS)
rlm@10 783 {
rlm@10 784 s = OBJECT | cw.addType(cw.thisName);
rlm@10 785 }
rlm@10 786 else if((t & (DIM | BASE_KIND)) == UNINITIALIZED)
rlm@10 787 {
rlm@10 788 String type = cw.typeTable[t & BASE_VALUE].strVal1;
rlm@10 789 s = OBJECT | cw.addType(type);
rlm@10 790 }
rlm@10 791 else
rlm@10 792 {
rlm@10 793 return t;
rlm@10 794 }
rlm@10 795 for(int j = 0; j < initializationCount; ++j)
rlm@10 796 {
rlm@10 797 int u = initializations[j];
rlm@10 798 int dim = u & DIM;
rlm@10 799 int kind = u & KIND;
rlm@10 800 if(kind == LOCAL)
rlm@10 801 {
rlm@10 802 u = dim + inputLocals[u & VALUE];
rlm@10 803 }
rlm@10 804 else if(kind == STACK)
rlm@10 805 {
rlm@10 806 u = dim + inputStack[inputStack.length - (u & VALUE)];
rlm@10 807 }
rlm@10 808 if(t == u)
rlm@10 809 {
rlm@10 810 return s;
rlm@10 811 }
rlm@10 812 }
rlm@10 813 return t;
rlm@10 814 }
rlm@10 815
rlm@10 816 /**
rlm@10 817 * Initializes the input frame of the first basic block from the method
rlm@10 818 * descriptor.
rlm@10 819 *
rlm@10 820 * @param cw the ClassWriter to which this label belongs.
rlm@10 821 * @param access the access flags of the method to which this label belongs.
rlm@10 822 * @param args the formal parameter types of this method.
rlm@10 823 * @param maxLocals the maximum number of local variables of this method.
rlm@10 824 */
rlm@10 825 void initInputFrame(
rlm@10 826 final ClassWriter cw,
rlm@10 827 final int access,
rlm@10 828 final Type[] args,
rlm@10 829 final int maxLocals){
rlm@10 830 inputLocals = new int[maxLocals];
rlm@10 831 inputStack = new int[0];
rlm@10 832 int i = 0;
rlm@10 833 if((access & Opcodes.ACC_STATIC) == 0)
rlm@10 834 {
rlm@10 835 if((access & MethodWriter.ACC_CONSTRUCTOR) == 0)
rlm@10 836 {
rlm@10 837 inputLocals[i++] = OBJECT | cw.addType(cw.thisName);
rlm@10 838 }
rlm@10 839 else
rlm@10 840 {
rlm@10 841 inputLocals[i++] = UNINITIALIZED_THIS;
rlm@10 842 }
rlm@10 843 }
rlm@10 844 for(int j = 0; j < args.length; ++j)
rlm@10 845 {
rlm@10 846 int t = type(cw, args[j].getDescriptor());
rlm@10 847 inputLocals[i++] = t;
rlm@10 848 if(t == LONG || t == DOUBLE)
rlm@10 849 {
rlm@10 850 inputLocals[i++] = TOP;
rlm@10 851 }
rlm@10 852 }
rlm@10 853 while(i < maxLocals)
rlm@10 854 {
rlm@10 855 inputLocals[i++] = TOP;
rlm@10 856 }
rlm@10 857 }
rlm@10 858
rlm@10 859 /**
rlm@10 860 * Simulates the action of the given instruction on the output stack frame.
rlm@10 861 *
rlm@10 862 * @param opcode the opcode of the instruction.
rlm@10 863 * @param arg the operand of the instruction, if any.
rlm@10 864 * @param cw the class writer to which this label belongs.
rlm@10 865 * @param item the operand of the instructions, if any.
rlm@10 866 */
rlm@10 867 void execute(
rlm@10 868 final int opcode,
rlm@10 869 final int arg,
rlm@10 870 final ClassWriter cw,
rlm@10 871 final Item item){
rlm@10 872 int t1, t2, t3, t4;
rlm@10 873 switch(opcode)
rlm@10 874 {
rlm@10 875 case Opcodes.NOP:
rlm@10 876 case Opcodes.INEG:
rlm@10 877 case Opcodes.LNEG:
rlm@10 878 case Opcodes.FNEG:
rlm@10 879 case Opcodes.DNEG:
rlm@10 880 case Opcodes.I2B:
rlm@10 881 case Opcodes.I2C:
rlm@10 882 case Opcodes.I2S:
rlm@10 883 case Opcodes.GOTO:
rlm@10 884 case Opcodes.RETURN:
rlm@10 885 break;
rlm@10 886 case Opcodes.ACONST_NULL:
rlm@10 887 push(NULL);
rlm@10 888 break;
rlm@10 889 case Opcodes.ICONST_M1:
rlm@10 890 case Opcodes.ICONST_0:
rlm@10 891 case Opcodes.ICONST_1:
rlm@10 892 case Opcodes.ICONST_2:
rlm@10 893 case Opcodes.ICONST_3:
rlm@10 894 case Opcodes.ICONST_4:
rlm@10 895 case Opcodes.ICONST_5:
rlm@10 896 case Opcodes.BIPUSH:
rlm@10 897 case Opcodes.SIPUSH:
rlm@10 898 case Opcodes.ILOAD:
rlm@10 899 push(INTEGER);
rlm@10 900 break;
rlm@10 901 case Opcodes.LCONST_0:
rlm@10 902 case Opcodes.LCONST_1:
rlm@10 903 case Opcodes.LLOAD:
rlm@10 904 push(LONG);
rlm@10 905 push(TOP);
rlm@10 906 break;
rlm@10 907 case Opcodes.FCONST_0:
rlm@10 908 case Opcodes.FCONST_1:
rlm@10 909 case Opcodes.FCONST_2:
rlm@10 910 case Opcodes.FLOAD:
rlm@10 911 push(FLOAT);
rlm@10 912 break;
rlm@10 913 case Opcodes.DCONST_0:
rlm@10 914 case Opcodes.DCONST_1:
rlm@10 915 case Opcodes.DLOAD:
rlm@10 916 push(DOUBLE);
rlm@10 917 push(TOP);
rlm@10 918 break;
rlm@10 919 case Opcodes.LDC:
rlm@10 920 switch(item.type)
rlm@10 921 {
rlm@10 922 case ClassWriter.INT:
rlm@10 923 push(INTEGER);
rlm@10 924 break;
rlm@10 925 case ClassWriter.LONG:
rlm@10 926 push(LONG);
rlm@10 927 push(TOP);
rlm@10 928 break;
rlm@10 929 case ClassWriter.FLOAT:
rlm@10 930 push(FLOAT);
rlm@10 931 break;
rlm@10 932 case ClassWriter.DOUBLE:
rlm@10 933 push(DOUBLE);
rlm@10 934 push(TOP);
rlm@10 935 break;
rlm@10 936 case ClassWriter.CLASS:
rlm@10 937 push(OBJECT | cw.addType("java/lang/Class"));
rlm@10 938 break;
rlm@10 939 // case ClassWriter.STR:
rlm@10 940 default:
rlm@10 941 push(OBJECT | cw.addType("java/lang/String"));
rlm@10 942 }
rlm@10 943 break;
rlm@10 944 case Opcodes.ALOAD:
rlm@10 945 push(get(arg));
rlm@10 946 break;
rlm@10 947 case Opcodes.IALOAD:
rlm@10 948 case Opcodes.BALOAD:
rlm@10 949 case Opcodes.CALOAD:
rlm@10 950 case Opcodes.SALOAD:
rlm@10 951 pop(2);
rlm@10 952 push(INTEGER);
rlm@10 953 break;
rlm@10 954 case Opcodes.LALOAD:
rlm@10 955 case Opcodes.D2L:
rlm@10 956 pop(2);
rlm@10 957 push(LONG);
rlm@10 958 push(TOP);
rlm@10 959 break;
rlm@10 960 case Opcodes.FALOAD:
rlm@10 961 pop(2);
rlm@10 962 push(FLOAT);
rlm@10 963 break;
rlm@10 964 case Opcodes.DALOAD:
rlm@10 965 case Opcodes.L2D:
rlm@10 966 pop(2);
rlm@10 967 push(DOUBLE);
rlm@10 968 push(TOP);
rlm@10 969 break;
rlm@10 970 case Opcodes.AALOAD:
rlm@10 971 pop(1);
rlm@10 972 t1 = pop();
rlm@10 973 push(ELEMENT_OF + t1);
rlm@10 974 break;
rlm@10 975 case Opcodes.ISTORE:
rlm@10 976 case Opcodes.FSTORE:
rlm@10 977 case Opcodes.ASTORE:
rlm@10 978 t1 = pop();
rlm@10 979 set(arg, t1);
rlm@10 980 if(arg > 0)
rlm@10 981 {
rlm@10 982 t2 = get(arg - 1);
rlm@10 983 // if t2 is of kind STACK or LOCAL we cannot know its size!
rlm@10 984 if(t2 == LONG || t2 == DOUBLE)
rlm@10 985 {
rlm@10 986 set(arg - 1, TOP);
rlm@10 987 }
rlm@10 988 }
rlm@10 989 break;
rlm@10 990 case Opcodes.LSTORE:
rlm@10 991 case Opcodes.DSTORE:
rlm@10 992 pop(1);
rlm@10 993 t1 = pop();
rlm@10 994 set(arg, t1);
rlm@10 995 set(arg + 1, TOP);
rlm@10 996 if(arg > 0)
rlm@10 997 {
rlm@10 998 t2 = get(arg - 1);
rlm@10 999 // if t2 is of kind STACK or LOCAL we cannot know its size!
rlm@10 1000 if(t2 == LONG || t2 == DOUBLE)
rlm@10 1001 {
rlm@10 1002 set(arg - 1, TOP);
rlm@10 1003 }
rlm@10 1004 }
rlm@10 1005 break;
rlm@10 1006 case Opcodes.IASTORE:
rlm@10 1007 case Opcodes.BASTORE:
rlm@10 1008 case Opcodes.CASTORE:
rlm@10 1009 case Opcodes.SASTORE:
rlm@10 1010 case Opcodes.FASTORE:
rlm@10 1011 case Opcodes.AASTORE:
rlm@10 1012 pop(3);
rlm@10 1013 break;
rlm@10 1014 case Opcodes.LASTORE:
rlm@10 1015 case Opcodes.DASTORE:
rlm@10 1016 pop(4);
rlm@10 1017 break;
rlm@10 1018 case Opcodes.POP:
rlm@10 1019 case Opcodes.IFEQ:
rlm@10 1020 case Opcodes.IFNE:
rlm@10 1021 case Opcodes.IFLT:
rlm@10 1022 case Opcodes.IFGE:
rlm@10 1023 case Opcodes.IFGT:
rlm@10 1024 case Opcodes.IFLE:
rlm@10 1025 case Opcodes.IRETURN:
rlm@10 1026 case Opcodes.FRETURN:
rlm@10 1027 case Opcodes.ARETURN:
rlm@10 1028 case Opcodes.TABLESWITCH:
rlm@10 1029 case Opcodes.LOOKUPSWITCH:
rlm@10 1030 case Opcodes.ATHROW:
rlm@10 1031 case Opcodes.MONITORENTER:
rlm@10 1032 case Opcodes.MONITOREXIT:
rlm@10 1033 case Opcodes.IFNULL:
rlm@10 1034 case Opcodes.IFNONNULL:
rlm@10 1035 pop(1);
rlm@10 1036 break;
rlm@10 1037 case Opcodes.POP2:
rlm@10 1038 case Opcodes.IF_ICMPEQ:
rlm@10 1039 case Opcodes.IF_ICMPNE:
rlm@10 1040 case Opcodes.IF_ICMPLT:
rlm@10 1041 case Opcodes.IF_ICMPGE:
rlm@10 1042 case Opcodes.IF_ICMPGT:
rlm@10 1043 case Opcodes.IF_ICMPLE:
rlm@10 1044 case Opcodes.IF_ACMPEQ:
rlm@10 1045 case Opcodes.IF_ACMPNE:
rlm@10 1046 case Opcodes.LRETURN:
rlm@10 1047 case Opcodes.DRETURN:
rlm@10 1048 pop(2);
rlm@10 1049 break;
rlm@10 1050 case Opcodes.DUP:
rlm@10 1051 t1 = pop();
rlm@10 1052 push(t1);
rlm@10 1053 push(t1);
rlm@10 1054 break;
rlm@10 1055 case Opcodes.DUP_X1:
rlm@10 1056 t1 = pop();
rlm@10 1057 t2 = pop();
rlm@10 1058 push(t1);
rlm@10 1059 push(t2);
rlm@10 1060 push(t1);
rlm@10 1061 break;
rlm@10 1062 case Opcodes.DUP_X2:
rlm@10 1063 t1 = pop();
rlm@10 1064 t2 = pop();
rlm@10 1065 t3 = pop();
rlm@10 1066 push(t1);
rlm@10 1067 push(t3);
rlm@10 1068 push(t2);
rlm@10 1069 push(t1);
rlm@10 1070 break;
rlm@10 1071 case Opcodes.DUP2:
rlm@10 1072 t1 = pop();
rlm@10 1073 t2 = pop();
rlm@10 1074 push(t2);
rlm@10 1075 push(t1);
rlm@10 1076 push(t2);
rlm@10 1077 push(t1);
rlm@10 1078 break;
rlm@10 1079 case Opcodes.DUP2_X1:
rlm@10 1080 t1 = pop();
rlm@10 1081 t2 = pop();
rlm@10 1082 t3 = pop();
rlm@10 1083 push(t2);
rlm@10 1084 push(t1);
rlm@10 1085 push(t3);
rlm@10 1086 push(t2);
rlm@10 1087 push(t1);
rlm@10 1088 break;
rlm@10 1089 case Opcodes.DUP2_X2:
rlm@10 1090 t1 = pop();
rlm@10 1091 t2 = pop();
rlm@10 1092 t3 = pop();
rlm@10 1093 t4 = pop();
rlm@10 1094 push(t2);
rlm@10 1095 push(t1);
rlm@10 1096 push(t4);
rlm@10 1097 push(t3);
rlm@10 1098 push(t2);
rlm@10 1099 push(t1);
rlm@10 1100 break;
rlm@10 1101 case Opcodes.SWAP:
rlm@10 1102 t1 = pop();
rlm@10 1103 t2 = pop();
rlm@10 1104 push(t1);
rlm@10 1105 push(t2);
rlm@10 1106 break;
rlm@10 1107 case Opcodes.IADD:
rlm@10 1108 case Opcodes.ISUB:
rlm@10 1109 case Opcodes.IMUL:
rlm@10 1110 case Opcodes.IDIV:
rlm@10 1111 case Opcodes.IREM:
rlm@10 1112 case Opcodes.IAND:
rlm@10 1113 case Opcodes.IOR:
rlm@10 1114 case Opcodes.IXOR:
rlm@10 1115 case Opcodes.ISHL:
rlm@10 1116 case Opcodes.ISHR:
rlm@10 1117 case Opcodes.IUSHR:
rlm@10 1118 case Opcodes.L2I:
rlm@10 1119 case Opcodes.D2I:
rlm@10 1120 case Opcodes.FCMPL:
rlm@10 1121 case Opcodes.FCMPG:
rlm@10 1122 pop(2);
rlm@10 1123 push(INTEGER);
rlm@10 1124 break;
rlm@10 1125 case Opcodes.LADD:
rlm@10 1126 case Opcodes.LSUB:
rlm@10 1127 case Opcodes.LMUL:
rlm@10 1128 case Opcodes.LDIV:
rlm@10 1129 case Opcodes.LREM:
rlm@10 1130 case Opcodes.LAND:
rlm@10 1131 case Opcodes.LOR:
rlm@10 1132 case Opcodes.LXOR:
rlm@10 1133 pop(4);
rlm@10 1134 push(LONG);
rlm@10 1135 push(TOP);
rlm@10 1136 break;
rlm@10 1137 case Opcodes.FADD:
rlm@10 1138 case Opcodes.FSUB:
rlm@10 1139 case Opcodes.FMUL:
rlm@10 1140 case Opcodes.FDIV:
rlm@10 1141 case Opcodes.FREM:
rlm@10 1142 case Opcodes.L2F:
rlm@10 1143 case Opcodes.D2F:
rlm@10 1144 pop(2);
rlm@10 1145 push(FLOAT);
rlm@10 1146 break;
rlm@10 1147 case Opcodes.DADD:
rlm@10 1148 case Opcodes.DSUB:
rlm@10 1149 case Opcodes.DMUL:
rlm@10 1150 case Opcodes.DDIV:
rlm@10 1151 case Opcodes.DREM:
rlm@10 1152 pop(4);
rlm@10 1153 push(DOUBLE);
rlm@10 1154 push(TOP);
rlm@10 1155 break;
rlm@10 1156 case Opcodes.LSHL:
rlm@10 1157 case Opcodes.LSHR:
rlm@10 1158 case Opcodes.LUSHR:
rlm@10 1159 pop(3);
rlm@10 1160 push(LONG);
rlm@10 1161 push(TOP);
rlm@10 1162 break;
rlm@10 1163 case Opcodes.IINC:
rlm@10 1164 set(arg, INTEGER);
rlm@10 1165 break;
rlm@10 1166 case Opcodes.I2L:
rlm@10 1167 case Opcodes.F2L:
rlm@10 1168 pop(1);
rlm@10 1169 push(LONG);
rlm@10 1170 push(TOP);
rlm@10 1171 break;
rlm@10 1172 case Opcodes.I2F:
rlm@10 1173 pop(1);
rlm@10 1174 push(FLOAT);
rlm@10 1175 break;
rlm@10 1176 case Opcodes.I2D:
rlm@10 1177 case Opcodes.F2D:
rlm@10 1178 pop(1);
rlm@10 1179 push(DOUBLE);
rlm@10 1180 push(TOP);
rlm@10 1181 break;
rlm@10 1182 case Opcodes.F2I:
rlm@10 1183 case Opcodes.ARRAYLENGTH:
rlm@10 1184 case Opcodes.INSTANCEOF:
rlm@10 1185 pop(1);
rlm@10 1186 push(INTEGER);
rlm@10 1187 break;
rlm@10 1188 case Opcodes.LCMP:
rlm@10 1189 case Opcodes.DCMPL:
rlm@10 1190 case Opcodes.DCMPG:
rlm@10 1191 pop(4);
rlm@10 1192 push(INTEGER);
rlm@10 1193 break;
rlm@10 1194 case Opcodes.JSR:
rlm@10 1195 case Opcodes.RET:
rlm@10 1196 throw new RuntimeException("JSR/RET are not supported with computeFrames option");
rlm@10 1197 case Opcodes.GETSTATIC:
rlm@10 1198 push(cw, item.strVal3);
rlm@10 1199 break;
rlm@10 1200 case Opcodes.PUTSTATIC:
rlm@10 1201 pop(item.strVal3);
rlm@10 1202 break;
rlm@10 1203 case Opcodes.GETFIELD:
rlm@10 1204 pop(1);
rlm@10 1205 push(cw, item.strVal3);
rlm@10 1206 break;
rlm@10 1207 case Opcodes.PUTFIELD:
rlm@10 1208 pop(item.strVal3);
rlm@10 1209 pop();
rlm@10 1210 break;
rlm@10 1211 case Opcodes.INVOKEVIRTUAL:
rlm@10 1212 case Opcodes.INVOKESPECIAL:
rlm@10 1213 case Opcodes.INVOKESTATIC:
rlm@10 1214 case Opcodes.INVOKEINTERFACE:
rlm@10 1215 pop(item.strVal3);
rlm@10 1216 if(opcode != Opcodes.INVOKESTATIC)
rlm@10 1217 {
rlm@10 1218 t1 = pop();
rlm@10 1219 if(opcode == Opcodes.INVOKESPECIAL
rlm@10 1220 && item.strVal2.charAt(0) == '<')
rlm@10 1221 {
rlm@10 1222 init(t1);
rlm@10 1223 }
rlm@10 1224 }
rlm@10 1225 push(cw, item.strVal3);
rlm@10 1226 break;
rlm@10 1227 case Opcodes.NEW:
rlm@10 1228 push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg));
rlm@10 1229 break;
rlm@10 1230 case Opcodes.NEWARRAY:
rlm@10 1231 pop();
rlm@10 1232 switch(arg)
rlm@10 1233 {
rlm@10 1234 case Opcodes.T_BOOLEAN:
rlm@10 1235 push(ARRAY_OF | BOOLEAN);
rlm@10 1236 break;
rlm@10 1237 case Opcodes.T_CHAR:
rlm@10 1238 push(ARRAY_OF | CHAR);
rlm@10 1239 break;
rlm@10 1240 case Opcodes.T_BYTE:
rlm@10 1241 push(ARRAY_OF | BYTE);
rlm@10 1242 break;
rlm@10 1243 case Opcodes.T_SHORT:
rlm@10 1244 push(ARRAY_OF | SHORT);
rlm@10 1245 break;
rlm@10 1246 case Opcodes.T_INT:
rlm@10 1247 push(ARRAY_OF | INTEGER);
rlm@10 1248 break;
rlm@10 1249 case Opcodes.T_FLOAT:
rlm@10 1250 push(ARRAY_OF | FLOAT);
rlm@10 1251 break;
rlm@10 1252 case Opcodes.T_DOUBLE:
rlm@10 1253 push(ARRAY_OF | DOUBLE);
rlm@10 1254 break;
rlm@10 1255 // case Opcodes.T_LONG:
rlm@10 1256 default:
rlm@10 1257 push(ARRAY_OF | LONG);
rlm@10 1258 break;
rlm@10 1259 }
rlm@10 1260 break;
rlm@10 1261 case Opcodes.ANEWARRAY:
rlm@10 1262 String s = item.strVal1;
rlm@10 1263 pop();
rlm@10 1264 if(s.charAt(0) == '[')
rlm@10 1265 {
rlm@10 1266 push(cw, "[" + s);
rlm@10 1267 }
rlm@10 1268 else
rlm@10 1269 {
rlm@10 1270 push(ARRAY_OF | OBJECT | cw.addType(s));
rlm@10 1271 }
rlm@10 1272 break;
rlm@10 1273 case Opcodes.CHECKCAST:
rlm@10 1274 s = item.strVal1;
rlm@10 1275 pop();
rlm@10 1276 if(s.charAt(0) == '[')
rlm@10 1277 {
rlm@10 1278 push(cw, s);
rlm@10 1279 }
rlm@10 1280 else
rlm@10 1281 {
rlm@10 1282 push(OBJECT | cw.addType(s));
rlm@10 1283 }
rlm@10 1284 break;
rlm@10 1285 // case Opcodes.MULTIANEWARRAY:
rlm@10 1286 default:
rlm@10 1287 pop(arg);
rlm@10 1288 push(cw, item.strVal1);
rlm@10 1289 break;
rlm@10 1290 }
rlm@10 1291 }
rlm@10 1292
rlm@10 1293 /**
rlm@10 1294 * Merges the input frame of the given basic block with the input and output
rlm@10 1295 * frames of this basic block. Returns <tt>true</tt> if the input frame of
rlm@10 1296 * the given label has been changed by this operation.
rlm@10 1297 *
rlm@10 1298 * @param cw the ClassWriter to which this label belongs.
rlm@10 1299 * @param frame the basic block whose input frame must be updated.
rlm@10 1300 * @param edge the kind of the {@link Edge} between this label and 'label'.
rlm@10 1301 * See {@link Edge#info}.
rlm@10 1302 * @return <tt>true</tt> if the input frame of the given label has been
rlm@10 1303 * changed by this operation.
rlm@10 1304 */
rlm@10 1305 boolean merge(final ClassWriter cw, final Frame frame, final int edge){
rlm@10 1306 boolean changed = false;
rlm@10 1307 int i, s, dim, kind, t;
rlm@10 1308
rlm@10 1309 int nLocal = inputLocals.length;
rlm@10 1310 int nStack = inputStack.length;
rlm@10 1311 if(frame.inputLocals == null)
rlm@10 1312 {
rlm@10 1313 frame.inputLocals = new int[nLocal];
rlm@10 1314 changed = true;
rlm@10 1315 }
rlm@10 1316
rlm@10 1317 for(i = 0; i < nLocal; ++i)
rlm@10 1318 {
rlm@10 1319 if(outputLocals != null && i < outputLocals.length)
rlm@10 1320 {
rlm@10 1321 s = outputLocals[i];
rlm@10 1322 if(s == 0)
rlm@10 1323 {
rlm@10 1324 t = inputLocals[i];
rlm@10 1325 }
rlm@10 1326 else
rlm@10 1327 {
rlm@10 1328 dim = s & DIM;
rlm@10 1329 kind = s & KIND;
rlm@10 1330 if(kind == LOCAL)
rlm@10 1331 {
rlm@10 1332 t = dim + inputLocals[s & VALUE];
rlm@10 1333 }
rlm@10 1334 else if(kind == STACK)
rlm@10 1335 {
rlm@10 1336 t = dim + inputStack[nStack - (s & VALUE)];
rlm@10 1337 }
rlm@10 1338 else
rlm@10 1339 {
rlm@10 1340 t = s;
rlm@10 1341 }
rlm@10 1342 }
rlm@10 1343 }
rlm@10 1344 else
rlm@10 1345 {
rlm@10 1346 t = inputLocals[i];
rlm@10 1347 }
rlm@10 1348 if(initializations != null)
rlm@10 1349 {
rlm@10 1350 t = init(cw, t);
rlm@10 1351 }
rlm@10 1352 changed |= merge(cw, t, frame.inputLocals, i);
rlm@10 1353 }
rlm@10 1354
rlm@10 1355 if(edge > 0)
rlm@10 1356 {
rlm@10 1357 for(i = 0; i < nLocal; ++i)
rlm@10 1358 {
rlm@10 1359 t = inputLocals[i];
rlm@10 1360 changed |= merge(cw, t, frame.inputLocals, i);
rlm@10 1361 }
rlm@10 1362 if(frame.inputStack == null)
rlm@10 1363 {
rlm@10 1364 frame.inputStack = new int[1];
rlm@10 1365 changed = true;
rlm@10 1366 }
rlm@10 1367 changed |= merge(cw, edge, frame.inputStack, 0);
rlm@10 1368 return changed;
rlm@10 1369 }
rlm@10 1370
rlm@10 1371 int nInputStack = inputStack.length + owner.inputStackTop;
rlm@10 1372 if(frame.inputStack == null)
rlm@10 1373 {
rlm@10 1374 frame.inputStack = new int[nInputStack + outputStackTop];
rlm@10 1375 changed = true;
rlm@10 1376 }
rlm@10 1377
rlm@10 1378 for(i = 0; i < nInputStack; ++i)
rlm@10 1379 {
rlm@10 1380 t = inputStack[i];
rlm@10 1381 if(initializations != null)
rlm@10 1382 {
rlm@10 1383 t = init(cw, t);
rlm@10 1384 }
rlm@10 1385 changed |= merge(cw, t, frame.inputStack, i);
rlm@10 1386 }
rlm@10 1387 for(i = 0; i < outputStackTop; ++i)
rlm@10 1388 {
rlm@10 1389 s = outputStack[i];
rlm@10 1390 dim = s & DIM;
rlm@10 1391 kind = s & KIND;
rlm@10 1392 if(kind == LOCAL)
rlm@10 1393 {
rlm@10 1394 t = dim + inputLocals[s & VALUE];
rlm@10 1395 }
rlm@10 1396 else if(kind == STACK)
rlm@10 1397 {
rlm@10 1398 t = dim + inputStack[nStack - (s & VALUE)];
rlm@10 1399 }
rlm@10 1400 else
rlm@10 1401 {
rlm@10 1402 t = s;
rlm@10 1403 }
rlm@10 1404 if(initializations != null)
rlm@10 1405 {
rlm@10 1406 t = init(cw, t);
rlm@10 1407 }
rlm@10 1408 changed |= merge(cw, t, frame.inputStack, nInputStack + i);
rlm@10 1409 }
rlm@10 1410 return changed;
rlm@10 1411 }
rlm@10 1412
rlm@10 1413 /**
rlm@10 1414 * Merges the type at the given index in the given type array with the given
rlm@10 1415 * type. Returns <tt>true</tt> if the type array has been modified by this
rlm@10 1416 * operation.
rlm@10 1417 *
rlm@10 1418 * @param cw the ClassWriter to which this label belongs.
rlm@10 1419 * @param t the type with which the type array element must be merged.
rlm@10 1420 * @param types an array of types.
rlm@10 1421 * @param index the index of the type that must be merged in 'types'.
rlm@10 1422 * @return <tt>true</tt> if the type array has been modified by this
rlm@10 1423 * operation.
rlm@10 1424 */
rlm@10 1425 private boolean merge(
rlm@10 1426 final ClassWriter cw,
rlm@10 1427 int t,
rlm@10 1428 final int[] types,
rlm@10 1429 final int index){
rlm@10 1430 int u = types[index];
rlm@10 1431 if(u == t)
rlm@10 1432 {
rlm@10 1433 // if the types are equal, merge(u,t)=u, so there is no change
rlm@10 1434 return false;
rlm@10 1435 }
rlm@10 1436 if((t & ~DIM) == NULL)
rlm@10 1437 {
rlm@10 1438 if(u == NULL)
rlm@10 1439 {
rlm@10 1440 return false;
rlm@10 1441 }
rlm@10 1442 t = NULL;
rlm@10 1443 }
rlm@10 1444 if(u == 0)
rlm@10 1445 {
rlm@10 1446 // if types[index] has never been assigned, merge(u,t)=t
rlm@10 1447 types[index] = t;
rlm@10 1448 return true;
rlm@10 1449 }
rlm@10 1450 int v;
rlm@10 1451 if((u & BASE_KIND) == OBJECT || (u & DIM) != 0)
rlm@10 1452 {
rlm@10 1453 // if u is a reference type of any dimension
rlm@10 1454 if(t == NULL)
rlm@10 1455 {
rlm@10 1456 // if t is the NULL type, merge(u,t)=u, so there is no change
rlm@10 1457 return false;
rlm@10 1458 }
rlm@10 1459 else if((t & (DIM | BASE_KIND)) == (u & (DIM | BASE_KIND)))
rlm@10 1460 {
rlm@10 1461 if((u & BASE_KIND) == OBJECT)
rlm@10 1462 {
rlm@10 1463 // if t is also a reference type, and if u and t have the
rlm@10 1464 // same dimension merge(u,t) = dim(t) | common parent of the
rlm@10 1465 // element types of u and t
rlm@10 1466 v = (t & DIM) | OBJECT
rlm@10 1467 | cw.getMergedType(t & BASE_VALUE, u & BASE_VALUE);
rlm@10 1468 }
rlm@10 1469 else
rlm@10 1470 {
rlm@10 1471 // if u and t are array types, but not with the same element
rlm@10 1472 // type, merge(u,t)=java/lang/Object
rlm@10 1473 v = OBJECT | cw.addType("java/lang/Object");
rlm@10 1474 }
rlm@10 1475 }
rlm@10 1476 else if((t & BASE_KIND) == OBJECT || (t & DIM) != 0)
rlm@10 1477 {
rlm@10 1478 // if t is any other reference or array type,
rlm@10 1479 // merge(u,t)=java/lang/Object
rlm@10 1480 v = OBJECT | cw.addType("java/lang/Object");
rlm@10 1481 }
rlm@10 1482 else
rlm@10 1483 {
rlm@10 1484 // if t is any other type, merge(u,t)=TOP
rlm@10 1485 v = TOP;
rlm@10 1486 }
rlm@10 1487 }
rlm@10 1488 else if(u == NULL)
rlm@10 1489 {
rlm@10 1490 // if u is the NULL type, merge(u,t)=t,
rlm@10 1491 // or TOP if t is not a reference type
rlm@10 1492 v = (t & BASE_KIND) == OBJECT || (t & DIM) != 0 ? t : TOP;
rlm@10 1493 }
rlm@10 1494 else
rlm@10 1495 {
rlm@10 1496 // if u is any other type, merge(u,t)=TOP whatever t
rlm@10 1497 v = TOP;
rlm@10 1498 }
rlm@10 1499 if(u != v)
rlm@10 1500 {
rlm@10 1501 types[index] = v;
rlm@10 1502 return true;
rlm@10 1503 }
rlm@10 1504 return false;
rlm@10 1505 }
rlm@10 1506 }