Mercurial > lasercutter
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 +}