/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.dx.cf.code; import com.android.dx.rop.cst.CstType; import com.android.dx.rop.type.Prototype; import com.android.dx.rop.type.Type; import com.android.dx.rop.type.TypeBearer; import com.android.dx.util.Hex; /** * {@link Machine} which keeps track of known values but does not do * smart/realistic reference type calculations. */ public class ValueAwareMachine extends BaseMachine { /** * Constructs an instance. * * @param prototype {@code non-null;} the prototype for the associated * method */ public ValueAwareMachine(Prototype prototype) { super(prototype); } /** {@inheritDoc} */ public void run(Frame frame, int offset, int opcode) { switch (opcode) { case ByteOps.NOP: case ByteOps.IASTORE: case ByteOps.POP: case ByteOps.POP2: case ByteOps.IFEQ: case ByteOps.IFNE: case ByteOps.IFLT: case ByteOps.IFGE: case ByteOps.IFGT: case ByteOps.IFLE: case ByteOps.IF_ICMPEQ: case ByteOps.IF_ICMPNE: case ByteOps.IF_ICMPLT: case ByteOps.IF_ICMPGE: case ByteOps.IF_ICMPGT: case ByteOps.IF_ICMPLE: case ByteOps.IF_ACMPEQ: case ByteOps.IF_ACMPNE: case ByteOps.GOTO: case ByteOps.RET: case ByteOps.LOOKUPSWITCH: case ByteOps.IRETURN: case ByteOps.RETURN: case ByteOps.PUTSTATIC: case ByteOps.PUTFIELD: case ByteOps.ATHROW: case ByteOps.MONITORENTER: case ByteOps.MONITOREXIT: case ByteOps.IFNULL: case ByteOps.IFNONNULL: { // Nothing to do for these ops in this class. clearResult(); break; } case ByteOps.LDC: case ByteOps.LDC2_W: { setResult((TypeBearer) getAuxCst()); break; } case ByteOps.ILOAD: case ByteOps.ISTORE: { setResult(arg(0)); break; } case ByteOps.IALOAD: case ByteOps.IADD: case ByteOps.ISUB: case ByteOps.IMUL: case ByteOps.IDIV: case ByteOps.IREM: case ByteOps.INEG: case ByteOps.ISHL: case ByteOps.ISHR: case ByteOps.IUSHR: case ByteOps.IAND: case ByteOps.IOR: case ByteOps.IXOR: case ByteOps.IINC: case ByteOps.I2L: case ByteOps.I2F: case ByteOps.I2D: case ByteOps.L2I: case ByteOps.L2F: case ByteOps.L2D: case ByteOps.F2I: case ByteOps.F2L: case ByteOps.F2D: case ByteOps.D2I: case ByteOps.D2L: case ByteOps.D2F: case ByteOps.I2B: case ByteOps.I2C: case ByteOps.I2S: case ByteOps.LCMP: case ByteOps.FCMPL: case ByteOps.FCMPG: case ByteOps.DCMPL: case ByteOps.DCMPG: case ByteOps.ARRAYLENGTH: { setResult(getAuxType()); break; } case ByteOps.DUP: case ByteOps.DUP_X1: case ByteOps.DUP_X2: case ByteOps.DUP2: case ByteOps.DUP2_X1: case ByteOps.DUP2_X2: case ByteOps.SWAP: { clearResult(); for (int pattern = getAuxInt(); pattern != 0; pattern >>= 4) { int which = (pattern & 0x0f) - 1; addResult(arg(which)); } break; } case ByteOps.JSR: { setResult(new ReturnAddress(getAuxTarget())); break; } case ByteOps.GETSTATIC: case ByteOps.GETFIELD: case ByteOps.INVOKEVIRTUAL: case ByteOps.INVOKESTATIC: case ByteOps.INVOKEINTERFACE: { Type type = ((TypeBearer) getAuxCst()).getType(); if (type == Type.VOID) { clearResult(); } else { setResult(type); } break; } case ByteOps.INVOKESPECIAL: { Type thisType = arg(0).getType(); if (thisType.isUninitialized()) { frame.makeInitialized(thisType); } Type type = ((TypeBearer) getAuxCst()).getType(); if (type == Type.VOID) { clearResult(); } else { setResult(type); } break; } case ByteOps.NEW: { Type type = ((CstType) getAuxCst()).getClassType(); setResult(type.asUninitialized(offset)); break; } case ByteOps.NEWARRAY: case ByteOps.CHECKCAST: case ByteOps.MULTIANEWARRAY: { Type type = ((CstType) getAuxCst()).getClassType(); setResult(type); break; } case ByteOps.ANEWARRAY: { Type type = ((CstType) getAuxCst()).getClassType(); setResult(type.getArrayType()); break; } case ByteOps.INSTANCEOF: { setResult(Type.INT); break; } default: { throw new RuntimeException("shouldn't happen: " + Hex.u1(opcode)); } } storeResults(frame); } }