You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by se...@apache.org on 2014/05/31 00:51:30 UTC

svn commit: r1598766 [7/12] - in /commons/proper/bcel/trunk/src: main/java/org/apache/bcel/ main/java/org/apache/bcel/classfile/ main/java/org/apache/bcel/generic/ main/java/org/apache/bcel/util/ main/java/org/apache/bcel/verifier/exc/ main/java/org/ap...

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);
+        }
+    }
 
 }