You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by tc...@apache.org on 2009/01/11 20:51:42 UTC

svn commit: r733503 [3/5] - in /commons/sandbox/javaflow/trunk: ./ src/java/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/commons/ src/main/java/org/apache/commons/javaflow/ src/main/java/org/apache/com...

Added: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ControlFlowGraph.java
URL: http://svn.apache.org/viewvc/commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ControlFlowGraph.java?rev=733503&view=auto
==============================================================================
--- commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ControlFlowGraph.java (added)
+++ commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ControlFlowGraph.java Sun Jan 11 11:51:40 2009
@@ -0,0 +1,398 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.javaflow.bytecode.transformation.bcel.analyser;
+
+import java.util.HashMap;
+import java.util.Hashtable;
+
+import org.apache.bcel.generic.ATHROW;
+import org.apache.bcel.generic.BranchInstruction;
+import org.apache.bcel.generic.GotoInstruction;
+import org.apache.bcel.generic.Instruction;
+import org.apache.bcel.generic.InstructionHandle;
+import org.apache.bcel.generic.JsrInstruction;
+import org.apache.bcel.generic.MethodGen;
+import org.apache.bcel.generic.RET;
+import org.apache.bcel.generic.ReturnInstruction;
+import org.apache.bcel.generic.Select;
+import org.apache.bcel.verifier.exc.AssertionViolatedException;
+import org.apache.bcel.verifier.exc.StructuralCodeConstraintException;
+
+
+/**
+ * This class represents a control flow graph of a method.
+ * 
+ * WARNING! These classes are a fork of the bcel verifier. 
+ *
+ * @version $Id$
+ * @author <A HREF="http://www.inf.fu-berlin.de/~ehaase"/>Enver Haase</A>
+ */
+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 InstructionHandle this InstructionContext is wrapped around.
+		 */
+		private InstructionHandle instruction;
+
+		/**
+		 * The 'incoming' execution Frames.
+		 */
+		private HashMap inFrames;	// key: the last-executed JSR
+
+		/**
+		 * The 'outgoing' execution Frames.
+		 */
+		private HashMap outFrames; // key: the last-executed JSR 
+
+		/**
+		 * The 'execution predecessors' - a list of {@link InstructionContext}
+		 * of those instances that have been execute()d before in that order.
+		 */
+		private ExecutionPath 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 java.util.HashMap();
+			outFrames = new java.util.HashMap();
+		}
+
+		/**
+		 * 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(ExecutionPath execChain){
+			executionPredecessors = execChain;
+
+			Frame org;
+
+			InstructionContext jsr = lastExecutionJSR();
+
+			org = (Frame) 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 = (Frame) 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 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, ExecutionPath execPreds, ExecutionVisitor ev){
+
+            // When merge failed, this is useful to see what are two passes
+            //ExecutionPath oldExecPreds = executionPredecessors;
+
+            executionPredecessors = execPreds;
+
+			//sanity check
+			if ( (lastExecutionJSR() == null) && (subroutines.subroutineOf(getInstruction()) != subroutines.getTopLevel() ) ){
+				//throw new AssertionViolatedException("Huh?! Am I '"+this+"' part of a subroutine or not?");
+				return false;
+			}
+			if ( (lastExecutionJSR() != null) && (subroutines.subroutineOf(getInstruction()) == subroutines.getTopLevel() ) ){
+				//throw new AssertionViolatedException("Huh?! Am I '"+this+"' part of a subroutine or not?");
+				return false;
+			}
+
+			Frame inF = (Frame) 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();
+
+			// 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.
+		 */
+		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 = (Frame) 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 {@link #execute(Frame, ExecutionPath, ExecutionVisitor) executing} the code represented
+		 * by the surrounding ControlFlowGraph.
+		 */
+		private String getExecutionChain(){
+            return executionPredecessors.toString()+"\n"+this.toString();
+		}
+
+
+		/**
+		 * 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;
+		}
+
+		private InstructionContext lastExecutionJSR(){
+            return executionPredecessors.lastExecutionJSR();
+		}
+
+		/* 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];
+			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;
+		}
+
+	} // End Inner InstructionContextImpl Class.
+
+	/** 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 Hashtable instructionContexts = new Hashtable(); //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 (int i=0; i<instructionhandles.length; i++){
+			instructionContexts.put(instructionhandles[i], new InstructionContextImpl(instructionhandles[i]));
+		}
+	}
+
+	/**
+	 * Returns the InstructionContext of a given instruction.
+	 */
+	public InstructionContext contextOf(InstructionHandle inst){
+		InstructionContext ic = (InstructionContext) 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 (InstructionContext[]) 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;
+	}	 
+}

Propchange: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ControlFlowGraph.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ControlFlowGraph.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ControlFlowGraph.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ExceptionHandler.java
URL: http://svn.apache.org/viewvc/commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ExceptionHandler.java?rev=733503&view=auto
==============================================================================
--- commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ExceptionHandler.java (added)
+++ commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ExceptionHandler.java Sun Jan 11 11:51:40 2009
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.javaflow.bytecode.transformation.bcel.analyser;
+
+import org.apache.bcel.generic.*;
+
+/**
+ * This class represents an exception handler; that is, an ObjectType
+ * representing a subclass of java.lang.Throwable and the instruction
+ * the handler starts off (represented by an InstructionContext).
+ * 
+ * WARNING! These classes are a fork of the bcel verifier. 
+ * 
+ * @version $Id$
+ * @author <A HREF="http://www.inf.fu-berlin.de/~ehaase"/>Enver Haase</A>
+ */
+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;
+
+	/** Leave instance creation to JustIce. */
+	ExceptionHandler(ObjectType catch_type, InstructionHandle handler_pc){
+		catchtype = catch_type;
+		handlerpc = handler_pc;
+	}
+
+	/**
+	 * 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;
+	}
+}

Propchange: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ExceptionHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ExceptionHandler.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ExceptionHandler.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ExceptionHandlers.java
URL: http://svn.apache.org/viewvc/commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ExceptionHandlers.java?rev=733503&view=auto
==============================================================================
--- commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ExceptionHandlers.java (added)
+++ commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ExceptionHandlers.java Sun Jan 11 11:51:40 2009
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.javaflow.bytecode.transformation.bcel.analyser;
+
+import org.apache.bcel.generic.*;
+import java.util.HashSet;
+import java.util.Hashtable;
+
+/**
+ * This class allows easy access to ExceptionHandler objects.
+ * 
+ * WARNING! These classes are a fork of the bcel verifier.
+ *
+ * @version $Id$
+ * @author <A HREF="http://www.inf.fu-berlin.de/~ehaase"/>Enver Haase</A>
+ */
+public class ExceptionHandlers{
+	/**
+	 * The ExceptionHandler instances.
+	 * Key: InstructionHandle objects, Values: HashSet<ExceptionHandler> instances.
+	 */
+	private Hashtable exceptionhandlers;
+	 
+	/**
+	 * Constructor. Creates a new ExceptionHandlers instance.
+	 */
+	public ExceptionHandlers(MethodGen mg){
+		exceptionhandlers = new Hashtable();
+		CodeExceptionGen[] cegs = mg.getExceptionHandlers();
+		for (int i=0; i<cegs.length; i++){
+			ExceptionHandler eh = new ExceptionHandler(cegs[i].getCatchType(), cegs[i].getHandlerPC());
+			for (InstructionHandle ih=cegs[i].getStartPC(); ih != cegs[i].getEndPC().getNext(); ih=ih.getNext()){
+				HashSet hs;
+				hs = (HashSet) exceptionhandlers.get(ih);
+				if (hs == null){
+					hs = new HashSet();
+					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){
+		HashSet hs = (HashSet) exceptionhandlers.get(ih);
+		if (hs == null) return new ExceptionHandler[0];
+		else{
+			ExceptionHandler[] ret = new ExceptionHandler[hs.size()];
+			return (ExceptionHandler[]) (hs.toArray(ret));
+		}
+	}
+
+}

Propchange: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ExceptionHandlers.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ExceptionHandlers.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ExceptionHandlers.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ExecutionPath.java
URL: http://svn.apache.org/viewvc/commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ExecutionPath.java?rev=733503&view=auto
==============================================================================
--- commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ExecutionPath.java (added)
+++ commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ExecutionPath.java Sun Jan 11 11:51:40 2009
@@ -0,0 +1,72 @@
+package org.apache.commons.javaflow.bytecode.transformation.bcel.analyser;
+
+import org.apache.bcel.generic.Instruction;
+import org.apache.bcel.generic.RET;
+import org.apache.bcel.generic.JsrInstruction;
+
+/**
+ * List of {@link InstructionContext} that represents a sequence of an execution.
+ *
+ * <p>
+ * This object is immutable.
+ * The sequence is represented in left-associative style; that is,
+ * a sequence of [a,b,c,d] is represented as prev=[a,b,c] and last=d.
+ *
+ * @author Kohsuke Kawaguchi
+ */
+public final class ExecutionPath {
+    /**
+     * Singleton {@link ExecutionPath} that represents an empty sequence [].
+     */
+    public static final ExecutionPath EMPTY = new ExecutionPath(null,null);
+
+    private final ExecutionPath prev;
+    private final InstructionContext last;
+
+    private ExecutionPath(ExecutionPath prev, InstructionContext last) {
+        this.prev = prev;
+        this.last = last;
+    }
+
+    /**
+     * Creates a new {@link ExecutionPath} that has
+     * <tt>[... list in this ExecutionPath ..., ins]</tt>.
+     */
+    public ExecutionPath append(InstructionContext ins) {
+        return new ExecutionPath(this,ins);
+    }
+
+    /**
+     * 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;
+    }
+
+    /**
+     * Returns a human readable representation.
+     */
+    public String toString() {
+        if(this==EMPTY)
+            return "";
+        else {
+            return prev.toString()+"\n"+last.toString();
+        }
+    }
+}

Propchange: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ExecutionPath.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ExecutionPath.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ExecutionPath.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ExecutionVisitor.java
URL: http://svn.apache.org/viewvc/commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ExecutionVisitor.java?rev=733503&view=auto
==============================================================================
--- commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ExecutionVisitor.java (added)
+++ commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ExecutionVisitor.java Sun Jan 11 11:51:40 2009
@@ -0,0 +1,1091 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.javaflow.bytecode.transformation.bcel.analyser;
+
+import org.apache.bcel.Constants;
+import org.apache.bcel.classfile.Constant;
+import org.apache.bcel.classfile.ConstantDouble;
+import org.apache.bcel.classfile.ConstantFloat;
+import org.apache.bcel.classfile.ConstantInteger;
+import org.apache.bcel.classfile.ConstantLong;
+import org.apache.bcel.classfile.ConstantString;
+import org.apache.bcel.classfile.ConstantClass;
+import org.apache.bcel.generic.*;
+
+/**
+ * This Visitor class may be used for a type-based Java Virtual Machine
+ * simulation.
+ * It does not check for correct types on the OperandStack or in the
+ * LocalVariables; nor does it check their sizes are sufficiently big.
+ * Thus, to use this Visitor for bytecode verifying, you have to make sure
+ * externally that the type constraints of the Java Virtual Machine instructions
+ * are satisfied. An InstConstraintVisitor may be used for this.
+ * Anyway, this Visitor does not mandate it. For example, when you
+ * visitIADD(IADD o), then there are two stack slots popped and one
+ * stack slot containing a Type.INT is pushed (where you could also
+ * pop only one slot if you know there are two Type.INT on top of the
+ * stack). Monitor-specific behaviour is not simulated.
+ * 
+ * </P><B>Conventions:</B>
+ *
+ * Type.VOID will never be pushed onto the stack. Type.DOUBLE and Type.LONG
+ * that would normally take up two stack slots (like Double_HIGH and
+ * Double_LOW) are represented by a simple single Type.DOUBLE or Type.LONG
+ * object on the stack here.
+ * If a two-slot type is stored into a local variable, the next variable
+ * is given the type Type.UNKNOWN.
+ * 
+ * WARNING! These classes are a fork of the bcel verifier.
+ *
+ * @version $Id$
+ * @author <A HREF="http://www.inf.fu-berlin.de/~ehaase"/>Enver Haase</A>
+ * @see #visitDSTORE(DSTORE o)
+ * @see org.apache.bcel.verifier.structurals.InstConstraintVisitor
+ */
+public class ExecutionVisitor extends EmptyVisitor implements Visitor{
+
+	/**
+	 * The executionframe we're operating on.
+	 */
+	private Frame frame = null;
+
+	/**
+	 * The ConstantPoolGen we're working with.
+	 * @see #setConstantPoolGen(ConstantPoolGen)
+	 */
+	private ConstantPoolGen cpg = null;
+
+	/**
+	 * Constructor. Constructs a new instance of this class.
+	 */
+	public ExecutionVisitor(){}
+
+	/**
+	 * The OperandStack from the current Frame we're operating on.
+	 * @see #setFrame(Frame)
+	 */
+	private OperandStack stack(){
+		return frame.getStack();
+	}
+
+	/**
+	 * The LocalVariables from the current Frame we're operating on.
+	 * @see #setFrame(Frame)
+	 */
+	private LocalVariables locals(){
+		return frame.getLocals();
+	}
+
+	/**
+	 * Sets the ConstantPoolGen needed for symbolic execution.
+	 */
+	public void setConstantPoolGen(ConstantPoolGen cpg){
+		this.cpg = cpg;
+	}
+	
+	/**
+	 * The only method granting access to the single instance of
+	 * the ExecutionVisitor class. Before actively using this
+	 * instance, <B>SET THE ConstantPoolGen FIRST</B>.
+	 * @see #setConstantPoolGen(ConstantPoolGen)
+	 */
+	public void setFrame(Frame f){
+		this.frame = f;
+	}
+
+	///** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	//public void visitWIDE(WIDE o){
+	// The WIDE instruction is modelled as a flag
+	// of the embedded instructions in BCEL.
+	// Therefore BCEL checks for possible errors
+	// when parsing in the .class file: We don't
+	// have even the possibilty to care for WIDE
+	// here.
+	//}
+
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitAALOAD(AALOAD o){
+		stack().pop();														// pop the index int
+//System.out.print(stack().peek());
+		Type t = stack().pop(); // Pop Array type
+		if (t == Type.NULL){
+			stack().push(Type.NULL);
+		}	// Do nothing stackwise --- a NullPointerException is thrown at Run-Time
+		else{
+			ArrayType at = (ArrayType) t;	
+			stack().push(at.getElementType());
+		}
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitAASTORE(AASTORE o){
+		stack().pop();
+		stack().pop();
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitACONST_NULL(ACONST_NULL o){
+		stack().push(Type.NULL);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitALOAD(ALOAD o){
+		stack().push(locals().get(o.getIndex()));
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitANEWARRAY(ANEWARRAY o){
+		stack().pop(); //count
+		stack().push( new ArrayType(o.getType(cpg), 1) );
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitARETURN(ARETURN o){
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitARRAYLENGTH(ARRAYLENGTH o){
+		stack().pop();
+		stack().push(Type.INT);
+	}
+
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitASTORE(ASTORE o){
+		locals().set(o.getIndex(), stack().pop());
+		//System.err.println("TODO-DEBUG:	set LV '"+o.getIndex()+"' to '"+locals().get(o.getIndex())+"'.");
+	}
+
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitATHROW(ATHROW o){
+		Type t = stack().pop();
+		stack().clear();
+		if (t.equals(Type.NULL))
+			stack().push(Type.getType("Ljava/lang/NullPointerException;"));
+		else
+			stack().push(t);
+	}
+
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitBALOAD(BALOAD o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.INT);
+	}
+
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitBASTORE(BASTORE o){
+		stack().pop();
+		stack().pop();
+		stack().pop();
+	}
+
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitBIPUSH(BIPUSH o){
+		stack().push(Type.INT);
+	}
+
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitCALOAD(CALOAD o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.INT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitCASTORE(CASTORE o){
+		stack().pop();
+		stack().pop();
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitCHECKCAST(CHECKCAST o){
+		// It's possibly wrong to do so, but SUN's
+		// ByteCode verifier seems to do (only) this, too.
+		// TODO: One could use a sophisticated analysis here to check
+		//       if a type cannot possibly be cated to another and by
+		//       so doing predict the ClassCastException at run-time.
+		stack().pop();
+		stack().push(o.getType(cpg));
+	}
+
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitD2F(D2F o){
+		stack().pop();
+		stack().push(Type.FLOAT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitD2I(D2I o){
+		stack().pop();
+		stack().push(Type.INT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitD2L(D2L o){
+		stack().pop();
+		stack().push(Type.LONG);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitDADD(DADD o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.DOUBLE);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitDALOAD(DALOAD o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.DOUBLE);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitDASTORE(DASTORE o){
+		stack().pop();
+		stack().pop();
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitDCMPG(DCMPG o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.INT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitDCMPL(DCMPL o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.INT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitDCONST(DCONST o){
+		stack().push(Type.DOUBLE);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitDDIV(DDIV o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.DOUBLE);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitDLOAD(DLOAD o){
+		stack().push(Type.DOUBLE);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitDMUL(DMUL o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.DOUBLE);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitDNEG(DNEG o){
+		stack().pop();
+		stack().push(Type.DOUBLE);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitDREM(DREM o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.DOUBLE);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitDRETURN(DRETURN o){
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitDSTORE(DSTORE o){
+		locals().set(o.getIndex(), stack().pop());
+		locals().set(o.getIndex()+1, Type.UNKNOWN);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitDSUB(DSUB o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.DOUBLE);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitDUP(DUP o){
+		Type t = stack().pop();
+		stack().push(t);
+		stack().push(t);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitDUP_X1(DUP_X1 o){
+		Type w1 = stack().pop();
+		Type w2 = stack().pop();
+		stack().push(w1);
+		stack().push(w2);
+		stack().push(w1);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitDUP_X2(DUP_X2 o){
+		Type w1 = stack().pop();
+		Type w2 = stack().pop();
+		if (w2.getSize() == 2){
+			stack().push(w1);
+			stack().push(w2);
+			stack().push(w1);
+		}
+		else{
+			Type w3 = stack().pop();
+			stack().push(w1);
+			stack().push(w3);
+			stack().push(w2);
+			stack().push(w1);
+		}
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitDUP2(DUP2 o){
+		Type t = stack().pop();
+		if (t.getSize() == 2){
+			stack().push(t);
+			stack().push(t);
+		}
+		else{ // t.getSize() is 1
+			Type u = stack().pop();
+			stack().push(u);
+			stack().push(t);
+			stack().push(u);
+			stack().push(t);
+		}
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitDUP2_X1(DUP2_X1 o){
+		Type t = stack().pop();
+		if (t.getSize() == 2){
+			Type u = stack().pop();
+			stack().push(t);
+			stack().push(u);
+			stack().push(t);
+		}
+		else{ //t.getSize() is1
+			Type u = stack().pop();
+			Type v = stack().pop();
+			stack().push(u);
+			stack().push(t);
+			stack().push(v);
+			stack().push(u);
+			stack().push(t);
+		}
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitDUP2_X2(DUP2_X2 o){
+		Type t = stack().pop();
+		if (t.getSize() == 2){
+			Type u = stack().pop();
+			if (u.getSize() == 2){
+				stack().push(t);
+				stack().push(u);
+				stack().push(t);
+			}else{
+				Type v = stack().pop();
+				stack().push(t);
+				stack().push(v);
+				stack().push(u);
+				stack().push(t);
+			}
+		}
+		else{ //t.getSize() is 1
+			Type u = stack().pop();
+			Type v = stack().pop();
+			if (v.getSize() == 2){
+				stack().push(u);
+				stack().push(t);
+				stack().push(v);
+				stack().push(u);
+				stack().push(t);
+			}else{
+				Type w = stack().pop();
+				stack().push(u);
+				stack().push(t);
+				stack().push(w);
+				stack().push(v);
+				stack().push(u);
+				stack().push(t);
+			}
+		}
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitF2D(F2D o){
+		stack().pop();
+		stack().push(Type.DOUBLE);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitF2I(F2I o){
+		stack().pop();
+		stack().push(Type.INT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitF2L(F2L o){
+		stack().pop();
+		stack().push(Type.LONG);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitFADD(FADD o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.FLOAT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitFALOAD(FALOAD o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.FLOAT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitFASTORE(FASTORE o){
+		stack().pop();
+		stack().pop();
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitFCMPG(FCMPG o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.INT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitFCMPL(FCMPL o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.INT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitFCONST(FCONST o){
+		stack().push(Type.FLOAT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitFDIV(FDIV o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.FLOAT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitFLOAD(FLOAD o){
+		stack().push(Type.FLOAT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitFMUL(FMUL o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.FLOAT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitFNEG(FNEG o){
+		stack().pop();
+		stack().push(Type.FLOAT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitFREM(FREM o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.FLOAT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitFRETURN(FRETURN o){
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitFSTORE(FSTORE o){
+		locals().set(o.getIndex(), stack().pop());
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitFSUB(FSUB o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.FLOAT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitGETFIELD(GETFIELD o){
+		stack().pop();
+		Type t = o.getFieldType(cpg);
+		if (	t.equals(Type.BOOLEAN)	||
+					t.equals(Type.CHAR)			||
+					t.equals(Type.BYTE) 		||
+					t.equals(Type.SHORT)		)
+			t = Type.INT;
+		stack().push(t);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitGETSTATIC(GETSTATIC o){
+		Type t = o.getFieldType(cpg);
+		if (	t.equals(Type.BOOLEAN)	||
+					t.equals(Type.CHAR)			||
+					t.equals(Type.BYTE) 		||
+					t.equals(Type.SHORT)		)
+			t = Type.INT;
+		stack().push(t);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitGOTO(GOTO o){
+		// no stack changes.
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitGOTO_W(GOTO_W o){
+		// no stack changes.
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitI2B(I2B o){
+		stack().pop();
+		stack().push(Type.INT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitI2C(I2C o){
+		stack().pop();
+		stack().push(Type.INT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitI2D(I2D o){
+		stack().pop();
+		stack().push(Type.DOUBLE);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitI2F(I2F o){
+		stack().pop();
+		stack().push(Type.FLOAT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitI2L(I2L o){
+		stack().pop();
+		stack().push(Type.LONG);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitI2S(I2S o){
+		stack().pop();
+		stack().push(Type.INT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitIADD(IADD o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.INT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitIALOAD(IALOAD o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.INT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitIAND(IAND o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.INT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitIASTORE(IASTORE o){
+		stack().pop();
+		stack().pop();
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitICONST(ICONST o){
+		stack().push(Type.INT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitIDIV(IDIV o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.INT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitIF_ACMPEQ(IF_ACMPEQ o){
+		stack().pop();
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitIF_ACMPNE(IF_ACMPNE o){
+		stack().pop();
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitIF_ICMPEQ(IF_ICMPEQ o){
+		stack().pop();
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitIF_ICMPGE(IF_ICMPGE o){
+		stack().pop();
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitIF_ICMPGT(IF_ICMPGT o){
+		stack().pop();
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitIF_ICMPLE(IF_ICMPLE o){
+		stack().pop();
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitIF_ICMPLT(IF_ICMPLT o){
+		stack().pop();
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitIF_ICMPNE(IF_ICMPNE o){
+		stack().pop();
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitIFEQ(IFEQ o){
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitIFGE(IFGE o){
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitIFGT(IFGT o){
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitIFLE(IFLE o){
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitIFLT(IFLT o){
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitIFNE(IFNE o){
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitIFNONNULL(IFNONNULL o){
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitIFNULL(IFNULL o){
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitIINC(IINC o){
+		// stack is not changed.
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitILOAD(ILOAD o){
+		stack().push(Type.INT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitIMUL(IMUL o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.INT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitINEG(INEG o){
+		stack().pop();
+		stack().push(Type.INT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitINSTANCEOF(INSTANCEOF o){
+		stack().pop();
+		stack().push(Type.INT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitINVOKEINTERFACE(INVOKEINTERFACE o){
+		stack().pop();	//objectref
+		for (int i=0; i<o.getArgumentTypes(cpg).length; i++){
+			stack().pop();
+		}
+		// We are sure the invoked method will xRETURN eventually
+		// We simulate xRETURNs functionality here because we
+		// don't really "jump into" and simulate the invoked
+		// method.
+		if (o.getReturnType(cpg) != Type.VOID){
+			Type t = o.getReturnType(cpg);
+			if (	t.equals(Type.BOOLEAN)	||
+						t.equals(Type.CHAR)			||
+						t.equals(Type.BYTE) 		||
+						t.equals(Type.SHORT)		)
+				t = Type.INT;
+			stack().push(t);
+		}
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitINVOKESPECIAL(INVOKESPECIAL o){
+		if (o.getMethodName(cpg).equals(Constants.CONSTRUCTOR_NAME)){
+			UninitializedObjectType t = (UninitializedObjectType) stack().peek(o.getArgumentTypes(cpg).length);
+			if (t == Frame._this){	
+				Frame._this = null;
+			}
+			stack().initializeObject(t);
+			locals().initializeObject(t);
+		}
+		stack().pop();	//objectref
+		for (int i=0; i<o.getArgumentTypes(cpg).length; i++){
+			stack().pop();
+		}
+		// We are sure the invoked method will xRETURN eventually
+		// We simulate xRETURNs functionality here because we
+		// don't really "jump into" and simulate the invoked
+		// method.
+		if (o.getReturnType(cpg) != Type.VOID){
+			Type t = o.getReturnType(cpg);
+			if (	t.equals(Type.BOOLEAN)	||
+						t.equals(Type.CHAR)			||
+						t.equals(Type.BYTE) 		||
+						t.equals(Type.SHORT)		)
+				t = Type.INT;
+			stack().push(t);
+		}
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitINVOKESTATIC(INVOKESTATIC o){
+		for (int i=0; i<o.getArgumentTypes(cpg).length; i++){
+			stack().pop();
+		}
+		// We are sure the invoked method will xRETURN eventually
+		// We simulate xRETURNs functionality here because we
+		// don't really "jump into" and simulate the invoked
+		// method.
+		if (o.getReturnType(cpg) != Type.VOID){
+			Type t = o.getReturnType(cpg);
+			if (	t.equals(Type.BOOLEAN)	||
+						t.equals(Type.CHAR)			||
+						t.equals(Type.BYTE) 		||
+						t.equals(Type.SHORT)		)
+				t = Type.INT;
+			stack().push(t);
+		}
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitINVOKEVIRTUAL(INVOKEVIRTUAL o){
+		stack().pop(); //objectref
+		for (int i=0; i<o.getArgumentTypes(cpg).length; i++){
+			stack().pop();
+		}
+		// We are sure the invoked method will xRETURN eventually
+		// We simulate xRETURNs functionality here because we
+		// don't really "jump into" and simulate the invoked
+		// method.
+		if (o.getReturnType(cpg) != Type.VOID){
+			Type t = o.getReturnType(cpg);
+			if (	t.equals(Type.BOOLEAN)	||
+						t.equals(Type.CHAR)			||
+						t.equals(Type.BYTE) 		||
+						t.equals(Type.SHORT)		)
+				t = Type.INT;
+			stack().push(t);
+		}
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitIOR(IOR o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.INT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitIREM(IREM o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.INT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitIRETURN(IRETURN o){
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitISHL(ISHL o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.INT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitISHR(ISHR o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.INT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitISTORE(ISTORE o){
+		locals().set(o.getIndex(), stack().pop());
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitISUB(ISUB o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.INT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitIUSHR(IUSHR o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.INT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitIXOR(IXOR o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.INT);
+	}
+
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitJSR(JSR o){
+		stack().push(new ReturnaddressType(o.physicalSuccessor()));
+//System.err.println("TODO-----------:"+o.physicalSuccessor());
+	}
+
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitJSR_W(JSR_W o){
+		stack().push(new ReturnaddressType(o.physicalSuccessor()));
+	}
+
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitL2D(L2D o){
+		stack().pop();
+		stack().push(Type.DOUBLE);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitL2F(L2F o){
+		stack().pop();
+		stack().push(Type.FLOAT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitL2I(L2I o){
+		stack().pop();
+		stack().push(Type.INT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitLADD(LADD o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.LONG);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitLALOAD(LALOAD o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.LONG);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitLAND(LAND o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.LONG);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitLASTORE(LASTORE o){
+		stack().pop();
+		stack().pop();
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitLCMP(LCMP o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.INT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitLCONST(LCONST o){
+		stack().push(Type.LONG);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitLDC(LDC o){
+		Constant c = cpg.getConstant(o.getIndex());
+		if (c instanceof ConstantInteger){
+			stack().push(Type.INT);
+		}
+		if (c instanceof ConstantFloat){
+			stack().push(Type.FLOAT);
+		}
+		if (c instanceof ConstantString){
+			stack().push(Type.STRING);
+		}
+        if (c instanceof ConstantClass) {
+            stack().push(new ObjectType("java.lang.Class"));
+        }
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitLDC_W(LDC_W o){
+		Constant c = cpg.getConstant(o.getIndex());
+		if (c instanceof ConstantInteger){
+			stack().push(Type.INT);
+		}
+		if (c instanceof ConstantFloat){
+			stack().push(Type.FLOAT);
+		}
+		if (c instanceof ConstantString){
+			stack().push(Type.STRING);
+		}
+        if (c instanceof ConstantClass) {
+            stack().push(new ObjectType("java.lang.Class"));
+        }
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitLDC2_W(LDC2_W o){
+		Constant c = cpg.getConstant(o.getIndex());
+		if (c instanceof ConstantLong){
+			stack().push(Type.LONG);
+		}
+		if (c instanceof ConstantDouble){
+			stack().push(Type.DOUBLE);
+		}
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitLDIV(LDIV o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.LONG);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitLLOAD(LLOAD o){
+		stack().push(locals().get(o.getIndex()));
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitLMUL(LMUL o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.LONG);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitLNEG(LNEG o){
+		stack().pop();
+		stack().push(Type.LONG);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitLOOKUPSWITCH(LOOKUPSWITCH o){
+		stack().pop(); //key
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitLOR(LOR o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.LONG);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitLREM(LREM o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.LONG);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitLRETURN(LRETURN o){
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitLSHL(LSHL o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.LONG);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitLSHR(LSHR o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.LONG);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitLSTORE(LSTORE o){
+		locals().set(o.getIndex(), stack().pop());
+		locals().set(o.getIndex()+1, Type.UNKNOWN);		
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitLSUB(LSUB o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.LONG);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitLUSHR(LUSHR o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.LONG);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitLXOR(LXOR o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.LONG);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitMONITORENTER(MONITORENTER o){
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitMONITOREXIT(MONITOREXIT o){
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitMULTIANEWARRAY(MULTIANEWARRAY o){
+		for (int i=0; i<o.getDimensions(); i++){
+			stack().pop();
+		}
+		stack().push(o.getType(cpg));
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitNEW(NEW o){
+		stack().push(new UninitializedObjectType((ObjectType) (o.getType(cpg))));
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitNEWARRAY(NEWARRAY o){
+		stack().pop();
+		stack().push(o.getType());
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitNOP(NOP o){
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitPOP(POP o){
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitPOP2(POP2 o){
+		Type t = stack().pop();
+		if (t.getSize() == 1){
+			stack().pop();
+		}		
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitPUTFIELD(PUTFIELD o){
+		stack().pop();
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitPUTSTATIC(PUTSTATIC o){
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitRET(RET o){
+		// do nothing, return address
+		// is in in the local variables.
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitRETURN(RETURN o){
+		// do nothing.
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitSALOAD(SALOAD o){
+		stack().pop();
+		stack().pop();
+		stack().push(Type.INT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitSASTORE(SASTORE o){
+		stack().pop();
+		stack().pop();
+		stack().pop();
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitSIPUSH(SIPUSH o){
+		stack().push(Type.INT);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitSWAP(SWAP o){
+		Type t = stack().pop();
+		Type u = stack().pop();
+		stack().push(t);
+		stack().push(u);
+	}
+	/** Symbolically executes the corresponding Java Virtual Machine instruction. */ 
+	public void visitTABLESWITCH(TABLESWITCH o){
+		stack().pop();
+	}
+}

Propchange: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ExecutionVisitor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ExecutionVisitor.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/ExecutionVisitor.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/Frame.java
URL: http://svn.apache.org/viewvc/commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/Frame.java?rev=733503&view=auto
==============================================================================
--- commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/Frame.java (added)
+++ commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/Frame.java Sun Jan 11 11:51:40 2009
@@ -0,0 +1,180 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.javaflow.bytecode.transformation.bcel.analyser;
+
+import org.apache.bcel.generic.Type;
+import org.apache.bcel.generic.ReferenceType;
+import org.apache.bcel.generic.ReturnaddressType;
+import org.apache.bcel.verifier.exc.StructuralCodeConstraintException;
+import org.apache.bcel.verifier.exc.AssertionViolatedException;
+
+/**
+ * This class represents a JVM execution frame; that means,
+ * a local variable array and an operand stack.
+ * 
+ * WARNING! These classes are a fork of the bcel verifier.
+ *
+ * @version $Id$
+ * @author <A HREF="http://www.inf.fu-berlin.de/~ehaase"/>Enver Haase</A>
+ */
+
+public class Frame{
+
+    /**
+     * For instance initialization methods, it is important to remember
+     * which instance it is that is not initialized yet. It will be
+     * initialized invoking another constructor later.
+     * NULL means the instance already *is* initialized.
+     */
+    public static UninitializedObjectType _this;
+
+    /**
+     *
+     */
+    private LocalVariables locals;
+
+    /**
+     *
+     */
+    private OperandStack stack;
+
+    /**
+     *
+     */
+    public Frame(int maxLocals, int maxStack){
+        locals = new LocalVariables(maxLocals);
+        stack = new OperandStack(maxStack);
+    }
+
+    /**
+     *
+     */
+    public Frame(LocalVariables locals, OperandStack stack){
+        this.locals = locals;
+        this.stack = stack;
+    }
+
+    /**
+     *
+     */
+    protected Object clone(){
+        Frame f = new Frame(locals.getClone(), stack.getClone());
+        return f;
+    }
+
+    /**
+     *
+     */
+    public Frame getClone(){
+        return (Frame) clone();
+    }
+
+    /**
+     *
+     */
+    public LocalVariables getLocals(){
+        return locals;
+    }
+
+    /**
+     *
+     */
+    public OperandStack getStack(){
+        return stack;
+    }
+
+    /**
+     *
+     */
+    public boolean equals(Object o){
+        if (!(o instanceof Frame)) return false; // implies "null" is non-equal.
+        Frame f = (Frame) o;
+        return this.stack.equals(f.stack) && this.locals.equals(f.locals);
+    }
+
+    /**
+     * Returns a String representation of the Frame instance.
+     */
+    public String toString(){
+        String s="Local Variables:\n";
+        s += locals;
+        s += "OperandStack:\n";
+        s += stack;
+        return s;
+    }
+
+
+    /**
+     * Merges two {@link Type}s into one.
+     *
+     * @param errorIfFailed
+     *      if true, attempting to merge two types that are incompatible causes an error.
+     *      if false, it yields {@link Type#UNKNOWN} value, indicating that value is unusable.
+     */
+    /*package*/ static Type merge(Type lhs, Type rhs, boolean errorIfFailed) {
+        try {
+
+            // We won't accept an unitialized object if we know it was initialized;
+            // compare vmspec2, 4.9.4, last paragraph.
+            if ((!(lhs instanceof UninitializedObjectType)) && (rhs instanceof UninitializedObjectType)) {
+                throw new StructuralCodeConstraintException("Backwards branch with an uninitialized object in the local variables detected.");
+            }
+            // Even harder, what about _different_ uninitialized object types?!
+            if ((!(lhs.equals(rhs))) && (lhs instanceof UninitializedObjectType) && (rhs instanceof UninitializedObjectType)) {
+                throw new StructuralCodeConstraintException("Backwards branch with an uninitialized object in the local variables detected.");
+            }
+            // If we just didn't know that it was initialized, we have now learned.
+            if (lhs instanceof UninitializedObjectType) {
+                if (! (rhs instanceof UninitializedObjectType)) {
+                    lhs = ((UninitializedObjectType) lhs).getInitialized();
+                }
+            }
+            if ((lhs instanceof ReferenceType) && (rhs instanceof ReferenceType)) {
+                if(lhs.equals(rhs)) {
+                    return lhs; // same type
+                }
+
+                Type sup = ((ReferenceType) lhs).getFirstCommonSuperclass((ReferenceType) rhs);
+
+                if (sup != null) {
+                    return sup;
+                } else {
+                    // We should have checked this in Pass2!
+                    throw new AssertionViolatedException("Could not load all the super classes of '" + lhs + "' and '" + rhs + "'.");
+                }
+            }
+
+            if ((lhs instanceof ReturnaddressType) && (rhs instanceof ReturnaddressType)) {
+                // see 'FinallyFlow' test.
+                return lhs;
+            }
+
+            if (!lhs.equals(rhs)) {
+                if(errorIfFailed) {
+                    throw new StructuralCodeConstraintException("Cannot merge different types:"+lhs+" and "+rhs);
+                } else {
+                    return Type.UNKNOWN;
+                }
+            }
+
+            return lhs;
+        } catch (ClassNotFoundException e) {
+            // FIXME: maybe not the best way to handle this
+            throw new AssertionViolatedException("Missing class: " + e.toString());
+        }
+    }
+}

Propchange: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/Frame.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/Frame.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/Frame.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/InstructionContext.java
URL: http://svn.apache.org/viewvc/commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/InstructionContext.java?rev=733503&view=auto
==============================================================================
--- commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/InstructionContext.java (added)
+++ commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/InstructionContext.java Sun Jan 11 11:51:40 2009
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.javaflow.bytecode.transformation.bcel.analyser;
+
+import java.util.ArrayList;
+
+import org.apache.bcel.generic.InstructionHandle;
+
+/**
+ * An InstructionContext offers convenient access
+ * to information like control flow successors and
+ * such.
+ *
+ * @version $Id$
+ * @author <A HREF="http://www.inf.fu-berlin.de/~ehaase"/>Enver Haase</A>
+ */
+public interface InstructionContext{
+
+	/**
+	 * This method symbolically executes the Instruction
+	 * held in the InstructionContext.
+	 * It "merges in" the incoming execution frame situation
+	 * (see The Java Virtual Machine Specification, 2nd
+	 * edition, page 146).
+	 * By so doing, the outgoing execution frame situation
+	 * is calculated.
+	 *
+	 * This method is JustIce-specific and is usually of
+	 * no sense for users of the ControlFlowGraph class.
+	 * They should use getInstruction().accept(Visitor),
+	 * possibly in conjunction with the ExecutionVisitor.
+	 * 
+	 * WARNING! These classes are a fork of the bcel verifier.
+	 *
+	 * @see ControlFlowGraph
+	 * @see ExecutionVisitor
+	 * @see #getOutFrame(ArrayList)
+	 * @return true -  if and only if the "outgoing" frame situation
+	 * changed from the one before execute()ing.
+	 */
+	boolean execute(Frame inFrame, ExecutionPath executionPredecessors, ExecutionVisitor ev);
+
+	Frame getInFrame();
+
+	/**
+	 * This method returns the outgoing execution frame situation;
+	 * therefore <B>it has to be calculated by execute(Frame, ArrayList)
+	 * first.</B>
+	 *
+	 * @see #execute(Frame, ExecutionPath, ExecutionVisitor)
+	 */
+	Frame getOutFrame(ExecutionPath executionPredecessors);
+	
+	/**
+	 * Returns the InstructionHandle this InstructionContext is wrapped around.
+	 *
+	 * @return The InstructionHandle this InstructionContext is wrapped around.
+	 */
+	InstructionHandle getInstruction();
+
+	/**
+	 * Returns the usual control flow successors.
+	 * @see #getExceptionHandlers()
+	 */
+	InstructionContext[] getSuccessors();
+
+	/**
+	 * Returns the exception handlers that protect this instruction.
+	 * They are special control flow successors.
+	 */
+	ExceptionHandler[] getExceptionHandlers();
+}

Propchange: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/InstructionContext.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/InstructionContext.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/InstructionContext.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/LocalVariables.java
URL: http://svn.apache.org/viewvc/commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/LocalVariables.java?rev=733503&view=auto
==============================================================================
--- commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/LocalVariables.java (added)
+++ commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/LocalVariables.java Sun Jan 11 11:51:40 2009
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.javaflow.bytecode.transformation.bcel.analyser;
+
+import org.apache.bcel.generic.Type;
+import org.apache.bcel.verifier.exc.AssertionViolatedException;
+
+import java.util.Arrays;
+
+/**
+ * This class implements an array of local variables used for symbolic JVM
+ * simulation.
+ * 
+ * WARNING! These classes are a fork of the bcel verifier.
+ *
+ * @version $Id$
+ * @author <A HREF="http://www.inf.fu-berlin.de/~ehaase"/>Enver Haase</A>
+ */
+public class LocalVariables{
+    /** The Type[] containing the local variable slots. */
+    private Type[] locals;
+
+    /**
+     * Creates a new LocalVariables object.
+     */
+    public LocalVariables(int maxLocals){
+        locals = new Type[maxLocals];
+        Arrays.fill(locals,Type.UNKNOWN);
+    }
+
+    /**
+     * Returns a deep copy of this object; i.e. the clone
+     * operates on a new local variable array.
+     * However, the Type objects in the array are shared.
+     */
+    protected Object clone(){
+        LocalVariables lvs = new LocalVariables(locals.length);
+        System.arraycopy(this.locals, 0, lvs.locals, 0, locals.length);
+        return lvs;
+    }
+
+    /**
+     * Returns the type of the local variable slot i.
+     */
+    public Type get(int i){
+        return locals[i];
+    }
+
+    /**
+     * Returns a (correctly typed) clone of this object.
+     * This is equivalent to ((LocalVariables) this.clone()).
+     */
+    public LocalVariables getClone(){
+        return (LocalVariables) this.clone();
+    }
+
+    /**
+     * Returns the number of local variable slots this
+     * LocalVariables instance has.
+     */
+    public int maxLocals(){
+        return locals.length;
+    }
+
+    /**
+     * Sets a new Type for the given local variable slot.
+     */
+    public void set(int i, Type type){
+        if (type == Type.BYTE || type == Type.SHORT || type == Type.BOOLEAN || type == Type.CHAR){
+            throw new AssertionViolatedException("LocalVariables do not know about '"+type+"'. Use Type.INT instead.");
+        }
+        locals[i] = type;
+    }
+
+    /*
+      * Fulfills the general contract of Object.equals().
+      */
+    public boolean equals(Object o){
+        if (!(o instanceof LocalVariables)) return false;
+        LocalVariables lv = (LocalVariables) o;
+        return Arrays.equals(this.locals, lv.locals);
+    }
+
+    /**
+     * Merges two local variables sets as described in the Java Virtual Machine Specification,
+     * Second Edition, section 4.9.2, page 146.
+     */
+    public void merge(LocalVariables that){
+
+        if (this.locals.length != that.locals.length){
+            throw new AssertionViolatedException("Merging LocalVariables of different size?!? From different methods or what?!?");
+        }
+
+        for (int i=0; i<locals.length; i++) {
+            this.locals[i] = Frame.merge(this.locals[i], that.locals[i], false);
+        }
+    }
+
+
+    /**
+     * Returns a String representation of this object.
+     */
+    public String toString(){
+        String s = "";
+        for (int i=0; i<locals.length; i++){
+            s += Integer.toString(i)+": "+locals[i]+"\n";
+        }
+        return s;
+    }
+
+    /**
+     * Replaces all occurences of u in this local variables set
+     * with an "initialized" ObjectType.
+     */
+    public void initializeObject(UninitializedObjectType u){
+        for (int i=0; i<locals.length; i++){
+            if (locals[i] == u){
+                locals[i] = u.getInitialized();
+            }
+        }
+    }
+}

Propchange: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/LocalVariables.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/LocalVariables.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/LocalVariables.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/OperandStack.java
URL: http://svn.apache.org/viewvc/commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/OperandStack.java?rev=733503&view=auto
==============================================================================
--- commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/OperandStack.java (added)
+++ commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/OperandStack.java Sun Jan 11 11:51:40 2009
@@ -0,0 +1,215 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.javaflow.bytecode.transformation.bcel.analyser;
+
+import org.apache.bcel.generic.*;
+import org.apache.bcel.verifier.exc.*;
+import java.util.*;
+
+/**
+ * This class implements a stack used for symbolic JVM stack simulation.
+ * [It's used an an operand stack substitute.]
+ * Elements of this stack are org.apache.bcel.generic.Type objects.
+ * 
+ * WARNING! These classes are a fork of the bcel verifier.
+ *
+ * @version $Id$
+ * @author <A HREF="http://www.inf.fu-berlin.de/~ehaase"/>Enver Haase</A>
+ */
+public class OperandStack{
+
+	/** We hold the stack information here. */
+	private ArrayList stack = new ArrayList();
+
+	/** The maximum number of stack slots this OperandStack instance may hold. */
+	private int maxStack;
+
+	/**
+	 * Creates an empty stack with a maximum of maxStack slots.
+	 */
+	public OperandStack(int maxStack){
+		this.maxStack = maxStack;
+	}
+
+	/**
+	 * Creates an otherwise empty stack with a maximum of maxStack slots and
+	 * the ObjectType 'obj' at the top.
+	 */
+	public OperandStack(int maxStack, ObjectType obj){
+		this.maxStack = maxStack;
+		this.push(obj);
+	}	
+	/**
+	 * Returns a deep copy of this object; that means, the clone operates
+	 * on a new stack. However, the Type objects on the stack are
+	 * shared.
+	 */
+	protected Object clone(){
+		OperandStack newstack = new OperandStack(this.maxStack);
+		newstack.stack = (ArrayList) this.stack.clone();
+		return newstack;
+	}
+
+	/**
+	 * Clears the stack.
+	 */
+	public void clear(){
+		stack = new ArrayList();
+	}
+
+	/**
+	 * Returns true if and only if this OperandStack
+	 * equals another, meaning equal lengths and equal
+	 * objects on the stacks.
+	 */
+	public boolean equals(Object o){
+		if (!(o instanceof OperandStack)) return false;
+		OperandStack s = (OperandStack) o;
+		return this.stack.equals(s.stack);
+	}
+
+	/**
+	 * Returns a (typed!) clone of this.
+	 *
+	 * @see #clone()
+	 */
+	public OperandStack getClone(){
+		return (OperandStack) this.clone();
+	}
+
+	/**
+	 * Returns true IFF this OperandStack is empty.
+   */
+	public boolean isEmpty(){
+		return stack.isEmpty();
+	}
+
+	/**
+	 * Returns the number of stack slots this stack can hold.
+	 */
+	public int maxStack(){
+		return this.maxStack;
+	}
+
+	/**
+	 * Returns the element on top of the stack. The element is not popped off the stack!
+	 */
+	public Type peek(){
+		return peek(0);
+	}
+
+	/**
+   * Returns the element that's i elements below the top element; that means,
+   * iff i==0 the top element is returned. The element is not popped off the stack!
+   */
+	public Type peek(int i){
+		return (Type) stack.get(size()-i-1);
+	}
+
+	/**
+	 * Returns the element on top of the stack. The element is popped off the stack.
+	 */
+	public Type pop(){
+		Type e = (Type) stack.remove(size()-1);
+		return e;
+	}
+
+	/**
+	 * Pops i elements off the stack. ALWAYS RETURNS "null"!!!
+	 */
+	public Type pop(int i){
+		for (int j=0; j<i; j++){
+			pop();
+		}
+		return null;
+	}
+
+	/**
+	 * Pushes a Type object onto the stack.
+	 */
+	public void push(Type type){
+		if (type == null) throw new AssertionViolatedException("Cannot push NULL onto OperandStack.");
+		if (type == Type.BOOLEAN || type == Type.CHAR || type == Type.BYTE || type == Type.SHORT){
+			throw new AssertionViolatedException("The OperandStack does not know about '"+type+"'; use Type.INT instead.");
+		}
+		if (slotsUsed() >= maxStack){
+			throw new AssertionViolatedException("OperandStack too small, should have thrown proper Exception elsewhere. Stack: "+this);
+		}
+		stack.add(type);
+	}
+
+	/**
+	 * Returns the size of this OperandStack; that means, how many Type objects there are.
+	 */
+	public int size(){
+		return stack.size();
+	}
+
+	/**
+	 * Returns the number of stack slots used.
+	 * @see #maxStack()
+	 */	
+	public int slotsUsed(){
+		/*  XXX change this to a better implementation using a variable
+		    that keeps track of the actual slotsUsed()-value monitoring
+		    all push()es and pop()s.
+		*/
+		int slots = 0;
+		for (int i=0; i<stack.size(); i++){
+			slots += peek(i).getSize();
+		}
+		return slots;
+	}
+	
+	/**
+	 * Returns a String representation of this OperandStack instance.
+	 */
+	public String toString(){
+		String s = "Slots used: "+slotsUsed()+" MaxStack: "+maxStack+".\n";
+		for (int i=0; i<size(); i++){
+			s+=peek(i)+" (Size: "+peek(i).getSize()+")\n";
+		}
+		return s;
+	}
+
+	/**
+	 * Merges another stack state into this instance's stack state.
+	 * See the Java Virtual Machine Specification, Second Edition, page 146: 4.9.2
+	 * for details.
+	 */
+	public void merge(OperandStack s){
+		if ( (slotsUsed() != s.slotsUsed()) || (size() != s.size()) )
+			throw new StructuralCodeConstraintException("Cannot merge stacks of different size:\nOperandStack A:\n"+this+"\nOperandStack B:\n"+s);
+		
+		for (int i=0; i<size(); i++){
+            this.stack.set(i, Frame.merge((Type)this.stack.get(i), (Type)s.stack.get(i), true));
+		}
+	}
+
+	/**
+	 * Replaces all occurences of u in this OperandStack instance
+	 * with an "initialized" ObjectType.
+	 */
+	public void initializeObject(UninitializedObjectType u){
+		for (int i=0; i<stack.size(); i++){
+            if (stack.get(i) == u){
+				stack.set(i, u.getInitialized());
+			}
+		}
+	}
+
+}