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