001/*** 002 * ASM: a very small and fast Java bytecode manipulation framework 003 * Copyright (c) 2000-2011 INRIA, France Telecom 004 * All rights reserved. 005 * 006 * Redistribution and use in source and binary forms, with or without 007 * modification, are permitted provided that the following conditions 008 * are met: 009 * 1. Redistributions of source code must retain the above copyright 010 * notice, this list of conditions and the following disclaimer. 011 * 2. Redistributions in binary form must reproduce the above copyright 012 * notice, this list of conditions and the following disclaimer in the 013 * documentation and/or other materials provided with the distribution. 014 * 3. Neither the name of the copyright holders nor the names of its 015 * contributors may be used to endorse or promote products derived from 016 * this software without specific prior written permission. 017 * 018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 021 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 022 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 028 * THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package io.ebean.enhance.asm.tree.analysis; 031 032import io.ebean.enhance.asm.Handle; 033import io.ebean.enhance.asm.Opcodes; 034import io.ebean.enhance.asm.Type; 035import io.ebean.enhance.asm.tree.AbstractInsnNode; 036import io.ebean.enhance.asm.tree.FieldInsnNode; 037import io.ebean.enhance.asm.tree.IntInsnNode; 038import io.ebean.enhance.asm.tree.InvokeDynamicInsnNode; 039import io.ebean.enhance.asm.tree.LdcInsnNode; 040import io.ebean.enhance.asm.tree.MethodInsnNode; 041import io.ebean.enhance.asm.tree.MultiANewArrayInsnNode; 042import io.ebean.enhance.asm.tree.TypeInsnNode; 043 044import java.util.List; 045 046/** 047 * An {@link Interpreter} for {@link BasicValue} values. 048 * 049 * @author Eric Bruneton 050 * @author Bing Ran 051 */ 052public class BasicInterpreter extends Interpreter<BasicValue> implements 053 Opcodes { 054 055 public BasicInterpreter() { 056 super(ASM6); 057 } 058 059 protected BasicInterpreter(final int api) { 060 super(api); 061 } 062 063 @Override 064 public BasicValue newValue(final Type type) { 065 if (type == null) { 066 return BasicValue.UNINITIALIZED_VALUE; 067 } 068 switch (type.getSort()) { 069 case Type.VOID: 070 return null; 071 case Type.BOOLEAN: 072 case Type.CHAR: 073 case Type.BYTE: 074 case Type.SHORT: 075 case Type.INT: 076 return BasicValue.INT_VALUE; 077 case Type.FLOAT: 078 return BasicValue.FLOAT_VALUE; 079 case Type.LONG: 080 return BasicValue.LONG_VALUE; 081 case Type.DOUBLE: 082 return BasicValue.DOUBLE_VALUE; 083 case Type.ARRAY: 084 case Type.OBJECT: 085 return BasicValue.REFERENCE_VALUE; 086 default: 087 throw new Error("Internal error"); 088 } 089 } 090 091 @Override 092 public BasicValue newOperation(final AbstractInsnNode insn) 093 throws AnalyzerException { 094 switch (insn.getOpcode()) { 095 case ACONST_NULL: 096 return newValue(Type.getObjectType("null")); 097 case ICONST_M1: 098 case ICONST_0: 099 case ICONST_1: 100 case ICONST_2: 101 case ICONST_3: 102 case ICONST_4: 103 case ICONST_5: 104 return BasicValue.INT_VALUE; 105 case LCONST_0: 106 case LCONST_1: 107 return BasicValue.LONG_VALUE; 108 case FCONST_0: 109 case FCONST_1: 110 case FCONST_2: 111 return BasicValue.FLOAT_VALUE; 112 case DCONST_0: 113 case DCONST_1: 114 return BasicValue.DOUBLE_VALUE; 115 case BIPUSH: 116 case SIPUSH: 117 return BasicValue.INT_VALUE; 118 case LDC: 119 Object cst = ((LdcInsnNode) insn).cst; 120 if (cst instanceof Integer) { 121 return BasicValue.INT_VALUE; 122 } else if (cst instanceof Float) { 123 return BasicValue.FLOAT_VALUE; 124 } else if (cst instanceof Long) { 125 return BasicValue.LONG_VALUE; 126 } else if (cst instanceof Double) { 127 return BasicValue.DOUBLE_VALUE; 128 } else if (cst instanceof String) { 129 return newValue(Type.getObjectType("java/lang/String")); 130 } else if (cst instanceof Type) { 131 int sort = ((Type) cst).getSort(); 132 if (sort == Type.OBJECT || sort == Type.ARRAY) { 133 return newValue(Type.getObjectType("java/lang/Class")); 134 } else if (sort == Type.METHOD) { 135 return newValue(Type 136 .getObjectType("java/lang/invoke/MethodType")); 137 } else { 138 throw new IllegalArgumentException("Illegal LDC constant " 139 + cst); 140 } 141 } else if (cst instanceof Handle) { 142 return newValue(Type 143 .getObjectType("java/lang/invoke/MethodHandle")); 144 } else { 145 throw new IllegalArgumentException("Illegal LDC constant " 146 + cst); 147 } 148 case JSR: 149 return BasicValue.RETURNADDRESS_VALUE; 150 case GETSTATIC: 151 return newValue(Type.getType(((FieldInsnNode) insn).desc)); 152 case NEW: 153 return newValue(Type.getObjectType(((TypeInsnNode) insn).desc)); 154 default: 155 throw new Error("Internal error."); 156 } 157 } 158 159 @Override 160 public BasicValue copyOperation(final AbstractInsnNode insn, 161 final BasicValue value) throws AnalyzerException { 162 return value; 163 } 164 165 @Override 166 public BasicValue unaryOperation(final AbstractInsnNode insn, 167 final BasicValue value) throws AnalyzerException { 168 switch (insn.getOpcode()) { 169 case INEG: 170 case IINC: 171 case L2I: 172 case F2I: 173 case D2I: 174 case I2B: 175 case I2C: 176 case I2S: 177 return BasicValue.INT_VALUE; 178 case FNEG: 179 case I2F: 180 case L2F: 181 case D2F: 182 return BasicValue.FLOAT_VALUE; 183 case LNEG: 184 case I2L: 185 case F2L: 186 case D2L: 187 return BasicValue.LONG_VALUE; 188 case DNEG: 189 case I2D: 190 case L2D: 191 case F2D: 192 return BasicValue.DOUBLE_VALUE; 193 case IFEQ: 194 case IFNE: 195 case IFLT: 196 case IFGE: 197 case IFGT: 198 case IFLE: 199 case TABLESWITCH: 200 case LOOKUPSWITCH: 201 case IRETURN: 202 case LRETURN: 203 case FRETURN: 204 case DRETURN: 205 case ARETURN: 206 case PUTSTATIC: 207 return null; 208 case GETFIELD: 209 return newValue(Type.getType(((FieldInsnNode) insn).desc)); 210 case NEWARRAY: 211 switch (((IntInsnNode) insn).operand) { 212 case T_BOOLEAN: 213 return newValue(Type.getType("[Z")); 214 case T_CHAR: 215 return newValue(Type.getType("[C")); 216 case T_BYTE: 217 return newValue(Type.getType("[B")); 218 case T_SHORT: 219 return newValue(Type.getType("[S")); 220 case T_INT: 221 return newValue(Type.getType("[I")); 222 case T_FLOAT: 223 return newValue(Type.getType("[F")); 224 case T_DOUBLE: 225 return newValue(Type.getType("[D")); 226 case T_LONG: 227 return newValue(Type.getType("[J")); 228 default: 229 throw new AnalyzerException(insn, "Invalid array type"); 230 } 231 case ANEWARRAY: 232 String desc = ((TypeInsnNode) insn).desc; 233 return newValue(Type.getType("[" + Type.getObjectType(desc))); 234 case ARRAYLENGTH: 235 return BasicValue.INT_VALUE; 236 case ATHROW: 237 return null; 238 case CHECKCAST: 239 desc = ((TypeInsnNode) insn).desc; 240 return newValue(Type.getObjectType(desc)); 241 case INSTANCEOF: 242 return BasicValue.INT_VALUE; 243 case MONITORENTER: 244 case MONITOREXIT: 245 case IFNULL: 246 case IFNONNULL: 247 return null; 248 default: 249 throw new Error("Internal error."); 250 } 251 } 252 253 @Override 254 public BasicValue binaryOperation(final AbstractInsnNode insn, 255 final BasicValue value1, final BasicValue value2) 256 throws AnalyzerException { 257 switch (insn.getOpcode()) { 258 case IALOAD: 259 case BALOAD: 260 case CALOAD: 261 case SALOAD: 262 case IADD: 263 case ISUB: 264 case IMUL: 265 case IDIV: 266 case IREM: 267 case ISHL: 268 case ISHR: 269 case IUSHR: 270 case IAND: 271 case IOR: 272 case IXOR: 273 return BasicValue.INT_VALUE; 274 case FALOAD: 275 case FADD: 276 case FSUB: 277 case FMUL: 278 case FDIV: 279 case FREM: 280 return BasicValue.FLOAT_VALUE; 281 case LALOAD: 282 case LADD: 283 case LSUB: 284 case LMUL: 285 case LDIV: 286 case LREM: 287 case LSHL: 288 case LSHR: 289 case LUSHR: 290 case LAND: 291 case LOR: 292 case LXOR: 293 return BasicValue.LONG_VALUE; 294 case DALOAD: 295 case DADD: 296 case DSUB: 297 case DMUL: 298 case DDIV: 299 case DREM: 300 return BasicValue.DOUBLE_VALUE; 301 case AALOAD: 302 return BasicValue.REFERENCE_VALUE; 303 case LCMP: 304 case FCMPL: 305 case FCMPG: 306 case DCMPL: 307 case DCMPG: 308 return BasicValue.INT_VALUE; 309 case IF_ICMPEQ: 310 case IF_ICMPNE: 311 case IF_ICMPLT: 312 case IF_ICMPGE: 313 case IF_ICMPGT: 314 case IF_ICMPLE: 315 case IF_ACMPEQ: 316 case IF_ACMPNE: 317 case PUTFIELD: 318 return null; 319 default: 320 throw new Error("Internal error."); 321 } 322 } 323 324 @Override 325 public BasicValue ternaryOperation(final AbstractInsnNode insn, 326 final BasicValue value1, final BasicValue value2, 327 final BasicValue value3) throws AnalyzerException { 328 return null; 329 } 330 331 @Override 332 public BasicValue naryOperation(final AbstractInsnNode insn, 333 final List<? extends BasicValue> values) throws AnalyzerException { 334 int opcode = insn.getOpcode(); 335 if (opcode == MULTIANEWARRAY) { 336 return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc)); 337 } else if (opcode == INVOKEDYNAMIC) { 338 return newValue(Type 339 .getReturnType(((InvokeDynamicInsnNode) insn).desc)); 340 } else { 341 return newValue(Type.getReturnType(((MethodInsnNode) insn).desc)); 342 } 343 } 344 345 @Override 346 public void returnOperation(final AbstractInsnNode insn, 347 final BasicValue value, final BasicValue expected) 348 throws AnalyzerException { 349 } 350 351 @Override 352 public BasicValue merge(final BasicValue v, final BasicValue w) { 353 if (!v.equals(w)) { 354 return BasicValue.UNINITIALIZED_VALUE; 355 } 356 return v; 357 } 358}