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