Modified: 
commons/proper/bcel/trunk/src/main/java/org/apache/bcel/verifier/structurals/ControlFlowGraph.java
URL: 
http://svn.apache.org/viewvc/commons/proper/bcel/trunk/src/main/java/org/apache/bcel/verifier/structurals/ControlFlowGraph.java?rev=1598766&r1=1598765&r2=1598766&view=diff
==============================================================================
--- 
commons/proper/bcel/trunk/src/main/java/org/apache/bcel/verifier/structurals/ControlFlowGraph.java
 (original)
+++ 
commons/proper/bcel/trunk/src/main/java/org/apache/bcel/verifier/structurals/ControlFlowGraph.java
 Fri May 30 22:51:27 2014
@@ -44,421 +44,421 @@ import org.apache.bcel.verifier.exc.Stru
  */
 public class ControlFlowGraph{
 
-       /**
-        * Objects of this class represent a node in a ControlFlowGraph.
-        * These nodes are instructions, not basic blocks.
-        */
-       private class InstructionContextImpl implements InstructionContext{
-
-               /**
-                * The TAG field is here for external temporary flagging, such
-                * as graph colouring.
-                *
-                * @see #getTag()
-                * @see #setTag(int)
-                */
-               private int TAG;
-
-               /**
-                * The InstructionHandle this InstructionContext is wrapped 
around.
-                */
-               private InstructionHandle instruction;
-
-               /**
-                * The 'incoming' execution Frames.
-                */
-               private Map<InstructionContext, Frame> inFrames;        // key: 
the last-executed JSR
-
-               /**
-                * The 'outgoing' execution Frames.
-                */
-               private Map<InstructionContext, Frame> outFrames; // key: the 
last-executed JSR 
-
-               /**
-                * The 'execution predecessors' - a list of type 
InstructionContext 
-                * of those instances that have been execute()d before in that 
order.
-                */
-               private List<InstructionContext> executionPredecessors = null; 
// Type: InstructionContext
-       
-               /**
-                * Creates an InstructionHandleImpl object from an 
InstructionHandle.
-                * Creation of one per InstructionHandle suffices. Don't create 
more.
-                */
-               public InstructionContextImpl(InstructionHandle inst){
-                       if (inst == null) {
+    /**
+     * Objects of this class represent a node in a ControlFlowGraph.
+     * These nodes are instructions, not basic blocks.
+     */
+    private class InstructionContextImpl implements InstructionContext{
+
+        /**
+         * The TAG field is here for external temporary flagging, such
+         * as graph colouring.
+         *
+         * @see #getTag()
+         * @see #setTag(int)
+         */
+        private int TAG;
+
+        /**
+         * The InstructionHandle this InstructionContext is wrapped around.
+         */
+        private InstructionHandle instruction;
+
+        /**
+         * The 'incoming' execution Frames.
+         */
+        private Map<InstructionContext, Frame> inFrames;    // key: the 
last-executed JSR
+
+        /**
+         * The 'outgoing' execution Frames.
+         */
+        private Map<InstructionContext, Frame> outFrames; // key: the 
last-executed JSR 
+
+        /**
+         * The 'execution predecessors' - a list of type InstructionContext 
+         * of those instances that have been execute()d before in that order.
+         */
+        private List<InstructionContext> executionPredecessors = null; // 
Type: InstructionContext
+
+        /**
+         * Creates an InstructionHandleImpl object from an InstructionHandle.
+         * Creation of one per InstructionHandle suffices. Don't create more.
+         */
+        public InstructionContextImpl(InstructionHandle inst){
+            if (inst == null) {
                 throw new AssertionViolatedException("Cannot instantiate 
InstructionContextImpl from NULL.");
             }
-               
-                       instruction = inst;
-                       inFrames = new HashMap<InstructionContext, Frame>();
-                       outFrames = new HashMap<InstructionContext, Frame>();
-               }
-
-               /* Satisfies InstructionContext.getTag(). */
-               public int getTag(){
-                       return TAG;
-               }
-
-               /* Satisfies InstructionContext.setTag(int). */
-               public void setTag(int tag){
-                       TAG = tag;
-               }
-
-               /**
-                * Returns the exception handlers of this instruction.
-                */
-               public ExceptionHandler[] getExceptionHandlers(){
-                       return 
exceptionhandlers.getExceptionHandlers(getInstruction());
-               }
-
-               /**
-                * Returns a clone of the "outgoing" frame situation with 
respect to the given ExecutionChain.
-                */     
-               public Frame getOutFrame(ArrayList<InstructionContext> 
execChain){
-                       executionPredecessors = execChain;
-
-                       Frame org;
-
-                       InstructionContext jsr = lastExecutionJSR();
-
-                       org = outFrames.get(jsr);
-
-                       if (org == null){
-                               throw new AssertionViolatedException("outFrame 
not set! This:\n"+this+"\nExecutionChain: "+getExecutionChain()+"\nOutFrames: 
'"+outFrames+"'.");
-                       }
-                       return org.getClone();
-               }
+
+            instruction = inst;
+            inFrames = new HashMap<InstructionContext, Frame>();
+            outFrames = new HashMap<InstructionContext, Frame>();
+        }
+
+        /* Satisfies InstructionContext.getTag(). */
+        public int getTag(){
+            return TAG;
+        }
+
+        /* Satisfies InstructionContext.setTag(int). */
+        public void setTag(int tag){
+            TAG = tag;
+        }
+
+        /**
+         * Returns the exception handlers of this instruction.
+         */
+        public ExceptionHandler[] getExceptionHandlers(){
+            return exceptionhandlers.getExceptionHandlers(getInstruction());
+        }
+
+        /**
+         * Returns a clone of the "outgoing" frame situation with respect to 
the given ExecutionChain.
+         */    
+        public Frame getOutFrame(ArrayList<InstructionContext> execChain){
+            executionPredecessors = execChain;
+
+            Frame org;
+
+            InstructionContext jsr = lastExecutionJSR();
+
+            org = outFrames.get(jsr);
+
+            if (org == null){
+                throw new AssertionViolatedException("outFrame not set! 
This:\n"+this+"\nExecutionChain: "+getExecutionChain()+"\nOutFrames: 
'"+outFrames+"'.");
+            }
+            return org.getClone();
+        }
 
     public Frame getInFrame() {
-                 Frame org;
-                       
-                       InstructionContext jsr = lastExecutionJSR();
-                       
-                       org = inFrames.get(jsr);
+          Frame org;
+
+            InstructionContext jsr = lastExecutionJSR();
 
-                       if (org == null){
-                           throw new AssertionViolatedException("inFrame not 
set! This:\n"+this+"\nInFrames: '"+inFrames+"'.");
+            org = inFrames.get(jsr);
+
+            if (org == null){
+                throw new AssertionViolatedException("inFrame not set! 
This:\n"+this+"\nInFrames: '"+inFrames+"'.");
       }
       return org.getClone();
     }
 
-               /**
-                * "Merges in" (vmspec2, page 146) the "incoming" frame 
situation;
-                * executes the instructions symbolically
-                * and therefore calculates the "outgoing" frame situation.
-                * Returns: True iff the "incoming" frame situation changed 
after
-                * merging with "inFrame".
-                * The execPreds ArrayList must contain the InstructionContext
-                * objects executed so far in the correct order. This is just
-                * one execution path [out of many]. This is needed to correctly
-                * "merge" in the special case of a RET's successor.
-                * <B>The InstConstraintVisitor and ExecutionVisitor instances
-                * must be set up correctly.</B>
-                * @return true - if and only if the "outgoing" frame situation
-                * changed from the one before execute()ing.
-                */
-               public boolean execute(Frame inFrame, 
ArrayList<InstructionContext> execPreds, InstConstraintVisitor icv, 
ExecutionVisitor ev){
-
-                       executionPredecessors = (List<InstructionContext>) 
execPreds.clone();
-
-                       //sanity check
-                       if ( (lastExecutionJSR() == null) && 
(subroutines.subroutineOf(getInstruction()) != subroutines.getTopLevel() ) ){
-                               throw new AssertionViolatedException("Huh?! Am 
I '"+this+"' part of a subroutine or not?");
-                       }
-                       if ( (lastExecutionJSR() != null) && 
(subroutines.subroutineOf(getInstruction()) == subroutines.getTopLevel() ) ){
-                               throw new AssertionViolatedException("Huh?! Am 
I '"+this+"' part of a subroutine or not?");
-                       }
-
-                       Frame inF = inFrames.get(lastExecutionJSR());
-                       if (inF == null){// no incoming frame was set, so set 
it.
-                               inFrames.put(lastExecutionJSR(), inFrame);
-                               inF = inFrame;
-                       }
-                       else{// if there was an "old" inFrame
-                               if (inF.equals(inFrame)){ //shortcut: no need 
to merge equal frames.
-                                       return false;
-                               }
-                               if (! mergeInFrames(inFrame)){
-                                       return false;
-                               }
-                       }
-                       
-                       // Now we're sure the inFrame has changed!
-                       
-                       // new inFrame is already merged in, see above.         
-                       Frame workingFrame = inF.getClone();
-
-                       try{
-                               // This verifies the InstructionConstraint for 
the current
-                               // instruction, but does not modify the 
workingFrame object.
+        /**
+         * "Merges in" (vmspec2, page 146) the "incoming" frame situation;
+         * executes the instructions symbolically
+         * and therefore calculates the "outgoing" frame situation.
+         * Returns: True iff the "incoming" frame situation changed after
+         * merging with "inFrame".
+         * The execPreds ArrayList must contain the InstructionContext
+         * objects executed so far in the correct order. This is just
+         * one execution path [out of many]. This is needed to correctly
+         * "merge" in the special case of a RET's successor.
+         * <B>The InstConstraintVisitor and ExecutionVisitor instances
+         * must be set up correctly.</B>
+         * @return true - if and only if the "outgoing" frame situation
+         * changed from the one before execute()ing.
+         */
+        public boolean execute(Frame inFrame, ArrayList<InstructionContext> 
execPreds, InstConstraintVisitor icv, ExecutionVisitor ev){
+
+            executionPredecessors = (List<InstructionContext>) 
execPreds.clone();
+
+            //sanity check
+            if ( (lastExecutionJSR() == null) && 
(subroutines.subroutineOf(getInstruction()) != subroutines.getTopLevel() ) ){
+                throw new AssertionViolatedException("Huh?! Am I '"+this+"' 
part of a subroutine or not?");
+            }
+            if ( (lastExecutionJSR() != null) && 
(subroutines.subroutineOf(getInstruction()) == subroutines.getTopLevel() ) ){
+                throw new AssertionViolatedException("Huh?! Am I '"+this+"' 
part of a subroutine or not?");
+            }
+
+            Frame inF = inFrames.get(lastExecutionJSR());
+            if (inF == null){// no incoming frame was set, so set it.
+                inFrames.put(lastExecutionJSR(), inFrame);
+                inF = inFrame;
+            }
+            else{// if there was an "old" inFrame
+                if (inF.equals(inFrame)){ //shortcut: no need to merge equal 
frames.
+                    return false;
+                }
+                if (! mergeInFrames(inFrame)){
+                    return false;
+                }
+            }
+
+            // Now we're sure the inFrame has changed!
+
+            // new inFrame is already merged in, see above.        
+            Frame workingFrame = inF.getClone();
+
+            try{
+                // This verifies the InstructionConstraint for the current
+                // instruction, but does not modify the workingFrame object.
 //InstConstraintVisitor icv = 
InstConstraintVisitor.getInstance(VerifierFactory.getVerifier(method_gen.getClassName()));
-                               icv.setFrame(workingFrame);
-                               getInstruction().accept(icv);
-                       }
-                       catch(StructuralCodeConstraintException ce){
-                               ce.extendMessage("","\nInstructionHandle: 
"+getInstruction()+"\n");
-                               ce.extendMessage("","\nExecution 
Frame:\n"+workingFrame);
-                               extendMessageWithFlow(ce);
-                               throw ce;
-                       }
+                icv.setFrame(workingFrame);
+                getInstruction().accept(icv);
+            }
+            catch(StructuralCodeConstraintException ce){
+                ce.extendMessage("","\nInstructionHandle: 
"+getInstruction()+"\n");
+                ce.extendMessage("","\nExecution Frame:\n"+workingFrame);
+                extendMessageWithFlow(ce);
+                throw ce;
+            }
 
-                       // This executes the Instruction.
-                       // Therefore the workingFrame object is modified.
+            // This executes the Instruction.
+            // Therefore the workingFrame object is modified.
 //ExecutionVisitor ev = 
ExecutionVisitor.getInstance(VerifierFactory.getVerifier(method_gen.getClassName()));
-                       ev.setFrame(workingFrame);
-                       getInstruction().accept(ev);
-                       
//getInstruction().accept(ExecutionVisitor.withFrame(workingFrame));
-                       outFrames.put(lastExecutionJSR(), workingFrame);
-
-                       return true;    // new inFrame was different from old 
inFrame so merging them
-                                                                               
// yielded a different this.inFrame.
-               }
-
-               /**
-                * Returns a simple String representation of this 
InstructionContext.
-                */
-               @Override
+            ev.setFrame(workingFrame);
+            getInstruction().accept(ev);
+            
//getInstruction().accept(ExecutionVisitor.withFrame(workingFrame));
+            outFrames.put(lastExecutionJSR(), workingFrame);
+
+            return true;    // new inFrame was different from old inFrame so 
merging them
+                                        // yielded a different this.inFrame.
+        }
+
+        /**
+         * Returns a simple String representation of this InstructionContext.
+         */
+        @Override
         public String toString(){
-               //TODO: Put information in the brackets, e.g.
-               //      Is this an ExceptionHandler? Is this a RET? Is this the 
start of
-               //      a subroutine?
-                       String ret = 
getInstruction().toString(false)+"\t[InstructionContext]";
-                       return ret;
-               }
-
-               /**
-                * Does the actual merging (vmspec2, page 146).
-                * Returns true IFF this.inFrame was changed in course of 
merging with inFrame.
-                */
-               private boolean mergeInFrames(Frame inFrame){
-                       // TODO: Can be performance-improved.
-                       Frame inF = inFrames.get(lastExecutionJSR());
-                       OperandStack oldstack = inF.getStack().getClone();
-                       LocalVariables oldlocals = inF.getLocals().getClone();
-                       try{
-                               inF.getStack().merge(inFrame.getStack());
-                               inF.getLocals().merge(inFrame.getLocals());
-                       }
-                       catch (StructuralCodeConstraintException sce){
-                               extendMessageWithFlow(sce);
-                               throw sce;
-                       }
-                       if (    oldstack.equals(inF.getStack()) &&
-                                               
oldlocals.equals(inF.getLocals()) ){
-                               return false;
-                       }
-                       else{
-                               return true;
-                       }
-               }
-
-               /**
-                * Returns the control flow execution chain. This is built
-                * while execute(Frame, ArrayList)-ing the code represented
-                * by the surrounding ControlFlowGraph.
-                */
-               private String getExecutionChain(){
-                       String s = this.toString();
-                       for (int i=executionPredecessors.size()-1; i>=0; i--){
-                               s = executionPredecessors.get(i)+"\n" + s;
-                       }
-                       return s;
-               }
-
-
-               /**
-                * Extends the StructuralCodeConstraintException ("e") object 
with an at-the-end-extended message.
-                * This extended message will then reflect the execution flow 
needed to get to the constraint
-                * violation that triggered the throwing of the "e" object.
-                */
-               private void 
extendMessageWithFlow(StructuralCodeConstraintException e){
-                       String s = "Execution flow:\n";
-                       e.extendMessage("", s+getExecutionChain());
-               }
-
-               /*
-                * Fulfils the contract of InstructionContext.getInstruction().
-                */
-               public InstructionHandle getInstruction(){
-                       return instruction;
-               }
-
-               /**
-                * 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) {
+        //TODO: Put information in the brackets, e.g.
+        //      Is this an ExceptionHandler? Is this a RET? Is this the start 
of
+        //      a subroutine?
+            String ret = 
getInstruction().toString(false)+"\t[InstructionContext]";
+            return ret;
+        }
+
+        /**
+         * Does the actual merging (vmspec2, page 146).
+         * Returns true IFF this.inFrame was changed in course of merging with 
inFrame.
+         */
+        private boolean mergeInFrames(Frame inFrame){
+            // TODO: Can be performance-improved.
+            Frame inF = inFrames.get(lastExecutionJSR());
+            OperandStack oldstack = inF.getStack().getClone();
+            LocalVariables oldlocals = inF.getLocals().getClone();
+            try{
+                inF.getStack().merge(inFrame.getStack());
+                inF.getLocals().merge(inFrame.getLocals());
+            }
+            catch (StructuralCodeConstraintException sce){
+                extendMessageWithFlow(sce);
+                throw sce;
+            }
+            if (    oldstack.equals(inF.getStack()) &&
+                        oldlocals.equals(inF.getLocals()) ){
+                return false;
+            }
+            else{
+                return true;
+            }
+        }
+
+        /**
+         * Returns the control flow execution chain. This is built
+         * while execute(Frame, ArrayList)-ing the code represented
+         * by the surrounding ControlFlowGraph.
+         */
+        private String getExecutionChain(){
+            String s = this.toString();
+            for (int i=executionPredecessors.size()-1; i>=0; i--){
+                s = executionPredecessors.get(i)+"\n" + s;
+            }
+            return s;
+        }
+
+
+        /**
+         * Extends the StructuralCodeConstraintException ("e") object with an 
at-the-end-extended message.
+         * This extended message will then reflect the execution flow needed 
to get to the constraint
+         * violation that triggered the throwing of the "e" object.
+         */
+        private void extendMessageWithFlow(StructuralCodeConstraintException 
e){
+            String s = "Execution flow:\n";
+            e.extendMessage("", s+getExecutionChain());
+        }
+
+        /*
+         * Fulfils the contract of InstructionContext.getInstruction().
+         */
+        public InstructionHandle getInstruction(){
+            return instruction;
+        }
+
+        /**
+         * 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) {
+                if (currentlast instanceof JsrInstruction){
+                    retcount--;
+                    if (retcount == -1) {
                         return current;
                     }
-                               }
-                       }
-                       return null;
-               }
-
-               /* Satisfies InstructionContext.getSuccessors(). */
-               public InstructionContext[] getSuccessors(){
-                       return contextsOf(_getSuccessors());
-               }
-
-               /**
-                * 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.
-                */
+                }
+            }
+            return null;
+        }
+
+        /* Satisfies InstructionContext.getSuccessors(). */
+        public InstructionContext[] getSuccessors(){
+            return contextsOf(_getSuccessors());
+        }
+
+        /**
+         * 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];
-               
-                       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?!");
-                               }
+        private InstructionHandle[] _getSuccessors(){
+            final InstructionHandle[] empty = new InstructionHandle[0];
+            final InstructionHandle[] single = new InstructionHandle[1];
+
+            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. Only JustIce must not use it, but foreign users of the 
ControlFlowGraph
 //      will want it. Thanks Johannes Wust.
 //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{
-                                       final InstructionHandle[] pair = new 
InstructionHandle[2];
-                                       pair[0] = getInstruction().getNext();
-                                       pair[1] = ((BranchInstruction) 
inst).getTarget();
-                                       return pair;
-                               }
-                       }
-
-                       // default case: Fall through.          
-                       single[0] = getInstruction().getNext();
-                       return single;
-               }
-
-       } // End Inner InstructionContextImpl Class.
-
-       ///** The MethodGen object we're working on. */
-       //private final MethodGen method_gen;
-
-       /** The Subroutines object for the method whose control flow is 
represented by this ControlFlowGraph. */
-       private final Subroutines subroutines;
-
-       /** The ExceptionHandlers object for the method whose control flow is 
represented by this ControlFlowGraph. */
-       private final ExceptionHandlers exceptionhandlers;
-
-       /** All InstructionContext instances of this ControlFlowGraph. */
-       private Map<InstructionHandle, InstructionContext> instructionContexts 
= new HashMap<InstructionHandle, InstructionContext>(); //keys: 
InstructionHandle, values: InstructionContextImpl
-
-       /** 
-        * A Control Flow Graph.
-        */
-       public ControlFlowGraph(MethodGen method_gen){
-               subroutines = new Subroutines(method_gen);
-               exceptionhandlers = new ExceptionHandlers(method_gen);
-
-               InstructionHandle[] instructionhandles = 
method_gen.getInstructionList().getInstructionHandles();
-               for (InstructionHandle instructionhandle : instructionhandles) {
-                       instructionContexts.put(instructionhandle, new 
InstructionContextImpl(instructionhandle));
-               }
-               
-               //this.method_gen = method_gen;
-       }
-
-       /**
-        * Returns the InstructionContext of a given instruction.
-        */
-       public InstructionContext contextOf(InstructionHandle inst){
-               InstructionContext ic = instructionContexts.get(inst);
-               if (ic == null){
-                       throw new 
AssertionViolatedException("InstructionContext requested for an 
InstructionHandle that's not known!");
-               }
-               return ic;
-       }
-
-       /**
-        * Returns the InstructionContext[] of a given InstructionHandle[],
-        * in a naturally ordered manner.
-        */
-       public InstructionContext[] contextsOf(InstructionHandle[] insts){
-               InstructionContext[] ret = new InstructionContext[insts.length];
-               for (int i=0; i<insts.length; i++){
-                       ret[i] = contextOf(insts[i]);
-               }
-               return ret;
-       }
-
-       /**
-        * Returns an InstructionContext[] with all the InstructionContext 
instances
-        * for the method whose control flow is represented by this 
ControlFlowGraph
-        * <B>(NOT ORDERED!)</B>.
-        */
-       public InstructionContext[] getInstructionContexts(){
-               InstructionContext[] ret = new 
InstructionContext[instructionContexts.values().size()];
-               return instructionContexts.values().toArray(ret);
-       }
-
-       /**
-        * Returns true, if and only if the said instruction is not reachable; 
that means,
-        * if it is not part of this ControlFlowGraph.
-        */
-       public boolean isDead(InstructionHandle i){
+                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{
+                    final InstructionHandle[] pair = new InstructionHandle[2];
+                    pair[0] = getInstruction().getNext();
+                    pair[1] = ((BranchInstruction) inst).getTarget();
+                    return pair;
+                }
+            }
+
+            // default case: Fall through.        
+            single[0] = getInstruction().getNext();
+            return single;
+        }
+
+    } // End Inner InstructionContextImpl Class.
+
+    ///** The MethodGen object we're working on. */
+    //private final MethodGen method_gen;
+
+    /** The Subroutines object for the method whose control flow is 
represented by this ControlFlowGraph. */
+    private final Subroutines subroutines;
+
+    /** The ExceptionHandlers object for the method whose control flow is 
represented by this ControlFlowGraph. */
+    private final ExceptionHandlers exceptionhandlers;
+
+    /** All InstructionContext instances of this ControlFlowGraph. */
+    private Map<InstructionHandle, InstructionContext> instructionContexts = 
new HashMap<InstructionHandle, InstructionContext>(); //keys: 
InstructionHandle, values: InstructionContextImpl
+
+    /** 
+     * A Control Flow Graph.
+     */
+    public ControlFlowGraph(MethodGen method_gen){
+        subroutines = new Subroutines(method_gen);
+        exceptionhandlers = new ExceptionHandlers(method_gen);
+
+        InstructionHandle[] instructionhandles = 
method_gen.getInstructionList().getInstructionHandles();
+        for (InstructionHandle instructionhandle : instructionhandles) {
+            instructionContexts.put(instructionhandle, new 
InstructionContextImpl(instructionhandle));
+        }
+
+        //this.method_gen = method_gen;
+    }
+
+    /**
+     * Returns the InstructionContext of a given instruction.
+     */
+    public InstructionContext contextOf(InstructionHandle inst){
+        InstructionContext ic = instructionContexts.get(inst);
+        if (ic == null){
+            throw new AssertionViolatedException("InstructionContext requested 
for an InstructionHandle that's not known!");
+        }
+        return ic;
+    }
+
+    /**
+     * Returns the InstructionContext[] of a given InstructionHandle[],
+     * in a naturally ordered manner.
+     */
+    public InstructionContext[] contextsOf(InstructionHandle[] insts){
+        InstructionContext[] ret = new InstructionContext[insts.length];
+        for (int i=0; i<insts.length; i++){
+            ret[i] = contextOf(insts[i]);
+        }
+        return ret;
+    }
+
+    /**
+     * Returns an InstructionContext[] with all the InstructionContext 
instances
+     * for the method whose control flow is represented by this 
ControlFlowGraph
+     * <B>(NOT ORDERED!)</B>.
+     */
+    public InstructionContext[] getInstructionContexts(){
+        InstructionContext[] ret = new 
InstructionContext[instructionContexts.values().size()];
+        return instructionContexts.values().toArray(ret);
+    }
+
+    /**
+     * Returns true, if and only if the said instruction is not reachable; 
that means,
+     * if it is not part of this ControlFlowGraph.
+     */
+    public boolean isDead(InstructionHandle i){
         return subroutines.subroutineOf(i) == null;
-       }        
+    }     
 }

Modified: 
commons/proper/bcel/trunk/src/main/java/org/apache/bcel/verifier/structurals/ExceptionHandler.java
URL: 
http://svn.apache.org/viewvc/commons/proper/bcel/trunk/src/main/java/org/apache/bcel/verifier/structurals/ExceptionHandler.java?rev=1598766&r1=1598765&r2=1598766&view=diff
==============================================================================
--- 
commons/proper/bcel/trunk/src/main/java/org/apache/bcel/verifier/structurals/ExceptionHandler.java
 (original)
+++ 
commons/proper/bcel/trunk/src/main/java/org/apache/bcel/verifier/structurals/ExceptionHandler.java
 Fri May 30 22:51:27 2014
@@ -30,29 +30,29 @@ import org.apache.bcel.generic.ObjectTyp
  * @author Enver Haase
  */
 public class ExceptionHandler{
-       /** The type of the exception to catch. NULL means ANY. */
-       private ObjectType catchtype;
-       
-       /** The InstructionHandle where the handling begins. */
-       private InstructionHandle handlerpc;
+    /** The type of the exception to catch. NULL means ANY. */
+    private ObjectType catchtype;
 
-       /** Leave instance creation to JustIce. */
-       ExceptionHandler(ObjectType catch_type, InstructionHandle handler_pc){
-               catchtype = catch_type;
-               handlerpc = handler_pc;
-       }
+    /** The InstructionHandle where the handling begins. */
+    private InstructionHandle handlerpc;
 
-       /**
-        * Returns the type of the exception that's handled. <B>'null' means 
'ANY'.</B>
-        */
-       public ObjectType getExceptionType(){
-               return catchtype;
-       }
+    /** Leave instance creation to JustIce. */
+    ExceptionHandler(ObjectType catch_type, InstructionHandle handler_pc){
+        catchtype = catch_type;
+        handlerpc = handler_pc;
+    }
 
-       /**
-        * Returns the InstructionHandle where the handler starts off.
-        */
-       public InstructionHandle getHandlerStart(){
-               return handlerpc;
-       }
+    /**
+     * Returns the type of the exception that's handled. <B>'null' means 
'ANY'.</B>
+     */
+    public ObjectType getExceptionType(){
+        return catchtype;
+    }
+
+    /**
+     * Returns the InstructionHandle where the handler starts off.
+     */
+    public InstructionHandle getHandlerStart(){
+        return handlerpc;
+    }
 }

Modified: 
commons/proper/bcel/trunk/src/main/java/org/apache/bcel/verifier/structurals/ExceptionHandlers.java
URL: 
http://svn.apache.org/viewvc/commons/proper/bcel/trunk/src/main/java/org/apache/bcel/verifier/structurals/ExceptionHandlers.java?rev=1598766&r1=1598765&r2=1598766&view=diff
==============================================================================
--- 
commons/proper/bcel/trunk/src/main/java/org/apache/bcel/verifier/structurals/ExceptionHandlers.java
 (original)
+++ 
commons/proper/bcel/trunk/src/main/java/org/apache/bcel/verifier/structurals/ExceptionHandlers.java
 Fri May 30 22:51:27 2014
@@ -34,44 +34,44 @@ import org.apache.bcel.generic.MethodGen
  * @author Enver Haase
  */
 public class ExceptionHandlers{
-       /**
-        * The ExceptionHandler instances.
-        * Key: InstructionHandle objects, Values: HashSet<ExceptionHandler> 
instances.
-        */
-       private Map<InstructionHandle, Set<ExceptionHandler>> exceptionhandlers;
-        
-       /**
-        * Constructor. Creates a new ExceptionHandlers instance.
-        */
-       public ExceptionHandlers(MethodGen mg){
-               exceptionhandlers = new HashMap<InstructionHandle, 
Set<ExceptionHandler>>();
-               CodeExceptionGen[] cegs = mg.getExceptionHandlers();
-               for (CodeExceptionGen ceg : cegs) {
-                       ExceptionHandler eh = new 
ExceptionHandler(ceg.getCatchType(), ceg.getHandlerPC());
-                       for (InstructionHandle ih=ceg.getStartPC(); ih != 
ceg.getEndPC().getNext(); ih=ih.getNext()){
-                               Set<ExceptionHandler> hs;
-                               hs = exceptionhandlers.get(ih);
-                               if (hs == null){
-                                       hs = new HashSet<ExceptionHandler>();
-                                       exceptionhandlers.put(ih, hs);
-                               }
-                               hs.add(eh);
-                       }
-               }
-       }
-       
-       /**
-        * Returns all the ExceptionHandler instances representing exception
-        * handlers that protect the instruction ih.
-        */
-       public ExceptionHandler[] getExceptionHandlers(InstructionHandle ih){
-               Set<ExceptionHandler> hs = exceptionhandlers.get(ih);
-               if (hs == null) {
+    /**
+     * The ExceptionHandler instances.
+     * Key: InstructionHandle objects, Values: HashSet<ExceptionHandler> 
instances.
+     */
+    private Map<InstructionHandle, Set<ExceptionHandler>> exceptionhandlers;
+
+    /**
+     * Constructor. Creates a new ExceptionHandlers instance.
+     */
+    public ExceptionHandlers(MethodGen mg){
+        exceptionhandlers = new HashMap<InstructionHandle, 
Set<ExceptionHandler>>();
+        CodeExceptionGen[] cegs = mg.getExceptionHandlers();
+        for (CodeExceptionGen ceg : cegs) {
+            ExceptionHandler eh = new ExceptionHandler(ceg.getCatchType(), 
ceg.getHandlerPC());
+            for (InstructionHandle ih=ceg.getStartPC(); ih != 
ceg.getEndPC().getNext(); ih=ih.getNext()){
+                Set<ExceptionHandler> hs;
+                hs = exceptionhandlers.get(ih);
+                if (hs == null){
+                    hs = new HashSet<ExceptionHandler>();
+                    exceptionhandlers.put(ih, hs);
+                }
+                hs.add(eh);
+            }
+        }
+    }
+
+    /**
+     * Returns all the ExceptionHandler instances representing exception
+     * handlers that protect the instruction ih.
+     */
+    public ExceptionHandler[] getExceptionHandlers(InstructionHandle ih){
+        Set<ExceptionHandler> hs = exceptionhandlers.get(ih);
+        if (hs == null) {
             return new ExceptionHandler[0];
         } else{
-                       ExceptionHandler[] ret = new 
ExceptionHandler[hs.size()];
-                       return hs.toArray(ret);
-               }
-       }
+            ExceptionHandler[] ret = new ExceptionHandler[hs.size()];
+            return hs.toArray(ret);
+        }
+    }
 
 }


Reply via email to