Example usage for org.apache.commons.bcel6.verifier.structurals InstructionContext getSuccessors

List of usage examples for org.apache.commons.bcel6.verifier.structurals InstructionContext getSuccessors

Introduction

In this page you can find the example usage for org.apache.commons.bcel6.verifier.structurals InstructionContext getSuccessors.

Prototype

InstructionContext[] getSuccessors();

Source Link

Document

Returns the usual control flow successors.

Usage

From source file:daikon.dcomp.StackVer.java

/**
 * Whenever the outgoing frame//w w  w.j  a v a 2s .  c  o  m
 * situation of an InstructionContext changes, all its successors are
 * put [back] into the queue [as if they were unvisited].
 * The proof of termination is about the existence of a
 * fix point of frame merging.
 */
private void circulationPump(ControlFlowGraph cfg, InstructionContext start, Frame vanillaFrame,
        InstConstraintVisitor icv, ExecutionVisitor ev) {
    final Random random = new Random();
    InstructionContextQueue icq = new InstructionContextQueue();

    stack_types.set(start.getInstruction().getPosition(), vanillaFrame);
    // new ArrayList() <=>   no Instruction was executed before
    start.execute(vanillaFrame, new ArrayList<InstructionContext>(), icv, ev);
    //   => Top-Level routine (no jsr call before)
    icq.add(start, new ArrayList<InstructionContext>());

    // LOOP!
    while (!icq.isEmpty()) {
        InstructionContext u;
        ArrayList<InstructionContext> ec;
        if (!DEBUG) {
            int r = random.nextInt(icq.size());
            u = icq.getIC(r);
            ec = icq.getEC(r);
            icq.remove(r);
        } else {
            u = icq.getIC(0);
            ec = icq.getEC(0);
            icq.remove(0);
        }

        // this makes Java grumpy
        // ArrayList<InstructionContext> oldchain = (ArrayList<InstructionContext>) (ec.clone());
        ArrayList<InstructionContext> oldchain = new ArrayList<InstructionContext>(ec);
        // this makes Java grumpy
        // ArrayList<InstructionContext> newchain = (ArrayList) (ec.clone());
        ArrayList<InstructionContext> newchain = new ArrayList<InstructionContext>(ec);
        newchain.add(u);

        if ((u.getInstruction().getInstruction()) instanceof RET) {
            // We can only follow _one_ successor, the one after the
            // JSR that was recently executed.
            RET ret = (RET) (u.getInstruction().getInstruction());
            ReturnaddressType t = (ReturnaddressType) u.getOutFrame(oldchain).getLocals().get(ret.getIndex());
            InstructionContext theSuccessor = cfg.contextOf(t.getTarget());

            // Sanity check
            InstructionContext lastJSR = null;
            int skip_jsr = 0;
            for (int ss = oldchain.size() - 1; ss >= 0; ss--) {
                if (skip_jsr < 0) {
                    throw new AssertionViolatedException("More RET than JSR in execution chain?!");
                }
                //System.err.println("+"+oldchain.get(ss));
                if ((oldchain.get(ss)).getInstruction().getInstruction() instanceof JsrInstruction) {
                    if (skip_jsr == 0) {
                        lastJSR = oldchain.get(ss);
                        break;
                    }
                    skip_jsr--;
                }
                if ((oldchain.get(ss)).getInstruction().getInstruction() instanceof RET) {
                    skip_jsr++;
                }
            }
            if (lastJSR == null) {
                throw new AssertionViolatedException(
                        "RET without a JSR before in ExecutionChain?! EC: '" + oldchain + "'.");
            }
            JsrInstruction jsr = (JsrInstruction) (lastJSR.getInstruction().getInstruction());
            if (theSuccessor != (cfg.contextOf(jsr.physicalSuccessor()))) {
                throw new AssertionViolatedException(
                        "RET '" + u.getInstruction() + "' info inconsistent: jump back to '" + theSuccessor
                                + "' or '" + cfg.contextOf(jsr.physicalSuccessor()) + "'?");
            }

            Frame f = u.getOutFrame(oldchain);
            stack_types.set(theSuccessor.getInstruction().getPosition(), f);
            if (theSuccessor.execute(f, newchain, icv, ev)) {
                // This makes 5.0 grumpy: icq.add(theSuccessor, (ArrayList) newchain.clone());
                icq.add(theSuccessor, new ArrayList<InstructionContext>(newchain));
            }
        } else { // "not a ret"

            // Normal successors. Add them to the queue of successors.
            InstructionContext[] succs = u.getSuccessors();
            for (int s = 0; s < succs.length; s++) {
                InstructionContext v = succs[s];
                Frame f = u.getOutFrame(oldchain);
                stack_types.set(v.getInstruction().getPosition(), f);
                if (v.execute(f, newchain, icv, ev)) {
                    // This makes 5.0 grumpy: icq.add(v, (ArrayList) newchain.clone());
                    icq.add(v, new ArrayList<InstructionContext>(newchain));
                }
            }
        } // end "not a ret"

        // Exception Handlers. Add them to the queue of successors.
        // [subroutines are never protected; mandated by JustIce]
        ExceptionHandler[] exc_hds = u.getExceptionHandlers();
        for (int s = 0; s < exc_hds.length; s++) {
            InstructionContext v = cfg.contextOf(exc_hds[s].getHandlerStart());
            // TODO: the "oldchain" and "newchain" is used to determine the subroutine
            // we're in (by searching for the last JSR) by the InstructionContext
            // implementation. Therefore, we should not use this chain mechanism
            // when dealing with exception handlers.
            // Example: a JSR with an exception handler as its successor does not
            // mean we're in a subroutine if we go to the exception handler.
            // We should address this problem later; by now we simply "cut" the chain
            // by using an empty chain for the exception handlers.
            //if (v.execute(new Frame(u.getOutFrame(oldchain).getLocals(), new OperandStack (u.getOutFrame().getStack().maxStack(), (exc_hds[s].getExceptionType()==null? Type.THROWABLE : exc_hds[s].getExceptionType())) ), newchain), icv, ev){
            //icq.add(v, (ArrayList) newchain.clone());
            Frame f = new Frame(u.getOutFrame(oldchain).getLocals(), new OperandStack(
                    u.getOutFrame(oldchain).getStack().maxStack(),
                    (exc_hds[s].getExceptionType() == null ? Type.THROWABLE : exc_hds[s].getExceptionType())));
            stack_types.set(v.getInstruction().getPosition(), f);
            if (v.execute(f, new ArrayList<InstructionContext>(), icv, ev)) {
                icq.add(v, new ArrayList<InstructionContext>());
            }
        }
    } // while (!icq.isEmpty()) END

    InstructionHandle ih = start.getInstruction();
    do {
        if ((ih.getInstruction() instanceof ReturnInstruction) && (!(cfg.isDead(ih)))) {
            InstructionContext ic = cfg.contextOf(ih);
            Frame f = ic.getOutFrame(new ArrayList<InstructionContext>());
            // TODO: This is buggy, we check only the top-level return instructions
            // this way. Maybe some maniac returns from a method when in a subroutine?
            LocalVariables lvs = f.getLocals();
            for (int i = 0; i < lvs.maxLocals(); i++) {
                if (lvs.get(i) instanceof UninitializedObjectType) {
                    this.addMessage("Warning: ReturnInstruction '" + ic
                            + "' may leave method with an uninitialized object in the local variables array '"
                            + lvs + "'.");
                }
            }
            OperandStack os = f.getStack();
            for (int i = 0; i < os.size(); i++) {
                if (os.peek(i) instanceof UninitializedObjectType) {
                    this.addMessage("Warning: ReturnInstruction '" + ic
                            + "' may leave method with an uninitialized object on the operand stack '" + os
                            + "'.");
                }
            }
        }
    } while ((ih = ih.getNext()) != null);
}