Example usage for org.objectweb.asm Frame push

List of usage examples for org.objectweb.asm Frame push

Introduction

In this page you can find the example usage for org.objectweb.asm Frame push.

Prototype

private void push(final int abstractType) 

Source Link

Document

Pushes the given abstract type on the output frame stack.

Usage

From source file:kilim.analysis.BasicBlock.java

License:Open Source License

void interpret() {
    Value v, v1, v2, v3, v4;// w  ww .  jav a  2 s .com
    Frame frame = startFrame.dup();
    if (isCatchHandler()) {
        // When an exception is thrown, the stack is cleared
        // and the thrown exception is pushed into the stack
        frame.clearStack();
        frame.push(Value.make(startPos, caughtExceptionType));
    } else if (hasFlag(IS_SUBROUTINE)) {
        // The target of a JSR instruction has a JVM-internal
        // return address which we model with a type of its
        // own
        frame.push(Value.make(startPos, D_RETURN_ADDRESS));
    }
    String componentType = null;
    @SuppressWarnings("unused")
    boolean canThrowException = false;
    boolean propagateFrame = true;
    int i = 0;
    try {
        for (i = startPos; i <= endPos; i++) {
            AbstractInsnNode ain = getInstruction(i);
            int opcode = ain.getOpcode();
            int val, var;
            switch (opcode) {
            case NOP:
                break;
            case ACONST_NULL:
                frame.push(Value.make(i, D_NULL));
                break;

            case ICONST_M1:
            case ICONST_0:
            case ICONST_1:
            case ICONST_2:
            case ICONST_3:
            case ICONST_4:
            case ICONST_5:
                frame.push(Value.make(i, D_INT, new Integer(opcode - ICONST_0)));
                break;

            case LCONST_0:
            case LCONST_1:
                frame.push(Value.make(i, D_LONG, new Long(opcode - LCONST_0)));
                break;

            case ILOAD:
            case LLOAD:
            case FLOAD:
            case DLOAD:
            case ALOAD:
                var = ((VarInsnNode) ain).var;
                v = frame.getLocal(var, opcode);
                frame.push(v);
                break;

            case FCONST_0:
            case FCONST_1:
            case FCONST_2:
                frame.push(Value.make(i, D_FLOAT, new Float(opcode - FCONST_0)));
                break;

            case DCONST_0:
            case DCONST_1:
                frame.push(Value.make(i, D_DOUBLE, new Double(opcode - DCONST_0)));
                break;

            case BIPUSH:
                val = ((IntInsnNode) ain).operand;
                frame.push(Value.make(i, D_BYTE, new Integer(val)));
                break;

            case SIPUSH:
                val = ((IntInsnNode) ain).operand;
                frame.push(Value.make(i, D_SHORT, new Integer(val)));
                break;

            case LDC:
                Object cval = ((LdcInsnNode) ain).cst;
                frame.push(Value.make(i, TypeDesc.getTypeDesc(cval), cval));
                break;

            case IALOAD:
            case LALOAD:
            case FALOAD:
            case DALOAD:
            case AALOAD:
            case BALOAD:
            case CALOAD:
            case SALOAD:
                canThrowException = true;
                frame.popWord(); // pop index
                v = frame.popWord(); // array ref
                frame.push(Value.make(i, TypeDesc.getComponentType(v.getTypeDesc()))); // push
                // component
                // of
                // array
                break;

            case ISTORE:
            case LSTORE:
            case FSTORE:
            case DSTORE:
            case ASTORE:
                v1 = frame.pop();
                var = ((VarInsnNode) ain).var;
                frame.setLocal(var, v1);
                break;

            case IASTORE:
            case LASTORE:
            case FASTORE:
            case DASTORE:
            case AASTORE:
            case BASTORE:
            case CASTORE:
            case SASTORE:
                canThrowException = true;
                frame.popn(3);
                break;

            case POP:
                frame.popWord();
                break;

            case POP2:
                if (frame.pop().isCategory1()) {
                    frame.popWord();
                }
                break;

            case DUP:
                // ... w => ... w w
                v = frame.popWord();
                frame.push(v);
                frame.push(v);
                break;

            case DUP_X1:
                // Insert top word beneath the next word
                // .. w2 w1 => .. w1 w2 w1
                v1 = frame.popWord();
                v2 = frame.popWord();
                frame.push(v1);
                frame.push(v2);
                frame.push(v1);
                break;

            case DUP_X2:
                // Insert top word beneath the next two words (or dword)
                v1 = frame.popWord();
                v2 = frame.pop();
                if (v2.isCategory1()) {
                    v3 = frame.pop();
                    if (v3.isCategory1()) {
                        // w3,w2,w1 => w1,w3,w2,w1
                        frame.push(v1);
                        frame.push(v3);
                        frame.push(v2);
                        frame.push(v1);
                        break;
                    }
                } else {
                    // dw2,w1 => w1,dw2,w1
                    frame.push(v1);
                    frame.push(v2);
                    frame.push(v1);
                    break;
                }
                throw new InternalError("Illegal use of DUP_X2");

            case DUP2:
                // duplicate top two words (or dword)
                v1 = frame.pop();
                if (v1.isCategory1()) {
                    v2 = frame.pop();
                    if (v2.isCategory1()) {
                        // w2,w1 => w2,w1,w2,w1
                        frame.push(v2);
                        frame.push(v1);
                        frame.push(v2);
                        frame.push(v1);
                        break;
                    }
                } else {
                    // dw1 => dw1,dw1
                    frame.push(v1);
                    frame.push(v1);
                    break;
                }
                throw new InternalError("Illegal use of DUP2");

            case DUP2_X1:
                // insert two words (or dword) beneath next word
                v1 = frame.pop();
                if (v1.isCategory1()) {
                    v2 = frame.pop();
                    if (v2.isCategory1()) {
                        v3 = frame.popWord();
                        // w3,w2,w1 => w2,w1,w3,w2,w1
                        frame.push(v2);
                        frame.push(v1);
                        frame.push(v3);
                        frame.push(v2);
                        frame.push(v1);
                        break;
                    }
                } else { // TypeDesc.isDoubleWord(t1)
                    // w2,dw1 => dw1,w2,dw1
                    v2 = frame.popWord();
                    frame.push(v1);
                    frame.push(v2);
                    frame.push(v1);
                    break;
                }
                throw new InternalError("Illegal use of DUP2_X1");
            case DUP2_X2:
                // insert two words (or dword) beneath next two words (or
                // dword)
                v1 = frame.pop();
                if (v1.isCategory1()) {
                    v2 = frame.pop();
                    if (v2.isCategory1()) {
                        v3 = frame.pop();
                        if (v3.isCategory1()) {
                            v4 = frame.pop();
                            if (v4.isCategory1()) {
                                // w4,w3,w2,w1 => w2,w1,w4,w3,w2,w1
                                frame.push(v2);
                                frame.push(v1);
                                frame.push(v4);
                                frame.push(v3);
                                frame.push(v2);
                                frame.push(v1);
                                break;
                            }
                        } else { // TypeDesc.isDoubleWord(t3)
                            // dw3,w2,w1 => w2,w1,dw3,w2,w1
                            frame.push(v2);
                            frame.push(v1);
                            frame.push(v3);
                            frame.push(v2);
                            frame.push(v1);
                            break;
                        }
                    }
                } else { // TypeDesc.isDoubleWord(t1)
                    v2 = frame.pop();
                    if (v2.isCategory1()) {
                        v3 = frame.pop();
                        if (v3.isCategory1()) {
                            // w3,w2,dw1 => dw1,w3,w2,dw1
                            frame.push(v1);
                            frame.push(v3);
                            frame.push(v2);
                            frame.push(v1);
                            break;
                        }
                    } else {
                        // dw2,dw1 => dw1,dw2,dw1
                        frame.push(v1);
                        frame.push(v2);
                        frame.push(v1);
                        break;
                    }
                }
                throw new InternalError("Illegal use of DUP2_X2");

            case SWAP:
                // w2, w1 => w1, w2
                v1 = frame.popWord();
                v2 = frame.popWord();
                frame.push(v1);
                frame.push(v2);
                break;

            case IDIV:
            case IREM:
            case LDIV:
            case LREM:
                frame.pop(); // See next case
                canThrowException = true;
                break;

            case IADD:
            case LADD:
            case FADD:
            case DADD:
            case ISUB:
            case LSUB:
            case FSUB:
            case DSUB:
            case IMUL:
            case LMUL:
            case FMUL:
            case DMUL:
            case FDIV:
            case DDIV:
            case FREM:
            case DREM:
            case ISHL:
            case LSHL:
            case ISHR:
            case LSHR:
            case IUSHR:
            case LUSHR:
            case IAND:
            case LAND:
            case IOR:
            case LOR:
            case IXOR:
            case LXOR:
                // Binary op.
                frame.pop();
                v = frame.pop();
                // The result is always the same type as the first arg
                frame.push(Value.make(i, v.getTypeDesc()));
                break;

            case LCMP:
            case FCMPL:
            case FCMPG:
            case DCMPL:
            case DCMPG:
                frame.popn(2);
                frame.push(Value.make(i, D_INT));
                break;

            case INEG:
            case LNEG:
            case FNEG:
            case DNEG:
                v = frame.pop();
                frame.push(Value.make(i, v.getTypeDesc()));
                break;

            case IINC:
                var = ((IincInsnNode) ain).var;
                frame.setLocal(var, Value.make(i, D_INT));
                break;

            case I2L:
            case F2L:
            case D2L:
                frame.pop();
                frame.push(Value.make(i, D_LONG));
                break;

            case I2D:
            case L2D:
            case F2D:
                frame.pop();
                frame.push(Value.make(i, D_DOUBLE));
                break;

            case I2F:
            case L2F:
            case D2F:
                frame.pop();
                frame.push(Value.make(i, D_FLOAT));
                break;

            case L2I:
            case F2I:
            case D2I:
                frame.pop();
                frame.push(Value.make(i, D_INT));
                break;

            case I2B:
                frame.popWord();
                frame.push(Value.make(i, D_BOOLEAN));
                break;

            case I2C:
                frame.popWord();
                frame.push(Value.make(i, D_CHAR));
                break;

            case I2S:
                frame.popWord();
                frame.push(Value.make(i, D_SHORT));
                break;

            case IFEQ:
            case IFNE:
            case IFLT:
            case IFGE:
            case IFGT:
            case IFLE:
            case IFNULL:
            case IFNONNULL:
                frame.popWord();
                break;

            case IF_ICMPEQ:
            case IF_ICMPNE:
            case IF_ICMPLT:
            case IF_ICMPGE:
            case IF_ICMPGT:
            case IF_ICMPLE:
            case IF_ACMPEQ:
            case IF_ACMPNE:
                frame.popn(2);
                break;

            case GOTO:
            case JSR: // note: the targetBB pushes the return address
                // itself
                // because it is marked with isSubroutine
            case RET:
                break;

            case TABLESWITCH:
            case LOOKUPSWITCH:
                frame.pop();
                break;

            case IRETURN:
            case LRETURN:
            case FRETURN:
            case DRETURN:
            case ARETURN:
            case RETURN:
                canThrowException = true;
                if (opcode != RETURN) {
                    frame.pop();
                }
                if (frame.stacklen != 0) {
                    throw new InternalError("stack non null at method return");
                }
                break;

            case GETSTATIC:
                canThrowException = true;
                v = Value.make(i, TypeDesc.getInterned(((FieldInsnNode) ain).desc));
                frame.push(v);
                break;

            case PUTSTATIC:
                canThrowException = true;
                frame.pop();
                break;

            case GETFIELD:
                canThrowException = true;
                v1 = frame.pop();
                v = Value.make(i, TypeDesc.getInterned(((FieldInsnNode) ain).desc));
                //if (TypeDesc.isRefType(v.getTypeDesc())) {
                //    System.out.println("GETFIELD " + ((FieldInsnNode)ain).name  + ": " + v + "---->" + v1);
                //}
                frame.push(v);
                break;

            case PUTFIELD:
                canThrowException = true;
                v1 = frame.pop();
                v = frame.pop();
                //if (TypeDesc.isRefType(v.getTypeDesc())) {
                //    System.out.println("PUTFIELD " + ((FieldInsnNode)ain).name  + ": " + v + " ----> " + v1);
                //}
                break;

            case INVOKEVIRTUAL:
            case INVOKESPECIAL:
            case INVOKESTATIC:
            case INVOKEINTERFACE:
            case INVOKEDYNAMIC: // TODO this is new and mysterious
                // pop args, push return value
                MethodInsnNode min = ((MethodInsnNode) ain);
                String desc = min.desc;
                if (flow.isPausableMethodInsn(min) && frame.numMonitorsActive > 0) {
                    throw new KilimException(
                            "Error: Can not call pausable nethods from within a synchronized block\n"
                                    + "Caller: " + this.flow.name + "\nCallee: " + ((MethodInsnNode) ain).name);
                }
                canThrowException = true;
                frame.popn(TypeDesc.getNumArgumentTypes(desc));
                if (opcode != INVOKESTATIC) {
                    v = frame.pop(); // "this" ref
                    //assert checkReceiverType(v, min) : "Method " + flow.name + " calls " + min.name + " on a receiver with incompatible type " + v.getTypeDesc() ;
                }
                desc = TypeDesc.getReturnTypeDesc(desc);
                if (desc != D_VOID) {
                    frame.push(Value.make(i, desc));
                }
                break;

            case NEW:
                canThrowException = true;
                v = Value.make(i, TypeDesc.getInterned(((TypeInsnNode) ain).desc));
                frame.push(v);
                break;

            case NEWARRAY:
                canThrowException = true;
                frame.popWord();
                int atype = ((IntInsnNode) ain).operand;
                String t;
                switch (atype) {
                case T_BOOLEAN:
                    t = D_ARRAY_BOOLEAN;
                    break;
                case T_CHAR:
                    t = D_ARRAY_CHAR;
                    break;
                case T_FLOAT:
                    t = D_ARRAY_FLOAT;
                    break;
                case T_DOUBLE:
                    t = D_ARRAY_DOUBLE;
                    break;
                case T_BYTE:
                    t = D_ARRAY_BYTE;
                    break;
                case T_SHORT:
                    t = D_ARRAY_SHORT;
                    break;
                case T_INT:
                    t = D_ARRAY_INT;
                    break;
                case T_LONG:
                    t = D_ARRAY_LONG;
                    break;
                default:
                    throw new InternalError("Illegal argument to NEWARRAY: " + atype);
                }
                frame.push(Value.make(i, t));
                break;
            case ANEWARRAY:
                canThrowException = true;
                frame.popWord();
                componentType = TypeDesc.getInterned(((TypeInsnNode) ain).desc);
                v = Value.make(i, TypeDesc.getInterned("[" + componentType));
                frame.push(v);
                break;

            case ARRAYLENGTH:
                canThrowException = true;
                frame.popWord();
                frame.push(Value.make(i, D_INT));
                break;

            case ATHROW:
                canThrowException = true;
                frame.pop();
                propagateFrame = false;
                break;

            case CHECKCAST:
                canThrowException = true;
                frame.pop();
                v = Value.make(i, TypeDesc.getInterned(((TypeInsnNode) ain).desc));
                frame.push(v);
                break;

            case INSTANCEOF:
                canThrowException = true;
                frame.pop();
                frame.push(Value.make(i, D_INT));
                break;

            case MONITORENTER:
            case MONITOREXIT:
                if (opcode == MONITORENTER) {
                    frame.numMonitorsActive++;
                } else {
                    frame.numMonitorsActive--;
                }
                canThrowException = true;
                frame.pop();
                canThrowException = true;
                break;

            case MULTIANEWARRAY:
                MultiANewArrayInsnNode minode = (MultiANewArrayInsnNode) ain;
                int dims = minode.dims;
                frame.popn(dims);
                componentType = TypeDesc.getInterned(minode.desc);
                StringBuffer sb = new StringBuffer(componentType.length() + dims);
                for (int j = 0; j < dims; j++)
                    sb.append('[');
                sb.append(componentType);
                v = Value.make(i, TypeDesc.getInterned(sb.toString()));
                frame.push(v);
                break;
            case -1: // TODO this is new and mysterious
                break;
            default:
                assert false : "Unexpected opcode: " + ain.getOpcode();
            }
        }
        i = -1; // reset for assertion catch block below
        if (propagateFrame) {
            mergeSuccessors(frame);
        }
        if (handlers != null) {
            for (Handler handler : handlers) {
                handler.catchBB.merge(frame, /* localsOnly= */true); // merge
                // only
                // locals
            }
            canThrowException = false;
        }
    } catch (AssertionError ae) {
        System.err.println("**** Assertion Error analyzing " + flow.classFlow.name + "." + flow.name);
        System.err.println("Basic block " + this);
        System.err.println("i = " + i);
        System.err.println("Frame: " + frame);
        throw ae;
    }

}