private int execute()

in rhino/src/main/java/org/mozilla/classfile/ClassFileWriter.java [1837:2277]


        private int execute(int bci) {
            int bc = itsCodeBuffer[bci] & 0xFF;
            int type, type2, index;
            int length = 0;
            long lType, lType2;
            String className;

            switch (bc) {
                case ByteCode.NOP:
                case ByteCode.IINC:
                case ByteCode.GOTO:
                case ByteCode.GOTO_W:
                    // No change
                    break;
                case ByteCode.CHECKCAST:
                    pop();
                    push(TypeInfo.OBJECT(getOperand(bci + 1, 2)));
                    break;
                case ByteCode.IASTORE: // pop; pop; pop
                case ByteCode.LASTORE:
                case ByteCode.FASTORE:
                case ByteCode.DASTORE:
                case ByteCode.AASTORE:
                case ByteCode.BASTORE:
                case ByteCode.CASTORE:
                case ByteCode.SASTORE:
                    pop();
                // fall through
                case ByteCode.PUTFIELD: // pop; pop
                case ByteCode.IF_ICMPEQ:
                case ByteCode.IF_ICMPNE:
                case ByteCode.IF_ICMPLT:
                case ByteCode.IF_ICMPGE:
                case ByteCode.IF_ICMPGT:
                case ByteCode.IF_ICMPLE:
                case ByteCode.IF_ACMPEQ:
                case ByteCode.IF_ACMPNE:
                    pop();
                // fall through
                case ByteCode.IFEQ: // pop
                case ByteCode.IFNE:
                case ByteCode.IFLT:
                case ByteCode.IFGE:
                case ByteCode.IFGT:
                case ByteCode.IFLE:
                case ByteCode.IFNULL:
                case ByteCode.IFNONNULL:
                case ByteCode.POP:
                case ByteCode.MONITORENTER:
                case ByteCode.MONITOREXIT:
                case ByteCode.PUTSTATIC:
                    pop();
                    break;
                case ByteCode.POP2:
                    pop2();
                    break;
                case ByteCode.ACONST_NULL:
                    push(TypeInfo.NULL);
                    break;
                case ByteCode.IALOAD: // pop; pop; push(INTEGER)
                case ByteCode.BALOAD:
                case ByteCode.CALOAD:
                case ByteCode.SALOAD:
                case ByteCode.IADD:
                case ByteCode.ISUB:
                case ByteCode.IMUL:
                case ByteCode.IDIV:
                case ByteCode.IREM:
                case ByteCode.ISHL:
                case ByteCode.ISHR:
                case ByteCode.IUSHR:
                case ByteCode.IAND:
                case ByteCode.IOR:
                case ByteCode.IXOR:
                case ByteCode.LCMP:
                case ByteCode.FCMPL:
                case ByteCode.FCMPG:
                case ByteCode.DCMPL:
                case ByteCode.DCMPG:
                    pop();
                // fall through
                case ByteCode.INEG: // pop; push(INTEGER)
                case ByteCode.L2I:
                case ByteCode.F2I:
                case ByteCode.D2I:
                case ByteCode.I2B:
                case ByteCode.I2C:
                case ByteCode.I2S:
                case ByteCode.ARRAYLENGTH:
                case ByteCode.INSTANCEOF:
                    pop();
                // fall through
                case ByteCode.ICONST_M1: // push(INTEGER)
                case ByteCode.ICONST_0:
                case ByteCode.ICONST_1:
                case ByteCode.ICONST_2:
                case ByteCode.ICONST_3:
                case ByteCode.ICONST_4:
                case ByteCode.ICONST_5:
                case ByteCode.ILOAD:
                case ByteCode.ILOAD_0:
                case ByteCode.ILOAD_1:
                case ByteCode.ILOAD_2:
                case ByteCode.ILOAD_3:
                case ByteCode.BIPUSH:
                case ByteCode.SIPUSH:
                    push(TypeInfo.INTEGER);
                    break;
                case ByteCode.LALOAD: // pop; pop; push(LONG)
                case ByteCode.LADD:
                case ByteCode.LSUB:
                case ByteCode.LMUL:
                case ByteCode.LDIV:
                case ByteCode.LREM:
                case ByteCode.LSHL:
                case ByteCode.LSHR:
                case ByteCode.LUSHR:
                case ByteCode.LAND:
                case ByteCode.LOR:
                case ByteCode.LXOR:
                    pop();
                // fall through
                case ByteCode.LNEG: // pop; push(LONG)
                case ByteCode.I2L:
                case ByteCode.F2L:
                case ByteCode.D2L:
                    pop();
                // fall through
                case ByteCode.LCONST_0: // push(LONG)
                case ByteCode.LCONST_1:
                case ByteCode.LLOAD:
                case ByteCode.LLOAD_0:
                case ByteCode.LLOAD_1:
                case ByteCode.LLOAD_2:
                case ByteCode.LLOAD_3:
                    push(TypeInfo.LONG);
                    break;
                case ByteCode.FALOAD: // pop; pop; push(FLOAT)
                case ByteCode.FADD:
                case ByteCode.FSUB:
                case ByteCode.FMUL:
                case ByteCode.FDIV:
                case ByteCode.FREM:
                    pop();
                // fall through
                case ByteCode.FNEG: // pop; push(FLOAT)
                case ByteCode.I2F:
                case ByteCode.L2F:
                case ByteCode.D2F:
                    pop();
                // fall through
                case ByteCode.FCONST_0: // push(FLOAT)
                case ByteCode.FCONST_1:
                case ByteCode.FCONST_2:
                case ByteCode.FLOAD:
                case ByteCode.FLOAD_0:
                case ByteCode.FLOAD_1:
                case ByteCode.FLOAD_2:
                case ByteCode.FLOAD_3:
                    push(TypeInfo.FLOAT);
                    break;
                case ByteCode.DALOAD: // pop; pop; push(DOUBLE)
                case ByteCode.DADD:
                case ByteCode.DSUB:
                case ByteCode.DMUL:
                case ByteCode.DDIV:
                case ByteCode.DREM:
                    pop();
                // fall through
                case ByteCode.DNEG: // pop; push(DOUBLE)
                case ByteCode.I2D:
                case ByteCode.L2D:
                case ByteCode.F2D:
                    pop();
                // fall through
                case ByteCode.DCONST_0: // push(DOUBLE)
                case ByteCode.DCONST_1:
                case ByteCode.DLOAD:
                case ByteCode.DLOAD_0:
                case ByteCode.DLOAD_1:
                case ByteCode.DLOAD_2:
                case ByteCode.DLOAD_3:
                    push(TypeInfo.DOUBLE);
                    break;
                case ByteCode.ISTORE:
                    executeStore(getOperand(bci + 1, wide ? 2 : 1), TypeInfo.INTEGER);
                    break;
                case ByteCode.ISTORE_0:
                case ByteCode.ISTORE_1:
                case ByteCode.ISTORE_2:
                case ByteCode.ISTORE_3:
                    executeStore(bc - ByteCode.ISTORE_0, TypeInfo.INTEGER);
                    break;
                case ByteCode.LSTORE:
                    executeStore(getOperand(bci + 1, wide ? 2 : 1), TypeInfo.LONG);
                    break;
                case ByteCode.LSTORE_0:
                case ByteCode.LSTORE_1:
                case ByteCode.LSTORE_2:
                case ByteCode.LSTORE_3:
                    executeStore(bc - ByteCode.LSTORE_0, TypeInfo.LONG);
                    break;
                case ByteCode.FSTORE:
                    executeStore(getOperand(bci + 1, wide ? 2 : 1), TypeInfo.FLOAT);
                    break;
                case ByteCode.FSTORE_0:
                case ByteCode.FSTORE_1:
                case ByteCode.FSTORE_2:
                case ByteCode.FSTORE_3:
                    executeStore(bc - ByteCode.FSTORE_0, TypeInfo.FLOAT);
                    break;
                case ByteCode.DSTORE:
                    executeStore(getOperand(bci + 1, wide ? 2 : 1), TypeInfo.DOUBLE);
                    break;
                case ByteCode.DSTORE_0:
                case ByteCode.DSTORE_1:
                case ByteCode.DSTORE_2:
                case ByteCode.DSTORE_3:
                    executeStore(bc - ByteCode.DSTORE_0, TypeInfo.DOUBLE);
                    break;
                case ByteCode.ALOAD:
                    executeALoad(getOperand(bci + 1, wide ? 2 : 1));
                    break;
                case ByteCode.ALOAD_0:
                case ByteCode.ALOAD_1:
                case ByteCode.ALOAD_2:
                case ByteCode.ALOAD_3:
                    executeALoad(bc - ByteCode.ALOAD_0);
                    break;
                case ByteCode.ASTORE:
                    executeAStore(getOperand(bci + 1, wide ? 2 : 1));
                    break;
                case ByteCode.ASTORE_0:
                case ByteCode.ASTORE_1:
                case ByteCode.ASTORE_2:
                case ByteCode.ASTORE_3:
                    executeAStore(bc - ByteCode.ASTORE_0);
                    break;
                case ByteCode.IRETURN:
                case ByteCode.LRETURN:
                case ByteCode.FRETURN:
                case ByteCode.DRETURN:
                case ByteCode.ARETURN:
                case ByteCode.RETURN:
                    clearStack();
                    break;
                case ByteCode.ATHROW:
                    type = pop();
                    clearStack();
                    push(type);
                    break;
                case ByteCode.SWAP:
                    type = pop();
                    type2 = pop();
                    push(type);
                    push(type2);
                    break;
                case ByteCode.LDC:
                case ByteCode.LDC_W:
                case ByteCode.LDC2_W:
                    if (bc == ByteCode.LDC) {
                        index = getOperand(bci + 1);
                    } else {
                        index = getOperand(bci + 1, 2);
                    }
                    byte constType = itsConstantPool.getConstantType(index);
                    switch (constType) {
                        case ConstantPool.CONSTANT_Double:
                            push(TypeInfo.DOUBLE);
                            break;
                        case ConstantPool.CONSTANT_Float:
                            push(TypeInfo.FLOAT);
                            break;
                        case ConstantPool.CONSTANT_Long:
                            push(TypeInfo.LONG);
                            break;
                        case ConstantPool.CONSTANT_Integer:
                            push(TypeInfo.INTEGER);
                            break;
                        case ConstantPool.CONSTANT_String:
                            push(TypeInfo.OBJECT("java/lang/String", itsConstantPool));
                            break;
                        default:
                            throw new IllegalArgumentException("bad const type " + constType);
                    }
                    break;
                case ByteCode.NEW:
                    push(TypeInfo.UNINITIALIZED_VARIABLE(bci));
                    break;
                case ByteCode.NEWARRAY:
                    pop();
                    char componentType = arrayTypeToName(itsCodeBuffer[bci + 1]);
                    index = itsConstantPool.addClass("[" + componentType);
                    push(TypeInfo.OBJECT((short) index));
                    break;
                case ByteCode.ANEWARRAY:
                    index = getOperand(bci + 1, 2);
                    className = (String) itsConstantPool.getConstantData(index);
                    pop();
                    push(TypeInfo.OBJECT("[L" + className + ';', itsConstantPool));
                    break;
                case ByteCode.INVOKEVIRTUAL:
                case ByteCode.INVOKESPECIAL:
                case ByteCode.INVOKESTATIC:
                case ByteCode.INVOKEINTERFACE:
                    index = getOperand(bci + 1, 2);
                    FieldOrMethodRef m = (FieldOrMethodRef) itsConstantPool.getConstantData(index);
                    String methodType = m.getType();
                    String methodName = m.getName();
                    int parameterCount = sizeOfParameters(methodType) >>> 16;
                    for (int i = 0; i < parameterCount; i++) {
                        pop();
                    }
                    if (bc != ByteCode.INVOKESTATIC) {
                        int instType = pop();
                        int tag = TypeInfo.getTag(instType);
                        if (tag == TypeInfo.UNINITIALIZED_VARIABLE(0)
                                || tag == TypeInfo.UNINITIALIZED_THIS) {
                            if ("<init>".equals(methodName)) {
                                int newType;
                                if (tag == TypeInfo.UNINITIALIZED_VARIABLE(0)) {
                                    newType = TypeInfo.OBJECT(m.getClassName(), itsConstantPool);
                                } else {
                                    newType = TypeInfo.OBJECT(itsThisClassIndex);
                                }
                                initializeTypeInfo(instType, newType);
                            } else {
                                throw new IllegalStateException("bad instance");
                            }
                        }
                    }
                    int rParen = methodType.indexOf(')');
                    String returnType = methodType.substring(rParen + 1);
                    returnType = descriptorToInternalName(returnType);
                    if (!returnType.equals("V")) {
                        push(TypeInfo.fromType(returnType, itsConstantPool));
                    }
                    break;
                case ByteCode.INVOKEDYNAMIC:
                    index = getOperand(bci + 1, 2);
                    methodType = (String) itsConstantPool.getConstantData(index);
                    parameterCount = sizeOfParameters(methodType) >>> 16;
                    for (int i = 0; i < parameterCount; i++) {
                        pop();
                    }
                    rParen = methodType.indexOf(')');
                    returnType = methodType.substring(rParen + 1);
                    returnType = descriptorToInternalName(returnType);
                    if (!returnType.equals("V")) {
                        push(TypeInfo.fromType(returnType, itsConstantPool));
                    }
                    break;
                case ByteCode.GETFIELD:
                    pop();
                // fall through
                case ByteCode.GETSTATIC:
                    index = getOperand(bci + 1, 2);
                    FieldOrMethodRef f = (FieldOrMethodRef) itsConstantPool.getConstantData(index);
                    String fieldType = descriptorToInternalName(f.getType());
                    push(TypeInfo.fromType(fieldType, itsConstantPool));
                    break;
                case ByteCode.DUP:
                    type = pop();
                    push(type);
                    push(type);
                    break;
                case ByteCode.DUP_X1:
                    type = pop();
                    type2 = pop();
                    push(type);
                    push(type2);
                    push(type);
                    break;
                case ByteCode.DUP_X2:
                    type = pop();
                    lType = pop2();
                    push(type);
                    push2(lType);
                    push(type);
                    break;
                case ByteCode.DUP2:
                    lType = pop2();
                    push2(lType);
                    push2(lType);
                    break;
                case ByteCode.DUP2_X1:
                    lType = pop2();
                    type = pop();
                    push2(lType);
                    push(type);
                    push2(lType);
                    break;
                case ByteCode.DUP2_X2:
                    lType = pop2();
                    lType2 = pop2();
                    push2(lType);
                    push2(lType2);
                    push2(lType);
                    break;
                case ByteCode.TABLESWITCH:
                    int switchStart = bci + 1 + (3 & ~bci);
                    int low = getOperand(switchStart + 4, 4);
                    int high = getOperand(switchStart + 8, 4);
                    length = 4 * (high - low + 4) + switchStart - bci;
                    pop();
                    break;
                case ByteCode.AALOAD:
                    pop();
                    int typeIndex = pop() >>> 8;
                    className = (String) itsConstantPool.getConstantData(typeIndex);
                    String arrayType = className;
                    if (arrayType.charAt(0) != '[') {
                        throw new IllegalStateException("bad array type");
                    }
                    String elementDesc = arrayType.substring(1);
                    String elementType = descriptorToInternalName(elementDesc);
                    typeIndex = itsConstantPool.addClass(elementType);
                    push(TypeInfo.OBJECT(typeIndex));
                    break;
                case ByteCode.WIDE:
                    // Alters behaviour of next instruction
                    wide = true;
                    break;
                case ByteCode.MULTIANEWARRAY:
                case ByteCode.LOOKUPSWITCH:
                // Currently not used in any part of Rhino, so ignore it
                case ByteCode.JSR: // TODO: JSR is deprecated
                case ByteCode.RET:
                case ByteCode.JSR_W:
                default:
                    throw new IllegalArgumentException("bad opcode: " + bc);
            }

            if (length == 0) {
                length = opcodeLength(bc, wide);
            }
            if (wide && bc != ByteCode.WIDE) {
                wide = false;
            }
            return length;
        }