Java 类org.apache.bcel.generic.RET 实例源码

项目:VestaClient    文件:Subroutines.java   
/**
 * Sets the leaving RET instruction. Must be invoked after all instructions are added.
 * Must not be invoked for top-level 'subroutine'.
 */
void setLeavingRET(){
    if (localVariable == UNSET){
        throw new AssertionViolatedException("setLeavingRET() called for top-level 'subroutine' or forgot to set local variable first.");
    }
    Iterator iter = instructions.iterator();
    InstructionHandle ret = null;
    while(iter.hasNext()){
        InstructionHandle actual = (InstructionHandle) iter.next();
        if (actual.getInstruction() instanceof RET){
            if (ret != null){
                throw new StructuralCodeConstraintException("Subroutine with more then one RET detected: '"+ret+"' and '"+actual+"'.");
            }
            else{
                ret = actual;
            }
        }
    }
    if (ret == null){
        throw new StructuralCodeConstraintException("Subroutine without a RET detected.");
    }
    if (((RET) ret.getInstruction()).getIndex() != localVariable){
        throw new StructuralCodeConstraintException("Subroutine uses '"+ret+"' which does not match the correct local variable '"+localVariable+"'.");
    }
    theRET = ret;
}
项目:VestaClient    文件:Subroutines.java   
/**
 * This (recursive) utility method makes sure that
 * no subroutine is calling a subroutine
 * that uses the same local variable for the RET as themselves
 * (recursively).
 * This includes that subroutines may not call themselves
 * recursively, even not through intermediate calls to other
 * subroutines.
 *
 * @throws StructuralCodeConstraintException if the above constraint is not satisfied.
 */
private void noRecursiveCalls(Subroutine sub, Set set){
    Subroutine[] subs = sub.subSubs();

    for (int i=0; i<subs.length; i++){
        int index = ((RET) (subs[i].getLeavingRET().getInstruction())).getIndex();

        if (!set.add(new Integer(index))){
            // Don't use toString() here because of possibly infinite recursive subSubs() calls then.
            SubroutineImpl si = (SubroutineImpl) subs[i];
            throw new StructuralCodeConstraintException("Subroutine with local variable '"+si.localVariable+"', JSRs '"+si.theJSRs+"', RET '"+si.theRET+"' is called by a subroutine which uses the same local variable index as itself; maybe even a recursive call? JustIce's clean definition of a subroutine forbids both.");
        }

        noRecursiveCalls(subs[i], set);

        set.remove(new Integer(index));
    }
}
项目:VestaClient    文件:ControlFlowGraph.java   
/**
 * Returns the InstructionContextImpl with an JSR/JSR_W
 * that was last in the ExecutionChain, without
 * a corresponding RET, i.e.
 * we were called by this one.
 * Returns null if we were called from the top level.
 */
private InstructionContextImpl lastExecutionJSR(){

    int size = executionPredecessors.size();
    int retcount = 0;

    for (int i=size-1; i>=0; i--){
        InstructionContextImpl current = (InstructionContextImpl) (executionPredecessors.get(i));
        Instruction currentlast = current.getInstruction().getInstruction();
        if (currentlast instanceof RET) {
                  retcount++;
              }
        if (currentlast instanceof JsrInstruction){
            retcount--;
            if (retcount == -1) {
                      return current;
                  }
        }
    }
    return null;
}
项目:eclectic    文件:Subroutines.java   
/**
 * Sets the leaving RET instruction. Must be invoked after all instructions are added.
 * Must not be invoked for top-level 'subroutine'.
 */
void setLeavingRET() {
    if (localVariable == UNSET){
        throw new AssertionViolatedException("setLeavingRET() called for top-level 'subroutine' or forgot to set local variable first.");
    }
    InstructionHandle ret = null;
    for (final InstructionHandle actual : instructions) {
        if (actual.getInstruction() instanceof RET){
            if (ret != null){
                throw new StructuralCodeConstraintException("Subroutine with more then one RET detected: '"+ret+"' and '"+actual+"'.");
            }
            else{
                ret = actual;
            }
        }
    }
    if (ret == null){
        throw new StructuralCodeConstraintException("Subroutine without a RET detected.");
    }
    if (((RET) ret.getInstruction()).getIndex() != localVariable){
        throw new StructuralCodeConstraintException("Subroutine uses '"+ret+"' which does not match the correct local variable '"+localVariable+"'.");
    }
    theRET = ret;
}
项目:eclectic    文件:ExecutionPath.java   
/**
 * Returns the InstructionContextImpl with an JSR/JSR_W
 * that was last in the ExecutionChain, without
 * a corresponding RET, i.e.
 * we were called by this one.
 * Returns null if we were called from the top level.
 */
public InstructionContext lastExecutionJSR(){
    int retcount = 0;

    for( ExecutionPath ptr = this; ptr!=EMPTY; ptr=ptr.prev) {
        Instruction i = ptr.last.getInstruction().getInstruction();
        if (i instanceof RET) retcount++;
        if (i instanceof JsrInstruction){
            retcount--;
            if (retcount == -1)
                return ptr.last;
        }
    }

    return null;
}
项目:eclectic    文件:Subroutines.java   
/**
 * Sets the leaving RET instruction. Must be invoked after all instructions are added.
 * Must not be invoked for top-level 'subroutine'.
 */
void setLeavingRET() {
    if (localVariable == UNSET){
        throw new AssertionViolatedException("setLeavingRET() called for top-level 'subroutine' or forgot to set local variable first.");
    }
    InstructionHandle ret = null;
    for (final InstructionHandle actual : instructions) {
        if (actual.getInstruction() instanceof RET){
            if (ret != null){
                throw new StructuralCodeConstraintException("Subroutine with more then one RET detected: '"+ret+"' and '"+actual+"'.");
            }
            else{
                ret = actual;
            }
        }
    }
    if (ret == null){
        throw new StructuralCodeConstraintException("Subroutine without a RET detected.");
    }
    if (((RET) ret.getInstruction()).getIndex() != localVariable){
        throw new StructuralCodeConstraintException("Subroutine uses '"+ret+"' which does not match the correct local variable '"+localVariable+"'.");
    }
    theRET = ret;
}
项目:eclectic    文件:ExecutionPath.java   
/**
 * Returns the InstructionContextImpl with an JSR/JSR_W
 * that was last in the ExecutionChain, without
 * a corresponding RET, i.e.
 * we were called by this one.
 * Returns null if we were called from the top level.
 */
public InstructionContext lastExecutionJSR(){
    int retcount = 0;

    for( ExecutionPath ptr = this; ptr!=EMPTY; ptr=ptr.prev) {
        Instruction i = ptr.last.getInstruction().getInstruction();
        if (i instanceof RET) retcount++;
        if (i instanceof JsrInstruction){
            retcount--;
            if (retcount == -1)
                return ptr.last;
        }
    }

    return null;
}
项目:VestaClient    文件:Pass3aVerifier.java   
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
public void visitRET(RET o){
    int idx = o.getIndex();
    if (idx < 0){
        constraintViolated(o, "Index '"+idx+"' must be non-negative.");
    }
    else{
        int maxminus1 =  max_locals()-1;
        if (idx > maxminus1){
            constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-1 '"+maxminus1+"'.");
        }
    }
}
项目:VestaClient    文件:Subroutines.java   
public int[] getAccessedLocalsIndices(){
    //TODO: Implement caching.
    Set acc = new HashSet();
    if (theRET == null && this != TOPLEVEL){
        throw new AssertionViolatedException("This subroutine object must be built up completely before calculating accessed locals.");
    }
    Iterator i = instructions.iterator();
    while (i.hasNext()){
        InstructionHandle ih = (InstructionHandle) i.next();
        // RET is not a LocalVariableInstruction in the current version of BCEL.
        if (ih.getInstruction() instanceof LocalVariableInstruction || ih.getInstruction() instanceof RET){
            int idx = ((IndexedInstruction) (ih.getInstruction())).getIndex();
            acc.add(new Integer(idx));
            // LONG? DOUBLE?.
            try{
                // LocalVariableInstruction instances are typed without the need to look into
                // the constant pool.
                if (ih.getInstruction() instanceof LocalVariableInstruction){
                    int s = ((LocalVariableInstruction) ih.getInstruction()).getType(null).getSize();
                    if (s==2) {
                              acc.add(new Integer(idx+1));
                          }
                }
            }
            catch(RuntimeException re){
                throw new AssertionViolatedException("Oops. BCEL did not like NULL as a ConstantPoolGen object.");
            }
        }
    }

    int[] ret = new int[acc.size()];
    i = acc.iterator();
    int j=-1;
    while (i.hasNext()){
        j++;
        ret[j] = ((Integer) i.next()).intValue();
    }
    return ret;
}
项目:eclectic    文件:Subroutines.java   
public int[] getAccessedLocalsIndices(){
    //TODO: Implement caching.
    final Set<Integer> acc = new HashSet<Integer>();
    if (theRET == null && this != TOPLEVEL){
        throw new AssertionViolatedException("This subroutine object must be built up completely before calculating accessed locals.");
    }
    for (final InstructionHandle ih : instructions) {
        // RET is not a LocalVariableInstruction in the current version of BCEL.
        if (ih.getInstruction() instanceof LocalVariableInstruction || ih.getInstruction() instanceof RET){
            int idx = IndexedInstruction.class.cast(ih.getInstruction()).getIndex();
            acc.add(idx);
            // LONG? DOUBLE?.
            try {
                // LocalVariableInstruction instances are typed without the need to look into
                // the constant pool.
                if (ih.getInstruction() instanceof LocalVariableInstruction) {
                    int s = LocalVariableInstruction.class.cast(ih.getInstruction()).getType(null).getSize();
                    if (s == 2) acc.add(idx + 1);
                }
            } catch(final RuntimeException re) {
                throw new AssertionViolatedException("Oops. BCEL did not like NULL as a ConstantPoolGen object.");
            }
        }
    }

    int[] ret = new int[acc.size()];
    int j = 0;
    for (final int v : acc) {
        ret[j++] = v;
    }
    return ret;
}
项目:eclectic    文件:Subroutines.java   
/**
 * This (recursive) utility method makes sure that
 * no subroutine is calling a subroutine
 * that uses the same local variable for the RET as themselves
 * (recursively).
 * This includes that subroutines may not call themselves
 * recursively, even not through intermediate calls to other
 * subroutines.
 *
 * @throws StructuralCodeConstraintException if the above constraint is not satisfied.
 */
private void noRecursiveCalls(final Subroutine sub, final Set<Integer> set){
    for (final Subroutine subSub : sub.subSubs()) {
        int index = ((RET) (subSub.getLeavingRET().getInstruction())).getIndex();
        if (!set.add(index)) {
            // Don't use toString() here because of possibly infinite recursive subSubs() calls then.
            final SubroutineImpl si = (SubroutineImpl)subSub;
            throw new StructuralCodeConstraintException("Subroutine with local variable '" + si.localVariable + "', JSRs '" + si.theJSRs+"', RET '" + si.theRET + "' is called by a subroutine which uses the same local variable index as itself; maybe even a recursive call? JustIce's clean definition of a subroutine forbids both.");
        }

        noRecursiveCalls(subSub, set);

        set.remove(index);
    }
}
项目:eclectic    文件:Subroutines.java   
public int[] getAccessedLocalsIndices(){
    //TODO: Implement caching.
    final Set<Integer> acc = new HashSet<Integer>();
    if (theRET == null && this != TOPLEVEL){
        throw new AssertionViolatedException("This subroutine object must be built up completely before calculating accessed locals.");
    }
    for (final InstructionHandle ih : instructions) {
        // RET is not a LocalVariableInstruction in the current version of BCEL.
        if (ih.getInstruction() instanceof LocalVariableInstruction || ih.getInstruction() instanceof RET){
            int idx = IndexedInstruction.class.cast(ih.getInstruction()).getIndex();
            acc.add(idx);
            // LONG? DOUBLE?.
            try {
                // LocalVariableInstruction instances are typed without the need to look into
                // the constant pool.
                if (ih.getInstruction() instanceof LocalVariableInstruction) {
                    int s = LocalVariableInstruction.class.cast(ih.getInstruction()).getType(null).getSize();
                    if (s == 2) acc.add(idx + 1);
                }
            } catch(final RuntimeException re) {
                throw new AssertionViolatedException("Oops. BCEL did not like NULL as a ConstantPoolGen object.");
            }
        }
    }

    int[] ret = new int[acc.size()];
    int j = 0;
    for (final int v : acc) {
        ret[j++] = v;
    }
    return ret;
}
项目:eclectic    文件:Subroutines.java   
/**
 * This (recursive) utility method makes sure that
 * no subroutine is calling a subroutine
 * that uses the same local variable for the RET as themselves
 * (recursively).
 * This includes that subroutines may not call themselves
 * recursively, even not through intermediate calls to other
 * subroutines.
 *
 * @throws StructuralCodeConstraintException if the above constraint is not satisfied.
 */
private void noRecursiveCalls(final Subroutine sub, final Set<Integer> set){
    for (final Subroutine subSub : sub.subSubs()) {
        int index = ((RET) (subSub.getLeavingRET().getInstruction())).getIndex();
        if (!set.add(index)) {
            // Don't use toString() here because of possibly infinite recursive subSubs() calls then.
            final SubroutineImpl si = (SubroutineImpl)subSub;
            throw new StructuralCodeConstraintException("Subroutine with local variable '" + si.localVariable + "', JSRs '" + si.theJSRs+"', RET '" + si.theRET + "' is called by a subroutine which uses the same local variable index as itself; maybe even a recursive call? JustIce's clean definition of a subroutine forbids both.");
        }

        noRecursiveCalls(subSub, set);

        set.remove(index);
    }
}
项目:VestaClient    文件:Pass3aVerifier.java   
/**
 * These are the checks if constraints are satisfied which are described in the
 * Java Virtual Machine Specification, Second Edition as Static Constraints on
 * the instructions of Java Virtual Machine Code (chapter 4.8.1).
 *
 * @throws StaticCodeConstraintException if the verification fails.
 */
private void pass3StaticInstructionChecks(){

    // Code array must not be empty:
    // Enforced in pass 2 (also stated in the static constraints of the Code
    // array in vmspec2), together with pass 1 (reading code_length bytes and
    // interpreting them as code[]). So this must not be checked again here.

    if (! (code.getCode().length < 65536)){// contradicts vmspec2 page 152 ("Limitations"), but is on page 134.
        throw new StaticCodeInstructionConstraintException("Code array in code attribute '"+code+"' too big: must be smaller than 65536 bytes.");
    }

    // First opcode at offset 0: okay, that's clear. Nothing to do.

    // Only instances of the instructions documented in Section 6.4 may appear in
    // the code array.

    // For BCEL's sake, we cannot handle WIDE stuff, but hopefully BCEL does its job right :)

    // The last byte of the last instruction in the code array must be the byte at index
    // code_length-1 : See the do_verify() comments. We actually don't iterate through the
    // byte array, but use an InstructionList so we cannot check for this. But BCEL does
    // things right, so it's implicitly okay.

    // TODO: Check how BCEL handles (and will handle) instructions like IMPDEP1, IMPDEP2,
    //       BREAKPOINT... that BCEL knows about but which are illegal anyway.
    //       We currently go the safe way here.
    InstructionHandle ih = instructionList.getStart();
    while (ih != null){
        Instruction i = ih.getInstruction();
        if (i instanceof IMPDEP1){
            throw new StaticCodeInstructionConstraintException("IMPDEP1 must not be in the code, it is an illegal instruction for _internal_ JVM use!");
        }
        if (i instanceof IMPDEP2){
            throw new StaticCodeInstructionConstraintException("IMPDEP2 must not be in the code, it is an illegal instruction for _internal_ JVM use!");
        }
        if (i instanceof BREAKPOINT){
            throw new StaticCodeInstructionConstraintException("BREAKPOINT must not be in the code, it is an illegal instruction for _internal_ JVM use!");
        }
        ih = ih.getNext();
    }

    // The original verifier seems to do this check here, too.
    // An unreachable last instruction may also not fall through the
    // end of the code, which is stupid -- but with the original
    // verifier's subroutine semantics one cannot predict reachability.
    Instruction last = instructionList.getEnd().getInstruction();
    if (! ((last instanceof ReturnInstruction)  ||
                (last instanceof RET)                               ||
                (last instanceof GotoInstruction)           ||
                (last instanceof ATHROW) )) {
           throw new StaticCodeInstructionConstraintException("Execution must not fall off the bottom of the code array. This constraint is enforced statically as some existing verifiers do - so it may be a false alarm if the last instruction is not reachable.");
       }
}
项目:VestaClient    文件:Subroutines.java   
/**
 * A utility method that calculates the successors of a given InstructionHandle
 * <B>in the same subroutine</B>. That means, a RET does not have any successors
 * as defined here. A JsrInstruction has its physical successor as its successor
 * (opposed to its target) as defined here.
 */
private static InstructionHandle[] getSuccessors(InstructionHandle instruction){
    final InstructionHandle[] empty = new InstructionHandle[0];
    final InstructionHandle[] single = new InstructionHandle[1];
    final InstructionHandle[] pair = new InstructionHandle[2];

    Instruction inst = instruction.getInstruction();

    if (inst instanceof RET){
        return empty;
    }

    // Terminates method normally.
    if (inst instanceof ReturnInstruction){
        return empty;
    }

    // Terminates method abnormally, because JustIce mandates
    // subroutines not to be protected by exception handlers.
    if (inst instanceof ATHROW){
        return empty;
    }

    // See method comment.
    if (inst instanceof JsrInstruction){
        single[0] = instruction.getNext();
        return single;
    }

    if (inst instanceof GotoInstruction){
        single[0] = ((GotoInstruction) inst).getTarget();
        return single;
    }

    if (inst instanceof BranchInstruction){
        if (inst instanceof Select){
            // BCEL's getTargets() returns only the non-default targets,
            // thanks to Eli Tilevich for reporting.
            InstructionHandle[] matchTargets = ((Select) inst).getTargets();
            InstructionHandle[] ret = new InstructionHandle[matchTargets.length+1];
            ret[0] = ((Select) inst).getTarget();
            System.arraycopy(matchTargets, 0, ret, 1, matchTargets.length);
            return ret;
        }
        else{
            pair[0] = instruction.getNext();
            pair[1] = ((BranchInstruction) inst).getTarget();
            return pair;
        }
    }

    // default case: Fall through.      
    single[0] = instruction.getNext();
    return single;
}
项目:VestaClient    文件:BCELFactory.java   
public void visitRET( RET i ) {
    _out.println("il.append(new RET(" + i.getIndex() + ")));");
}
项目:eclectic    文件:Subroutines.java   
/**
 * A utility method that calculates the successors of a given InstructionHandle
 * <B>in the same subroutine</B>. That means, a RET does not have any successors
 * as defined here. A JsrInstruction has its physical successor as its successor
 * (opposed to its target) as defined here.
 */
private static InstructionHandle[] getSuccessors(InstructionHandle instruction){
    Instruction inst = instruction.getInstruction();

       if (inst instanceof RET){
        return empty;
    }

    // Terminates method normally.
    if (inst instanceof ReturnInstruction){
        return empty;
    }

    // Terminates method abnormally, because JustIce mandates
    // subroutines not to be protected by exception handlers.
    if (inst instanceof ATHROW){
        return empty;
    }

       final InstructionHandle[] single = new InstructionHandle[1];

       // See method comment.
    if (inst instanceof JsrInstruction){
        single[0] = instruction.getNext();
        return single;
    }

    if (inst instanceof GotoInstruction){
        single[0] = ((GotoInstruction) inst).getTarget();
        return single;
    }

    if (inst instanceof BranchInstruction){
        if (inst instanceof Select){
            // BCEL's getTargets() returns only the non-default targets,
            // thanks to Eli Tilevich for reporting.
            InstructionHandle[] matchTargets = ((Select) inst).getTargets();
            InstructionHandle[] ret = new InstructionHandle[matchTargets.length+1];
            ret[0] = ((Select) inst).getTarget();
            System.arraycopy(matchTargets, 0, ret, 1, matchTargets.length);
            return ret;
        }
        else{
               final InstructionHandle[] pair = new InstructionHandle[2];
            pair[0] = instruction.getNext();
            pair[1] = ((BranchInstruction) inst).getTarget();
            return pair;
        }
    }

    // default case: Fall through.
    single[0] = instruction.getNext();
    return single;
}
项目:eclectic    文件:ControlFlowGraph.java   
/**
         * A utility method that calculates the successors of a given InstructionHandle
         * That means, a RET does have successors as defined here.
         * A JsrInstruction has its target as its successor
         * (opposed to its physical successor) as defined here.
         */
// TODO: implement caching!
        private InstructionHandle[] _getSuccessors(){
            final InstructionHandle[] empty = new InstructionHandle[0];
            final InstructionHandle[] single = new InstructionHandle[1];
            final InstructionHandle[] pair = new InstructionHandle[2];

            Instruction inst = getInstruction().getInstruction();

            if (inst instanceof RET){
                Subroutine s = subroutines.subroutineOf(getInstruction());
                if (s==null){ //return empty; // RET in dead code. "empty" would be the correct answer, but we know something about the surrounding project...
                    throw new AssertionViolatedException("Asking for successors of a RET in dead code?!");
                }
//TODO: remove
throw new AssertionViolatedException("DID YOU REALLY WANT TO ASK FOR RET'S SUCCS?");
/*
                InstructionHandle[] jsrs = s.getEnteringJsrInstructions();
                InstructionHandle[] ret = new InstructionHandle[jsrs.length];
                for (int i=0; i<jsrs.length; i++){
                    ret[i] = jsrs[i].getNext();
                }
                return ret;
*/
            }

            // Terminates method normally.
            if (inst instanceof ReturnInstruction){
                return empty;
            }

            // Terminates method abnormally, because JustIce mandates
            // subroutines not to be protected by exception handlers.
            if (inst instanceof ATHROW){
                return empty;
            }

            // See method comment.
            if (inst instanceof JsrInstruction){
                single[0] = ((JsrInstruction) inst).getTarget();
                return single;
            }

            if (inst instanceof GotoInstruction){
                single[0] = ((GotoInstruction) inst).getTarget();
                return single;
            }

            if (inst instanceof BranchInstruction){
                if (inst instanceof Select){
                    // BCEL's getTargets() returns only the non-default targets,
                    // thanks to Eli Tilevich for reporting.
                    InstructionHandle[] matchTargets = ((Select) inst).getTargets();
                    InstructionHandle[] ret = new InstructionHandle[matchTargets.length+1];
                    ret[0] = ((Select) inst).getTarget();
                    System.arraycopy(matchTargets, 0, ret, 1, matchTargets.length);
                    return ret;
                }
                else{
                    pair[0] = getInstruction().getNext();
                    pair[1] = ((BranchInstruction) inst).getTarget();
                    return pair;
                }
            }

            // default case: Fall through.      
            single[0] = getInstruction().getNext();
            return single;
        }
项目:eclectic    文件:Subroutines.java   
/**
 * A utility method that calculates the successors of a given InstructionHandle
 * <B>in the same subroutine</B>. That means, a RET does not have any successors
 * as defined here. A JsrInstruction has its physical successor as its successor
 * (opposed to its target) as defined here.
 */
private static InstructionHandle[] getSuccessors(InstructionHandle instruction){
    Instruction inst = instruction.getInstruction();

       if (inst instanceof RET){
        return empty;
    }

    // Terminates method normally.
    if (inst instanceof ReturnInstruction){
        return empty;
    }

    // Terminates method abnormally, because JustIce mandates
    // subroutines not to be protected by exception handlers.
    if (inst instanceof ATHROW){
        return empty;
    }

       final InstructionHandle[] single = new InstructionHandle[1];

       // See method comment.
    if (inst instanceof JsrInstruction){
        single[0] = instruction.getNext();
        return single;
    }

    if (inst instanceof GotoInstruction){
        single[0] = ((GotoInstruction) inst).getTarget();
        return single;
    }

    if (inst instanceof BranchInstruction){
        if (inst instanceof Select){
            // BCEL's getTargets() returns only the non-default targets,
            // thanks to Eli Tilevich for reporting.
            InstructionHandle[] matchTargets = ((Select) inst).getTargets();
            InstructionHandle[] ret = new InstructionHandle[matchTargets.length+1];
            ret[0] = ((Select) inst).getTarget();
            System.arraycopy(matchTargets, 0, ret, 1, matchTargets.length);
            return ret;
        }
        else{
               final InstructionHandle[] pair = new InstructionHandle[2];
            pair[0] = instruction.getNext();
            pair[1] = ((BranchInstruction) inst).getTarget();
            return pair;
        }
    }

    // default case: Fall through.
    single[0] = instruction.getNext();
    return single;
}
项目:eclectic    文件:ControlFlowGraph.java   
/**
         * A utility method that calculates the successors of a given InstructionHandle
         * That means, a RET does have successors as defined here.
         * A JsrInstruction has its target as its successor
         * (opposed to its physical successor) as defined here.
         */
// TODO: implement caching!
        private InstructionHandle[] _getSuccessors(){
            final InstructionHandle[] empty = new InstructionHandle[0];
            final InstructionHandle[] single = new InstructionHandle[1];
            final InstructionHandle[] pair = new InstructionHandle[2];

            Instruction inst = getInstruction().getInstruction();

            if (inst instanceof RET){
                Subroutine s = subroutines.subroutineOf(getInstruction());
                if (s==null){ //return empty; // RET in dead code. "empty" would be the correct answer, but we know something about the surrounding project...
                    throw new AssertionViolatedException("Asking for successors of a RET in dead code?!");
                }
//TODO: remove
throw new AssertionViolatedException("DID YOU REALLY WANT TO ASK FOR RET'S SUCCS?");
/*
                InstructionHandle[] jsrs = s.getEnteringJsrInstructions();
                InstructionHandle[] ret = new InstructionHandle[jsrs.length];
                for (int i=0; i<jsrs.length; i++){
                    ret[i] = jsrs[i].getNext();
                }
                return ret;
*/
            }

            // Terminates method normally.
            if (inst instanceof ReturnInstruction){
                return empty;
            }

            // Terminates method abnormally, because JustIce mandates
            // subroutines not to be protected by exception handlers.
            if (inst instanceof ATHROW){
                return empty;
            }

            // See method comment.
            if (inst instanceof JsrInstruction){
                single[0] = ((JsrInstruction) inst).getTarget();
                return single;
            }

            if (inst instanceof GotoInstruction){
                single[0] = ((GotoInstruction) inst).getTarget();
                return single;
            }

            if (inst instanceof BranchInstruction){
                if (inst instanceof Select){
                    // BCEL's getTargets() returns only the non-default targets,
                    // thanks to Eli Tilevich for reporting.
                    InstructionHandle[] matchTargets = ((Select) inst).getTargets();
                    InstructionHandle[] ret = new InstructionHandle[matchTargets.length+1];
                    ret[0] = ((Select) inst).getTarget();
                    System.arraycopy(matchTargets, 0, ret, 1, matchTargets.length);
                    return ret;
                }
                else{
                    pair[0] = getInstruction().getNext();
                    pair[1] = ((BranchInstruction) inst).getTarget();
                    return pair;
                }
            }

            // default case: Fall through.      
            single[0] = getInstruction().getNext();
            return single;
        }