Home | History | Annotate | Download | only in code
      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