1/*** 2 * ASM: a very small and fast Java bytecode manipulation framework 3 * Copyright (c) 2000-2007 INRIA, France Telecom 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of the copyright holders nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 * THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30package org.mockito.asm.tree.analysis; 31 32import java.util.List; 33 34import org.mockito.asm.Opcodes; 35import org.mockito.asm.Type; 36import org.mockito.asm.tree.AbstractInsnNode; 37import org.mockito.asm.tree.FieldInsnNode; 38import org.mockito.asm.tree.IntInsnNode; 39import org.mockito.asm.tree.LdcInsnNode; 40import org.mockito.asm.tree.MethodInsnNode; 41import org.mockito.asm.tree.MultiANewArrayInsnNode; 42import org.mockito.asm.tree.TypeInsnNode; 43 44/** 45 * An {@link Interpreter} for {@link BasicValue} values. 46 * 47 * @author Eric Bruneton 48 * @author Bing Ran 49 */ 50public class BasicInterpreter implements Opcodes, Interpreter { 51 52 public Value newValue(final Type type) { 53 if (type == null) { 54 return BasicValue.UNINITIALIZED_VALUE; 55 } 56 switch (type.getSort()) { 57 case Type.VOID: 58 return null; 59 case Type.BOOLEAN: 60 case Type.CHAR: 61 case Type.BYTE: 62 case Type.SHORT: 63 case Type.INT: 64 return BasicValue.INT_VALUE; 65 case Type.FLOAT: 66 return BasicValue.FLOAT_VALUE; 67 case Type.LONG: 68 return BasicValue.LONG_VALUE; 69 case Type.DOUBLE: 70 return BasicValue.DOUBLE_VALUE; 71 case Type.ARRAY: 72 case Type.OBJECT: 73 return BasicValue.REFERENCE_VALUE; 74 default: 75 throw new Error("Internal error"); 76 } 77 } 78 79 public Value newOperation(final AbstractInsnNode insn) { 80 switch (insn.getOpcode()) { 81 case ACONST_NULL: 82 return newValue(Type.getObjectType("null")); 83 case ICONST_M1: 84 case ICONST_0: 85 case ICONST_1: 86 case ICONST_2: 87 case ICONST_3: 88 case ICONST_4: 89 case ICONST_5: 90 return BasicValue.INT_VALUE; 91 case LCONST_0: 92 case LCONST_1: 93 return BasicValue.LONG_VALUE; 94 case FCONST_0: 95 case FCONST_1: 96 case FCONST_2: 97 return BasicValue.FLOAT_VALUE; 98 case DCONST_0: 99 case DCONST_1: 100 return BasicValue.DOUBLE_VALUE; 101 case BIPUSH: 102 case SIPUSH: 103 return BasicValue.INT_VALUE; 104 case LDC: 105 Object cst = ((LdcInsnNode) insn).cst; 106 if (cst instanceof Integer) { 107 return BasicValue.INT_VALUE; 108 } else if (cst instanceof Float) { 109 return BasicValue.FLOAT_VALUE; 110 } else if (cst instanceof Long) { 111 return BasicValue.LONG_VALUE; 112 } else if (cst instanceof Double) { 113 return BasicValue.DOUBLE_VALUE; 114 } else if (cst instanceof Type) { 115 return newValue(Type.getObjectType("java/lang/Class")); 116 } else { 117 return newValue(Type.getType(cst.getClass())); 118 } 119 case JSR: 120 return BasicValue.RETURNADDRESS_VALUE; 121 case GETSTATIC: 122 return newValue(Type.getType(((FieldInsnNode) insn).desc)); 123 case NEW: 124 return newValue(Type.getObjectType(((TypeInsnNode) insn).desc)); 125 default: 126 throw new Error("Internal error."); 127 } 128 } 129 130 public Value copyOperation(final AbstractInsnNode insn, final Value value) 131 throws AnalyzerException 132 { 133 return value; 134 } 135 136 public Value unaryOperation(final AbstractInsnNode insn, final Value value) 137 throws AnalyzerException 138 { 139 switch (insn.getOpcode()) { 140 case INEG: 141 case IINC: 142 case L2I: 143 case F2I: 144 case D2I: 145 case I2B: 146 case I2C: 147 case I2S: 148 return BasicValue.INT_VALUE; 149 case FNEG: 150 case I2F: 151 case L2F: 152 case D2F: 153 return BasicValue.FLOAT_VALUE; 154 case LNEG: 155 case I2L: 156 case F2L: 157 case D2L: 158 return BasicValue.LONG_VALUE; 159 case DNEG: 160 case I2D: 161 case L2D: 162 case F2D: 163 return BasicValue.DOUBLE_VALUE; 164 case IFEQ: 165 case IFNE: 166 case IFLT: 167 case IFGE: 168 case IFGT: 169 case IFLE: 170 case TABLESWITCH: 171 case LOOKUPSWITCH: 172 case IRETURN: 173 case LRETURN: 174 case FRETURN: 175 case DRETURN: 176 case ARETURN: 177 case PUTSTATIC: 178 return null; 179 case GETFIELD: 180 return newValue(Type.getType(((FieldInsnNode) insn).desc)); 181 case NEWARRAY: 182 switch (((IntInsnNode) insn).operand) { 183 case T_BOOLEAN: 184 return newValue(Type.getType("[Z")); 185 case T_CHAR: 186 return newValue(Type.getType("[C")); 187 case T_BYTE: 188 return newValue(Type.getType("[B")); 189 case T_SHORT: 190 return newValue(Type.getType("[S")); 191 case T_INT: 192 return newValue(Type.getType("[I")); 193 case T_FLOAT: 194 return newValue(Type.getType("[F")); 195 case T_DOUBLE: 196 return newValue(Type.getType("[D")); 197 case T_LONG: 198 return newValue(Type.getType("[J")); 199 default: 200 throw new AnalyzerException("Invalid array type"); 201 } 202 case ANEWARRAY: 203 String desc = ((TypeInsnNode) insn).desc; 204 return newValue(Type.getType("[" + Type.getObjectType(desc))); 205 case ARRAYLENGTH: 206 return BasicValue.INT_VALUE; 207 case ATHROW: 208 return null; 209 case CHECKCAST: 210 desc = ((TypeInsnNode) insn).desc; 211 return newValue(Type.getObjectType(desc)); 212 case INSTANCEOF: 213 return BasicValue.INT_VALUE; 214 case MONITORENTER: 215 case MONITOREXIT: 216 case IFNULL: 217 case IFNONNULL: 218 return null; 219 default: 220 throw new Error("Internal error."); 221 } 222 } 223 224 public Value binaryOperation( 225 final AbstractInsnNode insn, 226 final Value value1, 227 final Value value2) throws AnalyzerException 228 { 229 switch (insn.getOpcode()) { 230 case IALOAD: 231 case BALOAD: 232 case CALOAD: 233 case SALOAD: 234 case IADD: 235 case ISUB: 236 case IMUL: 237 case IDIV: 238 case IREM: 239 case ISHL: 240 case ISHR: 241 case IUSHR: 242 case IAND: 243 case IOR: 244 case IXOR: 245 return BasicValue.INT_VALUE; 246 case FALOAD: 247 case FADD: 248 case FSUB: 249 case FMUL: 250 case FDIV: 251 case FREM: 252 return BasicValue.FLOAT_VALUE; 253 case LALOAD: 254 case LADD: 255 case LSUB: 256 case LMUL: 257 case LDIV: 258 case LREM: 259 case LSHL: 260 case LSHR: 261 case LUSHR: 262 case LAND: 263 case LOR: 264 case LXOR: 265 return BasicValue.LONG_VALUE; 266 case DALOAD: 267 case DADD: 268 case DSUB: 269 case DMUL: 270 case DDIV: 271 case DREM: 272 return BasicValue.DOUBLE_VALUE; 273 case AALOAD: 274 return BasicValue.REFERENCE_VALUE; 275 case LCMP: 276 case FCMPL: 277 case FCMPG: 278 case DCMPL: 279 case DCMPG: 280 return BasicValue.INT_VALUE; 281 case IF_ICMPEQ: 282 case IF_ICMPNE: 283 case IF_ICMPLT: 284 case IF_ICMPGE: 285 case IF_ICMPGT: 286 case IF_ICMPLE: 287 case IF_ACMPEQ: 288 case IF_ACMPNE: 289 case PUTFIELD: 290 return null; 291 default: 292 throw new Error("Internal error."); 293 } 294 } 295 296 public Value ternaryOperation( 297 final AbstractInsnNode insn, 298 final Value value1, 299 final Value value2, 300 final Value value3) throws AnalyzerException 301 { 302 return null; 303 } 304 305 public Value naryOperation(final AbstractInsnNode insn, final List values) 306 throws AnalyzerException 307 { 308 if (insn.getOpcode() == MULTIANEWARRAY) { 309 return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc)); 310 } else { 311 return newValue(Type.getReturnType(((MethodInsnNode) insn).desc)); 312 } 313 } 314 315 public Value merge(final Value v, final Value w) { 316 if (!v.equals(w)) { 317 return BasicValue.UNINITIALIZED_VALUE; 318 } 319 return v; 320 } 321} 322