1/* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.dx.cf.code; 18 19import com.android.dx.rop.cst.CstType; 20import com.android.dx.rop.type.Prototype; 21import com.android.dx.rop.type.Type; 22import com.android.dx.rop.type.TypeBearer; 23import com.android.dx.util.Hex; 24 25/** 26 * {@link Machine} which keeps track of known values but does not do 27 * smart/realistic reference type calculations. 28 */ 29public class ValueAwareMachine extends BaseMachine { 30 /** 31 * Constructs an instance. 32 * 33 * @param prototype non-null; the prototype for the associated method 34 */ 35 public ValueAwareMachine(Prototype prototype) { 36 super(prototype); 37 } 38 39 /** {@inheritDoc} */ 40 public void run(Frame frame, int offset, int opcode) { 41 switch (opcode) { 42 case ByteOps.NOP: 43 case ByteOps.IASTORE: 44 case ByteOps.POP: 45 case ByteOps.POP2: 46 case ByteOps.IFEQ: 47 case ByteOps.IFNE: 48 case ByteOps.IFLT: 49 case ByteOps.IFGE: 50 case ByteOps.IFGT: 51 case ByteOps.IFLE: 52 case ByteOps.IF_ICMPEQ: 53 case ByteOps.IF_ICMPNE: 54 case ByteOps.IF_ICMPLT: 55 case ByteOps.IF_ICMPGE: 56 case ByteOps.IF_ICMPGT: 57 case ByteOps.IF_ICMPLE: 58 case ByteOps.IF_ACMPEQ: 59 case ByteOps.IF_ACMPNE: 60 case ByteOps.GOTO: 61 case ByteOps.RET: 62 case ByteOps.LOOKUPSWITCH: 63 case ByteOps.IRETURN: 64 case ByteOps.RETURN: 65 case ByteOps.PUTSTATIC: 66 case ByteOps.PUTFIELD: 67 case ByteOps.ATHROW: 68 case ByteOps.MONITORENTER: 69 case ByteOps.MONITOREXIT: 70 case ByteOps.IFNULL: 71 case ByteOps.IFNONNULL: { 72 // Nothing to do for these ops in this class. 73 clearResult(); 74 break; 75 } 76 case ByteOps.LDC: 77 case ByteOps.LDC2_W: { 78 setResult((TypeBearer) getAuxCst()); 79 break; 80 } 81 case ByteOps.ILOAD: 82 case ByteOps.ISTORE: { 83 setResult(arg(0)); 84 break; 85 } 86 case ByteOps.IALOAD: 87 case ByteOps.IADD: 88 case ByteOps.ISUB: 89 case ByteOps.IMUL: 90 case ByteOps.IDIV: 91 case ByteOps.IREM: 92 case ByteOps.INEG: 93 case ByteOps.ISHL: 94 case ByteOps.ISHR: 95 case ByteOps.IUSHR: 96 case ByteOps.IAND: 97 case ByteOps.IOR: 98 case ByteOps.IXOR: 99 case ByteOps.IINC: 100 case ByteOps.I2L: 101 case ByteOps.I2F: 102 case ByteOps.I2D: 103 case ByteOps.L2I: 104 case ByteOps.L2F: 105 case ByteOps.L2D: 106 case ByteOps.F2I: 107 case ByteOps.F2L: 108 case ByteOps.F2D: 109 case ByteOps.D2I: 110 case ByteOps.D2L: 111 case ByteOps.D2F: 112 case ByteOps.I2B: 113 case ByteOps.I2C: 114 case ByteOps.I2S: 115 case ByteOps.LCMP: 116 case ByteOps.FCMPL: 117 case ByteOps.FCMPG: 118 case ByteOps.DCMPL: 119 case ByteOps.DCMPG: 120 case ByteOps.ARRAYLENGTH: { 121 setResult(getAuxType()); 122 break; 123 } 124 case ByteOps.DUP: 125 case ByteOps.DUP_X1: 126 case ByteOps.DUP_X2: 127 case ByteOps.DUP2: 128 case ByteOps.DUP2_X1: 129 case ByteOps.DUP2_X2: 130 case ByteOps.SWAP: { 131 clearResult(); 132 for (int pattern = getAuxInt(); pattern != 0; pattern >>= 4) { 133 int which = (pattern & 0x0f) - 1; 134 addResult(arg(which)); 135 } 136 break; 137 } 138 139 case ByteOps.JSR: { 140 setResult(new ReturnAddress(getAuxTarget())); 141 break; 142 } 143 case ByteOps.GETSTATIC: 144 case ByteOps.GETFIELD: 145 case ByteOps.INVOKEVIRTUAL: 146 case ByteOps.INVOKESTATIC: 147 case ByteOps.INVOKEINTERFACE: { 148 Type type = ((TypeBearer) getAuxCst()).getType(); 149 if (type == Type.VOID) { 150 clearResult(); 151 } else { 152 setResult(type); 153 } 154 break; 155 } 156 case ByteOps.INVOKESPECIAL: { 157 Type thisType = arg(0).getType(); 158 if (thisType.isUninitialized()) { 159 frame.makeInitialized(thisType); 160 } 161 Type type = ((TypeBearer) getAuxCst()).getType(); 162 if (type == Type.VOID) { 163 clearResult(); 164 } else { 165 setResult(type); 166 } 167 break; 168 } 169 case ByteOps.NEW: { 170 Type type = ((CstType) getAuxCst()).getClassType(); 171 setResult(type.asUninitialized(offset)); 172 break; 173 } 174 case ByteOps.NEWARRAY: 175 case ByteOps.CHECKCAST: 176 case ByteOps.MULTIANEWARRAY: { 177 Type type = ((CstType) getAuxCst()).getClassType(); 178 setResult(type); 179 break; 180 } 181 case ByteOps.ANEWARRAY: { 182 Type type = ((CstType) getAuxCst()).getClassType(); 183 setResult(type.getArrayType()); 184 break; 185 } 186 case ByteOps.INSTANCEOF: { 187 setResult(Type.INT); 188 break; 189 } 190 default: { 191 throw new RuntimeException("shouldn't happen: " + 192 Hex.u1(opcode)); 193 } 194 } 195 196 storeResults(frame); 197 } 198} 199