Home | History | Annotate | Download | only in analysis
      1 /*
      2  * Javassist, a Java-bytecode translator toolkit.
      3  * Copyright (C) 1999-2007 Shigeru Chiba, and others. All Rights Reserved.
      4  *
      5  * The contents of this file are subject to the Mozilla Public License Version
      6  * 1.1 (the "License"); you may not use this file except in compliance with
      7  * the License.  Alternatively, the contents of this file may be used under
      8  * the terms of the GNU Lesser General Public License Version 2.1 or later.
      9  *
     10  * Software distributed under the License is distributed on an "AS IS" basis,
     11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
     12  * for the specific language governing rights and limitations under the
     13  * License.
     14  */
     15 package javassist.bytecode.analysis;
     16 
     17 import javassist.ClassPool;
     18 import javassist.CtClass;
     19 import javassist.NotFoundException;
     20 import javassist.bytecode.BadBytecode;
     21 import javassist.bytecode.CodeIterator;
     22 import javassist.bytecode.ConstPool;
     23 import javassist.bytecode.Descriptor;
     24 import javassist.bytecode.MethodInfo;
     25 import javassist.bytecode.Opcode;
     26 
     27 /**
     28  * Executor is responsible for modeling the effects of a JVM instruction on a frame.
     29  *
     30  * @author Jason T. Greene
     31  */
     32 public class Executor implements Opcode {
     33     private final ConstPool constPool;
     34     private final ClassPool classPool;
     35     private final Type STRING_TYPE;
     36     private final Type CLASS_TYPE;
     37     private final Type THROWABLE_TYPE;
     38     private int lastPos;
     39 
     40     public Executor(ClassPool classPool, ConstPool constPool) {
     41         this.constPool = constPool;
     42         this.classPool = classPool;
     43 
     44         try {
     45             STRING_TYPE = getType("java.lang.String");
     46             CLASS_TYPE = getType("java.lang.Class");
     47             THROWABLE_TYPE = getType("java.lang.Throwable");
     48         } catch (Exception e) {
     49             throw new RuntimeException(e);
     50         }
     51     }
     52 
     53 
     54     /**
     55      * Execute the instruction, modeling the effects on the specified frame and subroutine.
     56      * If a subroutine is passed, the access flags will be modified if this instruction accesses
     57      * the local variable table.
     58      *
     59      * @param method the method containing the instruction
     60      * @param pos the position of the instruction in the method
     61      * @param iter the code iterator used to find the instruction
     62      * @param frame the frame to modify to represent the result of the instruction
     63      * @param subroutine the optional subroutine this instruction belongs to.
     64      * @throws BadBytecode if the bytecode violates the jvm spec
     65      */
     66     public void execute(MethodInfo method, int pos, CodeIterator iter, Frame frame, Subroutine subroutine) throws BadBytecode {
     67         this.lastPos = pos;
     68         int opcode = iter.byteAt(pos);
     69 
     70 
     71         // Declared opcode in order
     72         switch (opcode) {
     73             case NOP:
     74                 break;
     75             case ACONST_NULL:
     76                 frame.push(Type.UNINIT);
     77                 break;
     78             case ICONST_M1:
     79             case ICONST_0:
     80             case ICONST_1:
     81             case ICONST_2:
     82             case ICONST_3:
     83             case ICONST_4:
     84             case ICONST_5:
     85                 frame.push(Type.INTEGER);
     86                 break;
     87             case LCONST_0:
     88             case LCONST_1:
     89                 frame.push(Type.LONG);
     90                 frame.push(Type.TOP);
     91                 break;
     92             case FCONST_0:
     93             case FCONST_1:
     94             case FCONST_2:
     95                 frame.push(Type.FLOAT);
     96                 break;
     97             case DCONST_0:
     98             case DCONST_1:
     99                 frame.push(Type.DOUBLE);
    100                 frame.push(Type.TOP);
    101                 break;
    102             case BIPUSH:
    103             case SIPUSH:
    104                 frame.push(Type.INTEGER);
    105                 break;
    106             case LDC:
    107                 evalLDC(iter.byteAt(pos + 1),  frame);
    108                 break;
    109             case LDC_W :
    110             case LDC2_W :
    111                 evalLDC(iter.u16bitAt(pos + 1), frame);
    112                 break;
    113             case ILOAD:
    114                 evalLoad(Type.INTEGER, iter.byteAt(pos + 1), frame, subroutine);
    115                 break;
    116             case LLOAD:
    117                 evalLoad(Type.LONG, iter.byteAt(pos + 1), frame, subroutine);
    118                 break;
    119             case FLOAD:
    120                 evalLoad(Type.FLOAT, iter.byteAt(pos + 1), frame, subroutine);
    121                 break;
    122             case DLOAD:
    123                 evalLoad(Type.DOUBLE, iter.byteAt(pos + 1), frame, subroutine);
    124                 break;
    125             case ALOAD:
    126                 evalLoad(Type.OBJECT, iter.byteAt(pos + 1), frame, subroutine);
    127                 break;
    128             case ILOAD_0:
    129             case ILOAD_1:
    130             case ILOAD_2:
    131             case ILOAD_3:
    132                 evalLoad(Type.INTEGER, opcode - ILOAD_0, frame, subroutine);
    133                 break;
    134             case LLOAD_0:
    135             case LLOAD_1:
    136             case LLOAD_2:
    137             case LLOAD_3:
    138                 evalLoad(Type.LONG, opcode - LLOAD_0, frame, subroutine);
    139                 break;
    140             case FLOAD_0:
    141             case FLOAD_1:
    142             case FLOAD_2:
    143             case FLOAD_3:
    144                 evalLoad(Type.FLOAT, opcode - FLOAD_0, frame, subroutine);
    145                 break;
    146             case DLOAD_0:
    147             case DLOAD_1:
    148             case DLOAD_2:
    149             case DLOAD_3:
    150                 evalLoad(Type.DOUBLE, opcode - DLOAD_0, frame, subroutine);
    151                 break;
    152             case ALOAD_0:
    153             case ALOAD_1:
    154             case ALOAD_2:
    155             case ALOAD_3:
    156                 evalLoad(Type.OBJECT, opcode - ALOAD_0, frame, subroutine);
    157                 break;
    158             case IALOAD:
    159                 evalArrayLoad(Type.INTEGER, frame);
    160                 break;
    161             case LALOAD:
    162                 evalArrayLoad(Type.LONG, frame);
    163                 break;
    164             case FALOAD:
    165                 evalArrayLoad(Type.FLOAT, frame);
    166                 break;
    167             case DALOAD:
    168                 evalArrayLoad(Type.DOUBLE, frame);
    169                 break;
    170             case AALOAD:
    171                 evalArrayLoad(Type.OBJECT, frame);
    172                 break;
    173             case BALOAD:
    174             case CALOAD:
    175             case SALOAD:
    176                 evalArrayLoad(Type.INTEGER, frame);
    177                 break;
    178             case ISTORE:
    179                 evalStore(Type.INTEGER, iter.byteAt(pos + 1), frame, subroutine);
    180                 break;
    181             case LSTORE:
    182                 evalStore(Type.LONG, iter.byteAt(pos + 1), frame, subroutine);
    183                 break;
    184             case FSTORE:
    185                 evalStore(Type.FLOAT, iter.byteAt(pos + 1), frame, subroutine);
    186                 break;
    187             case DSTORE:
    188                 evalStore(Type.DOUBLE, iter.byteAt(pos + 1), frame, subroutine);
    189                 break;
    190             case ASTORE:
    191                 evalStore(Type.OBJECT, iter.byteAt(pos + 1), frame, subroutine);
    192                 break;
    193             case ISTORE_0:
    194             case ISTORE_1:
    195             case ISTORE_2:
    196             case ISTORE_3:
    197                 evalStore(Type.INTEGER, opcode - ISTORE_0, frame, subroutine);
    198                 break;
    199             case LSTORE_0:
    200             case LSTORE_1:
    201             case LSTORE_2:
    202             case LSTORE_3:
    203                 evalStore(Type.LONG, opcode - LSTORE_0, frame, subroutine);
    204                 break;
    205             case FSTORE_0:
    206             case FSTORE_1:
    207             case FSTORE_2:
    208             case FSTORE_3:
    209                 evalStore(Type.FLOAT, opcode - FSTORE_0, frame, subroutine);
    210                 break;
    211             case DSTORE_0:
    212             case DSTORE_1:
    213             case DSTORE_2:
    214             case DSTORE_3:
    215                 evalStore(Type.DOUBLE, opcode - DSTORE_0, frame, subroutine);
    216                 break;
    217             case ASTORE_0:
    218             case ASTORE_1:
    219             case ASTORE_2:
    220             case ASTORE_3:
    221                 evalStore(Type.OBJECT, opcode - ASTORE_0, frame, subroutine);
    222                 break;
    223             case IASTORE:
    224                 evalArrayStore(Type.INTEGER, frame);
    225                 break;
    226             case LASTORE:
    227                 evalArrayStore(Type.LONG, frame);
    228                 break;
    229             case FASTORE:
    230                 evalArrayStore(Type.FLOAT, frame);
    231                 break;
    232             case DASTORE:
    233                 evalArrayStore(Type.DOUBLE, frame);
    234                 break;
    235             case AASTORE:
    236                 evalArrayStore(Type.OBJECT, frame);
    237                 break;
    238             case BASTORE:
    239             case CASTORE:
    240             case SASTORE:
    241                 evalArrayStore(Type.INTEGER, frame);
    242                 break;
    243             case POP:
    244                 if (frame.pop() == Type.TOP)
    245                     throw new BadBytecode("POP can not be used with a category 2 value, pos = " + pos);
    246                 break;
    247             case POP2:
    248                 frame.pop();
    249                 frame.pop();
    250                 break;
    251             case DUP: {
    252                 Type type = frame.peek();
    253                 if (type == Type.TOP)
    254                     throw new BadBytecode("DUP can not be used with a category 2 value, pos = " + pos);
    255 
    256                 frame.push(frame.peek());
    257                 break;
    258             }
    259             case DUP_X1:
    260             case DUP_X2: {
    261                 Type type = frame.peek();
    262                 if (type == Type.TOP)
    263                     throw new BadBytecode("DUP can not be used with a category 2 value, pos = " + pos);
    264                 int end = frame.getTopIndex();
    265                 int insert = end - (opcode - DUP_X1) - 1;
    266                 frame.push(type);
    267 
    268                 while (end > insert) {
    269                     frame.setStack(end, frame.getStack(end - 1));
    270                     end--;
    271                 }
    272                 frame.setStack(insert, type);
    273                 break;
    274             }
    275             case DUP2:
    276                 frame.push(frame.getStack(frame.getTopIndex() - 1));
    277                 frame.push(frame.getStack(frame.getTopIndex() - 1));
    278                 break;
    279             case DUP2_X1:
    280             case DUP2_X2: {
    281                 int end = frame.getTopIndex();
    282                 int insert = end - (opcode - DUP2_X1) - 1;
    283                 Type type1 = frame.getStack(frame.getTopIndex() - 1);
    284                 Type type2 = frame.peek();
    285                 frame.push(type1);
    286                 frame.push(type2);
    287                 while (end > insert) {
    288                     frame.setStack(end, frame.getStack(end - 2));
    289                     end--;
    290                 }
    291                 frame.setStack(insert, type2);
    292                 frame.setStack(insert - 1, type1);
    293                 break;
    294             }
    295             case SWAP: {
    296                 Type type1 = frame.pop();
    297                 Type type2 = frame.pop();
    298                 if (type1.getSize() == 2 || type2.getSize() == 2)
    299                     throw new BadBytecode("Swap can not be used with category 2 values, pos = " + pos);
    300                 frame.push(type1);
    301                 frame.push(type2);
    302                 break;
    303             }
    304 
    305             // Math
    306             case IADD:
    307                 evalBinaryMath(Type.INTEGER, frame);
    308                 break;
    309             case LADD:
    310                 evalBinaryMath(Type.LONG, frame);
    311                 break;
    312             case FADD:
    313                 evalBinaryMath(Type.FLOAT, frame);
    314                 break;
    315             case DADD:
    316                 evalBinaryMath(Type.DOUBLE, frame);
    317                 break;
    318             case ISUB:
    319                 evalBinaryMath(Type.INTEGER, frame);
    320                 break;
    321             case LSUB:
    322                 evalBinaryMath(Type.LONG, frame);
    323                 break;
    324             case FSUB:
    325                 evalBinaryMath(Type.FLOAT, frame);
    326                 break;
    327             case DSUB:
    328                 evalBinaryMath(Type.DOUBLE, frame);
    329                 break;
    330             case IMUL:
    331                 evalBinaryMath(Type.INTEGER, frame);
    332                 break;
    333             case LMUL:
    334                 evalBinaryMath(Type.LONG, frame);
    335                 break;
    336             case FMUL:
    337                 evalBinaryMath(Type.FLOAT, frame);
    338                 break;
    339             case DMUL:
    340                 evalBinaryMath(Type.DOUBLE, frame);
    341                 break;
    342             case IDIV:
    343                 evalBinaryMath(Type.INTEGER, frame);
    344                 break;
    345             case LDIV:
    346                 evalBinaryMath(Type.LONG, frame);
    347                 break;
    348             case FDIV:
    349                 evalBinaryMath(Type.FLOAT, frame);
    350                 break;
    351             case DDIV:
    352                 evalBinaryMath(Type.DOUBLE, frame);
    353                 break;
    354             case IREM:
    355                 evalBinaryMath(Type.INTEGER, frame);
    356                 break;
    357             case LREM:
    358                 evalBinaryMath(Type.LONG, frame);
    359                 break;
    360             case FREM:
    361                 evalBinaryMath(Type.FLOAT, frame);
    362                 break;
    363             case DREM:
    364                 evalBinaryMath(Type.DOUBLE, frame);
    365                 break;
    366 
    367             // Unary
    368             case INEG:
    369                 verifyAssignable(Type.INTEGER, simplePeek(frame));
    370                 break;
    371             case LNEG:
    372                 verifyAssignable(Type.LONG, simplePeek(frame));
    373                 break;
    374             case FNEG:
    375                 verifyAssignable(Type.FLOAT, simplePeek(frame));
    376                 break;
    377             case DNEG:
    378                 verifyAssignable(Type.DOUBLE, simplePeek(frame));
    379                 break;
    380 
    381             // Shifts
    382             case ISHL:
    383                 evalShift(Type.INTEGER, frame);
    384                 break;
    385             case LSHL:
    386                 evalShift(Type.LONG, frame);
    387                 break;
    388             case ISHR:
    389                 evalShift(Type.INTEGER, frame);
    390                 break;
    391             case LSHR:
    392                 evalShift(Type.LONG, frame);
    393                 break;
    394             case IUSHR:
    395                 evalShift(Type.INTEGER,frame);
    396                 break;
    397             case LUSHR:
    398                 evalShift(Type.LONG, frame);
    399                 break;
    400 
    401             // Bitwise Math
    402             case IAND:
    403                 evalBinaryMath(Type.INTEGER, frame);
    404                 break;
    405             case LAND:
    406                 evalBinaryMath(Type.LONG, frame);
    407                 break;
    408             case IOR:
    409                 evalBinaryMath(Type.INTEGER, frame);
    410                 break;
    411             case LOR:
    412                 evalBinaryMath(Type.LONG, frame);
    413                 break;
    414             case IXOR:
    415                 evalBinaryMath(Type.INTEGER, frame);
    416                 break;
    417             case LXOR:
    418                 evalBinaryMath(Type.LONG, frame);
    419                 break;
    420 
    421             case IINC: {
    422                 int index = iter.byteAt(pos + 1);
    423                 verifyAssignable(Type.INTEGER, frame.getLocal(index));
    424                 access(index, Type.INTEGER, subroutine);
    425                 break;
    426             }
    427 
    428             // Conversion
    429             case I2L:
    430                 verifyAssignable(Type.INTEGER, simplePop(frame));
    431                 simplePush(Type.LONG, frame);
    432                 break;
    433             case I2F:
    434                 verifyAssignable(Type.INTEGER, simplePop(frame));
    435                 simplePush(Type.FLOAT, frame);
    436                 break;
    437             case I2D:
    438                 verifyAssignable(Type.INTEGER, simplePop(frame));
    439                 simplePush(Type.DOUBLE, frame);
    440                 break;
    441             case L2I:
    442                 verifyAssignable(Type.LONG, simplePop(frame));
    443                 simplePush(Type.INTEGER, frame);
    444                 break;
    445             case L2F:
    446                 verifyAssignable(Type.LONG, simplePop(frame));
    447                 simplePush(Type.FLOAT, frame);
    448                 break;
    449             case L2D:
    450                 verifyAssignable(Type.LONG, simplePop(frame));
    451                 simplePush(Type.DOUBLE, frame);
    452                 break;
    453             case F2I:
    454                 verifyAssignable(Type.FLOAT, simplePop(frame));
    455                 simplePush(Type.INTEGER, frame);
    456                 break;
    457             case F2L:
    458                 verifyAssignable(Type.FLOAT, simplePop(frame));
    459                 simplePush(Type.LONG, frame);
    460                 break;
    461             case F2D:
    462                 verifyAssignable(Type.FLOAT, simplePop(frame));
    463                 simplePush(Type.DOUBLE, frame);
    464                 break;
    465             case D2I:
    466                 verifyAssignable(Type.DOUBLE, simplePop(frame));
    467                 simplePush(Type.INTEGER, frame);
    468                 break;
    469             case D2L:
    470                 verifyAssignable(Type.DOUBLE, simplePop(frame));
    471                 simplePush(Type.LONG, frame);
    472                 break;
    473             case D2F:
    474                 verifyAssignable(Type.DOUBLE, simplePop(frame));
    475                 simplePush(Type.FLOAT, frame);
    476                 break;
    477             case I2B:
    478             case I2C:
    479             case I2S:
    480                 verifyAssignable(Type.INTEGER, frame.peek());
    481                 break;
    482             case LCMP:
    483                 verifyAssignable(Type.LONG, simplePop(frame));
    484                 verifyAssignable(Type.LONG, simplePop(frame));
    485                 frame.push(Type.INTEGER);
    486                 break;
    487             case FCMPL:
    488             case FCMPG:
    489                 verifyAssignable(Type.FLOAT, simplePop(frame));
    490                 verifyAssignable(Type.FLOAT, simplePop(frame));
    491                 frame.push(Type.INTEGER);
    492                 break;
    493             case DCMPL:
    494             case DCMPG:
    495                 verifyAssignable(Type.DOUBLE, simplePop(frame));
    496                 verifyAssignable(Type.DOUBLE, simplePop(frame));
    497                 frame.push(Type.INTEGER);
    498                 break;
    499 
    500             // Control flow
    501             case IFEQ:
    502             case IFNE:
    503             case IFLT:
    504             case IFGE:
    505             case IFGT:
    506             case IFLE:
    507                 verifyAssignable(Type.INTEGER, simplePop(frame));
    508                 break;
    509             case IF_ICMPEQ:
    510             case IF_ICMPNE:
    511             case IF_ICMPLT:
    512             case IF_ICMPGE:
    513             case IF_ICMPGT:
    514             case IF_ICMPLE:
    515                 verifyAssignable(Type.INTEGER, simplePop(frame));
    516                 verifyAssignable(Type.INTEGER, simplePop(frame));
    517                 break;
    518             case IF_ACMPEQ:
    519             case IF_ACMPNE:
    520                 verifyAssignable(Type.OBJECT, simplePop(frame));
    521                 verifyAssignable(Type.OBJECT, simplePop(frame));
    522                 break;
    523             case GOTO:
    524                 break;
    525             case JSR:
    526                 frame.push(Type.RETURN_ADDRESS);
    527                 break;
    528             case RET:
    529                 verifyAssignable(Type.RETURN_ADDRESS, frame.getLocal(iter.byteAt(pos + 1)));
    530                 break;
    531             case TABLESWITCH:
    532             case LOOKUPSWITCH:
    533             case IRETURN:
    534                 verifyAssignable(Type.INTEGER, simplePop(frame));
    535                 break;
    536             case LRETURN:
    537                 verifyAssignable(Type.LONG, simplePop(frame));
    538                 break;
    539             case FRETURN:
    540                 verifyAssignable(Type.FLOAT, simplePop(frame));
    541                 break;
    542             case DRETURN:
    543                 verifyAssignable(Type.DOUBLE, simplePop(frame));
    544                 break;
    545             case ARETURN:
    546                 try {
    547                     CtClass returnType = Descriptor.getReturnType(method.getDescriptor(), classPool);
    548                     verifyAssignable(Type.get(returnType), simplePop(frame));
    549                 } catch (NotFoundException e) {
    550                    throw new RuntimeException(e);
    551                 }
    552                 break;
    553             case RETURN:
    554                 break;
    555             case GETSTATIC:
    556                 evalGetField(opcode, iter.u16bitAt(pos + 1), frame);
    557                 break;
    558             case PUTSTATIC:
    559                 evalPutField(opcode, iter.u16bitAt(pos + 1), frame);
    560                 break;
    561             case GETFIELD:
    562                 evalGetField(opcode, iter.u16bitAt(pos + 1), frame);
    563                 break;
    564             case PUTFIELD:
    565                 evalPutField(opcode, iter.u16bitAt(pos + 1), frame);
    566                 break;
    567             case INVOKEVIRTUAL:
    568             case INVOKESPECIAL:
    569             case INVOKESTATIC:
    570                 evalInvokeMethod(opcode, iter.u16bitAt(pos + 1), frame);
    571                 break;
    572             case INVOKEINTERFACE:
    573                 evalInvokeIntfMethod(opcode, iter.u16bitAt(pos + 1), frame);
    574                 break;
    575             case 186:
    576                 throw new RuntimeException("Bad opcode 186");
    577             case NEW:
    578                 frame.push(resolveClassInfo(constPool.getClassInfo(iter.u16bitAt(pos + 1))));
    579                 break;
    580             case NEWARRAY:
    581                 evalNewArray(pos, iter, frame);
    582                 break;
    583             case ANEWARRAY:
    584                 evalNewObjectArray(pos, iter, frame);
    585                 break;
    586             case ARRAYLENGTH: {
    587                 Type array = simplePop(frame);
    588                 if (! array.isArray() && array != Type.UNINIT)
    589                     throw new BadBytecode("Array length passed a non-array [pos = " + pos + "]: " + array);
    590                 frame.push(Type.INTEGER);
    591                 break;
    592             }
    593             case ATHROW:
    594                 verifyAssignable(THROWABLE_TYPE, simplePop(frame));
    595                 break;
    596             case CHECKCAST:
    597                 verifyAssignable(Type.OBJECT, simplePop(frame));
    598                 frame.push(typeFromDesc(constPool.getClassInfo(iter.u16bitAt(pos + 1))));
    599                 break;
    600             case INSTANCEOF:
    601                 verifyAssignable(Type.OBJECT, simplePop(frame));
    602                 frame.push(Type.INTEGER);
    603                 break;
    604             case MONITORENTER:
    605             case MONITOREXIT:
    606                 verifyAssignable(Type.OBJECT, simplePop(frame));
    607                 break;
    608             case WIDE:
    609                 evalWide(pos, iter, frame, subroutine);
    610                 break;
    611             case MULTIANEWARRAY:
    612                 evalNewObjectArray(pos, iter, frame);
    613                 break;
    614             case IFNULL:
    615             case IFNONNULL:
    616                 verifyAssignable(Type.OBJECT, simplePop(frame));
    617                 break;
    618             case GOTO_W:
    619                 break;
    620             case JSR_W:
    621                 frame.push(Type.RETURN_ADDRESS);
    622                 break;
    623         }
    624     }
    625 
    626     private Type zeroExtend(Type type) {
    627         if (type == Type.SHORT || type == Type.BYTE || type == Type.CHAR || type == Type.BOOLEAN)
    628             return  Type.INTEGER;
    629 
    630         return type;
    631     }
    632 
    633     private void evalArrayLoad(Type expectedComponent, Frame frame) throws BadBytecode {
    634         Type index = frame.pop();
    635         Type array = frame.pop();
    636 
    637         // Special case, an array defined by aconst_null
    638         // TODO - we might need to be more inteligent about this
    639         if (array == Type.UNINIT) {
    640             verifyAssignable(Type.INTEGER, index);
    641             if (expectedComponent == Type.OBJECT) {
    642                 simplePush(Type.UNINIT, frame);
    643             } else {
    644                 simplePush(expectedComponent, frame);
    645             }
    646             return;
    647         }
    648 
    649         Type component = array.getComponent();
    650 
    651         if (component == null)
    652             throw new BadBytecode("Not an array! [pos = " + lastPos + "]: " + component);
    653 
    654         component = zeroExtend(component);
    655 
    656         verifyAssignable(expectedComponent, component);
    657         verifyAssignable(Type.INTEGER, index);
    658         simplePush(component, frame);
    659     }
    660 
    661     private void evalArrayStore(Type expectedComponent, Frame frame) throws BadBytecode {
    662         Type value = simplePop(frame);
    663         Type index = frame.pop();
    664         Type array = frame.pop();
    665 
    666         if (array == Type.UNINIT) {
    667             verifyAssignable(Type.INTEGER, index);
    668             return;
    669         }
    670 
    671         Type component = array.getComponent();
    672 
    673         if (component == null)
    674             throw new BadBytecode("Not an array! [pos = " + lastPos + "]: " + component);
    675 
    676         component = zeroExtend(component);
    677 
    678         verifyAssignable(expectedComponent, component);
    679         verifyAssignable(Type.INTEGER, index);
    680 
    681         // This intentionally only checks for Object on aastore
    682         // downconverting of an array (no casts)
    683         // e.g. Object[] blah = new String[];
    684         //      blah[2] = (Object) "test";
    685         //      blah[3] = new Integer(); // compiler doesnt catch it (has legal bytecode),
    686         //                               // but will throw arraystoreexception
    687         if (expectedComponent == Type.OBJECT) {
    688             verifyAssignable(expectedComponent, value);
    689         } else {
    690             verifyAssignable(component, value);
    691         }
    692     }
    693 
    694     private void evalBinaryMath(Type expected, Frame frame) throws BadBytecode {
    695         Type value2 = simplePop(frame);
    696         Type value1 = simplePop(frame);
    697 
    698         verifyAssignable(expected, value2);
    699         verifyAssignable(expected, value1);
    700         simplePush(value1, frame);
    701     }
    702 
    703     private void evalGetField(int opcode, int index, Frame frame) throws BadBytecode {
    704         String desc = constPool.getFieldrefType(index);
    705         Type type = zeroExtend(typeFromDesc(desc));
    706 
    707         if (opcode == GETFIELD) {
    708             Type objectType = resolveClassInfo(constPool.getFieldrefClassName(index));
    709             verifyAssignable(objectType, simplePop(frame));
    710         }
    711 
    712         simplePush(type, frame);
    713     }
    714 
    715     private void evalInvokeIntfMethod(int opcode, int index, Frame frame) throws BadBytecode {
    716         String desc = constPool.getInterfaceMethodrefType(index);
    717         Type[] types = paramTypesFromDesc(desc);
    718         int i = types.length;
    719 
    720         while (i > 0)
    721             verifyAssignable(zeroExtend(types[--i]), simplePop(frame));
    722 
    723         String classInfo = constPool.getInterfaceMethodrefClassName(index);
    724         Type objectType = resolveClassInfo(classInfo);
    725         verifyAssignable(objectType, simplePop(frame));
    726 
    727         Type returnType = returnTypeFromDesc(desc);
    728         if (returnType != Type.VOID)
    729             simplePush(zeroExtend(returnType), frame);
    730     }
    731 
    732     private void evalInvokeMethod(int opcode, int index, Frame frame) throws BadBytecode {
    733         String desc = constPool.getMethodrefType(index);
    734         Type[] types = paramTypesFromDesc(desc);
    735         int i = types.length;
    736 
    737         while (i > 0)
    738             verifyAssignable(zeroExtend(types[--i]), simplePop(frame));
    739 
    740         if (opcode != INVOKESTATIC) {
    741             Type objectType = resolveClassInfo(constPool.getMethodrefClassName(index));
    742             verifyAssignable(objectType, simplePop(frame));
    743         }
    744 
    745         Type returnType = returnTypeFromDesc(desc);
    746         if (returnType != Type.VOID)
    747             simplePush(zeroExtend(returnType), frame);
    748     }
    749 
    750 
    751     private void evalLDC(int index, Frame frame) throws BadBytecode {
    752         int tag = constPool.getTag(index);
    753         Type type;
    754         switch (tag) {
    755         case ConstPool.CONST_String:
    756             type = STRING_TYPE;
    757             break;
    758         case ConstPool.CONST_Integer:
    759             type = Type.INTEGER;
    760             break;
    761         case ConstPool.CONST_Float:
    762             type = Type.FLOAT;
    763             break;
    764         case ConstPool.CONST_Long:
    765             type = Type.LONG;
    766             break;
    767         case ConstPool.CONST_Double:
    768             type = Type.DOUBLE;
    769             break;
    770         case ConstPool.CONST_Class:
    771             type = CLASS_TYPE;
    772             break;
    773         default:
    774             throw new BadBytecode("bad LDC [pos = " + lastPos + "]: " + tag);
    775         }
    776 
    777         simplePush(type, frame);
    778     }
    779 
    780     private void evalLoad(Type expected, int index, Frame frame, Subroutine subroutine) throws BadBytecode {
    781         Type type = frame.getLocal(index);
    782 
    783         verifyAssignable(expected, type);
    784 
    785         simplePush(type, frame);
    786         access(index, type, subroutine);
    787     }
    788 
    789     private void evalNewArray(int pos, CodeIterator iter, Frame frame) throws BadBytecode {
    790         verifyAssignable(Type.INTEGER, simplePop(frame));
    791         Type type = null;
    792         int typeInfo = iter.byteAt(pos + 1);
    793         switch (typeInfo) {
    794             case T_BOOLEAN:
    795                 type = getType("boolean[]");
    796                 break;
    797             case T_CHAR:
    798                 type = getType("char[]");
    799                 break;
    800             case T_BYTE:
    801                 type = getType("byte[]");
    802                 break;
    803             case T_SHORT:
    804                 type = getType("short[]");
    805                 break;
    806             case T_INT:
    807                 type = getType("int[]");
    808                 break;
    809             case T_LONG:
    810                 type = getType("long[]");
    811                 break;
    812             case T_FLOAT:
    813                 type = getType("float[]");
    814                 break;
    815             case T_DOUBLE:
    816                 type = getType("double[]");
    817                 break;
    818             default:
    819                 throw new BadBytecode("Invalid array type [pos = " + pos + "]: " + typeInfo);
    820 
    821         }
    822 
    823         frame.push(type);
    824     }
    825 
    826     private void evalNewObjectArray(int pos, CodeIterator iter, Frame frame) throws BadBytecode {
    827         // Convert to x[] format
    828         Type type = resolveClassInfo(constPool.getClassInfo(iter.u16bitAt(pos + 1)));
    829         String name = type.getCtClass().getName();
    830         int opcode = iter.byteAt(pos);
    831         int dimensions;
    832 
    833         if (opcode == MULTIANEWARRAY) {
    834             dimensions = iter.byteAt(pos + 3);
    835         } else {
    836             name = name + "[]";
    837             dimensions = 1;
    838         }
    839 
    840         while (dimensions-- > 0) {
    841             verifyAssignable(Type.INTEGER, simplePop(frame));
    842         }
    843 
    844         simplePush(getType(name), frame);
    845     }
    846 
    847     private void evalPutField(int opcode, int index, Frame frame) throws BadBytecode {
    848         String desc = constPool.getFieldrefType(index);
    849         Type type = zeroExtend(typeFromDesc(desc));
    850 
    851         verifyAssignable(type, simplePop(frame));
    852 
    853         if (opcode == PUTFIELD) {
    854             Type objectType = resolveClassInfo(constPool.getFieldrefClassName(index));
    855             verifyAssignable(objectType, simplePop(frame));
    856         }
    857     }
    858 
    859     private void evalShift(Type expected, Frame frame) throws BadBytecode {
    860         Type value2 = simplePop(frame);
    861         Type value1 = simplePop(frame);
    862 
    863         verifyAssignable(Type.INTEGER, value2);
    864         verifyAssignable(expected, value1);
    865         simplePush(value1, frame);
    866     }
    867 
    868     private void evalStore(Type expected, int index, Frame frame, Subroutine subroutine) throws BadBytecode {
    869         Type type = simplePop(frame);
    870 
    871         // RETURN_ADDRESS is allowed by ASTORE
    872         if (! (expected == Type.OBJECT && type == Type.RETURN_ADDRESS))
    873             verifyAssignable(expected, type);
    874         simpleSetLocal(index, type, frame);
    875         access(index, type, subroutine);
    876     }
    877 
    878     private void evalWide(int pos, CodeIterator iter, Frame frame, Subroutine subroutine) throws BadBytecode {
    879         int opcode = iter.byteAt(pos + 1);
    880         int index = iter.u16bitAt(pos + 2);
    881         switch (opcode) {
    882             case ILOAD:
    883                 evalLoad(Type.INTEGER, index, frame, subroutine);
    884                 break;
    885             case LLOAD:
    886                 evalLoad(Type.LONG, index, frame, subroutine);
    887                 break;
    888             case FLOAD:
    889                 evalLoad(Type.FLOAT, index, frame, subroutine);
    890                 break;
    891             case DLOAD:
    892                 evalLoad(Type.DOUBLE, index, frame, subroutine);
    893                 break;
    894             case ALOAD:
    895                 evalLoad(Type.OBJECT, index, frame, subroutine);
    896                 break;
    897             case ISTORE:
    898                 evalStore(Type.INTEGER, index, frame, subroutine);
    899                 break;
    900             case LSTORE:
    901                 evalStore(Type.LONG, index, frame, subroutine);
    902                 break;
    903             case FSTORE:
    904                 evalStore(Type.FLOAT, index, frame, subroutine);
    905                 break;
    906             case DSTORE:
    907                 evalStore(Type.DOUBLE, index, frame, subroutine);
    908                 break;
    909             case ASTORE:
    910                 evalStore(Type.OBJECT, index, frame, subroutine);
    911                 break;
    912             case IINC:
    913                 verifyAssignable(Type.INTEGER, frame.getLocal(index));
    914                 break;
    915             case RET:
    916                 verifyAssignable(Type.RETURN_ADDRESS, frame.getLocal(index));
    917                 break;
    918             default:
    919                 throw new BadBytecode("Invalid WIDE operand [pos = " + pos + "]: " + opcode);
    920         }
    921 
    922     }
    923 
    924     private Type getType(String name) throws BadBytecode {
    925         try {
    926             return Type.get(classPool.get(name));
    927         } catch (NotFoundException e) {
    928             throw new BadBytecode("Could not find class [pos = " + lastPos + "]: " + name);
    929         }
    930     }
    931 
    932     private Type[] paramTypesFromDesc(String desc) throws BadBytecode {
    933         CtClass classes[] = null;
    934         try {
    935             classes = Descriptor.getParameterTypes(desc, classPool);
    936         } catch (NotFoundException e) {
    937             throw new BadBytecode("Could not find class in descriptor [pos = " + lastPos + "]: " + e.getMessage());
    938         }
    939 
    940         if (classes == null)
    941             throw new BadBytecode("Could not obtain parameters for descriptor [pos = " + lastPos + "]: " + desc);
    942 
    943         Type[] types = new Type[classes.length];
    944         for (int i = 0; i < types.length; i++)
    945             types[i] = Type.get(classes[i]);
    946 
    947         return types;
    948     }
    949 
    950     private Type returnTypeFromDesc(String desc) throws BadBytecode {
    951         CtClass clazz = null;
    952         try {
    953             clazz = Descriptor.getReturnType(desc, classPool);
    954         } catch (NotFoundException e) {
    955             throw new BadBytecode("Could not find class in descriptor [pos = " + lastPos + "]: " + e.getMessage());
    956         }
    957 
    958         if (clazz == null)
    959             throw new BadBytecode("Could not obtain return type for descriptor [pos = " + lastPos + "]: " + desc);
    960 
    961         return Type.get(clazz);
    962     }
    963 
    964     private Type simplePeek(Frame frame) {
    965         Type type = frame.peek();
    966         return (type == Type.TOP) ? frame.getStack(frame.getTopIndex() - 1) : type;
    967     }
    968 
    969     private Type simplePop(Frame frame) {
    970         Type type = frame.pop();
    971         return (type == Type.TOP) ? frame.pop() : type;
    972     }
    973 
    974     private void simplePush(Type type, Frame frame) {
    975         frame.push(type);
    976         if (type.getSize() == 2)
    977             frame.push(Type.TOP);
    978     }
    979 
    980     private void access(int index, Type type, Subroutine subroutine) {
    981         if (subroutine == null)
    982             return;
    983         subroutine.access(index);
    984         if (type.getSize() == 2)
    985             subroutine.access(index + 1);
    986     }
    987 
    988     private void simpleSetLocal(int index, Type type, Frame frame) {
    989         frame.setLocal(index, type);
    990         if (type.getSize() == 2)
    991             frame.setLocal(index + 1, Type.TOP);
    992     }
    993 
    994     private Type resolveClassInfo(String info) throws BadBytecode {
    995         CtClass clazz = null;
    996         try {
    997             if (info.charAt(0) == '[') {
    998                 clazz = Descriptor.toCtClass(info, classPool);
    999             } else {
   1000                 clazz = classPool.get(info);
   1001             }
   1002 
   1003         } catch (NotFoundException e) {
   1004             throw new BadBytecode("Could not find class in descriptor [pos = " + lastPos + "]: " + e.getMessage());
   1005         }
   1006 
   1007         if (clazz == null)
   1008             throw new BadBytecode("Could not obtain type for descriptor [pos = " + lastPos + "]: " + info);
   1009 
   1010         return Type.get(clazz);
   1011     }
   1012 
   1013     private Type typeFromDesc(String desc) throws BadBytecode {
   1014         CtClass clazz = null;
   1015         try {
   1016             clazz = Descriptor.toCtClass(desc, classPool);
   1017         } catch (NotFoundException e) {
   1018             throw new BadBytecode("Could not find class in descriptor [pos = " + lastPos + "]: " + e.getMessage());
   1019         }
   1020 
   1021         if (clazz == null)
   1022             throw new BadBytecode("Could not obtain type for descriptor [pos = " + lastPos + "]: " + desc);
   1023 
   1024         return Type.get(clazz);
   1025     }
   1026 
   1027     private void verifyAssignable(Type expected, Type type) throws BadBytecode {
   1028         if (! expected.isAssignableFrom(type))
   1029             throw new BadBytecode("Expected type: " + expected + " Got: " + type + " [pos = " + lastPos + "]");
   1030     }
   1031 }
   1032