FileDocCategorySizeDatePackage
OperandStack.javaAPI DocJava SE 5 API9245Fri Aug 26 14:55:26 BST 2005com.sun.org.apache.bcel.internal.verifier.structurals

OperandStack

public class OperandStack extends Object
This class implements a stack used for symbolic JVM stack simulation. [It's used an an operand stack substitute.] Elements of this stack are com.sun.org.apache.bcel.internal.generic.Type objects.
version
$Id: OperandStack.java,v 1.1.1.1 2001/10/29 20:00:41 jvanzyl Exp $
author
Enver Haase

Fields Summary
private ArrayList
stack
We hold the stack information here.
private int
maxStack
The maximum number of stack slots this OperandStack instance may hold.
Constructors Summary
public OperandStack(int maxStack)
Creates an empty stack with a maximum of maxStack slots.


	          	 
	  
		this.maxStack = maxStack;
	
public OperandStack(int maxStack, ObjectType obj)
Creates an otherwise empty stack with a maximum of maxStack slots and the ObjectType 'obj' at the top.

		this.maxStack = maxStack;
		this.push(obj);
	
Methods Summary
public voidclear()
Clears the stack.

		stack = new ArrayList();
	
protected java.lang.Objectclone()
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.

		OperandStack newstack = new OperandStack(this.maxStack);
		newstack.stack = (ArrayList) this.stack.clone();
		return newstack;
	
public booleanequals(java.lang.Object o)
Returns true if and only if this OperandStack equals another, meaning equal lengths and equal objects on the stacks.

		if (!(o instanceof OperandStack)) return false;
		OperandStack s = (OperandStack) o;
		return this.stack.equals(s.stack);
	
public com.sun.org.apache.bcel.internal.verifier.structurals.OperandStackgetClone()
Returns a (typed!) clone of this.

see
#clone()

		return (OperandStack) this.clone();
	
public voidinitializeObject(UninitializedObjectType u)
Replaces all occurences of u in this OperandStack instance with an "initialized" ObjectType.

		for (int i=0; i<stack.size(); i++){
			if (stack.get(i) == u){
				stack.set(i, u.getInitialized());
			}
		}
	
public booleanisEmpty()
Returns true IFF this OperandStack is empty.

		return stack.isEmpty();
	
public intmaxStack()
Returns the number of stack slots this stack can hold.

		return this.maxStack;
	
public voidmerge(com.sun.org.apache.bcel.internal.verifier.structurals.OperandStack 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.

		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++){
			// If the object _was_ initialized and we're supposed to merge
			// in some uninitialized object, we reject the code (see vmspec2, 4.9.4, last paragraph).
			if ( (! (stack.get(i) instanceof UninitializedObjectType)) && (s.stack.get(i) instanceof UninitializedObjectType) ){
				throw new StructuralCodeConstraintException("Backwards branch with an uninitialized object on the stack detected.");
			}
			// Even harder, we're not initialized but are supposed to broaden
			// the known object type
			if ( (!(stack.get(i).equals(s.stack.get(i)))) && (stack.get(i) instanceof UninitializedObjectType) && (!(s.stack.get(i) instanceof UninitializedObjectType))){
				throw new StructuralCodeConstraintException("Backwards branch with an uninitialized object on the stack detected.");
			}
			// on the other hand...
			if (stack.get(i) instanceof UninitializedObjectType){ //if we have an uninitialized object here
				if (! (s.stack.get(i) instanceof UninitializedObjectType)){ //that has been initialized by now
					stack.set(i, ((UninitializedObjectType) (stack.get(i))).getInitialized() ); //note that.
				}
			}
			if (! stack.get(i).equals(s.stack.get(i))){
				if (	(stack.get(i) instanceof ReferenceType) &&
							(s.stack.get(i) instanceof ReferenceType)  ){
					stack.set(i, ((ReferenceType) stack.get(i)).firstCommonSuperclass((ReferenceType) (s.stack.get(i))));
				}
				else{
					throw new StructuralCodeConstraintException("Cannot merge stacks of different types:\nStack A:\n"+this+"\nStack B:\n"+s);
				}
			}
		}
	
public com.sun.org.apache.bcel.internal.generic.Typepeek(int i)
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!

		return (Type) stack.get(size()-i-1);
	
public com.sun.org.apache.bcel.internal.generic.Typepeek()
Returns the element on top of the stack. The element is not popped off the stack!

		return peek(0);
	
public com.sun.org.apache.bcel.internal.generic.Typepop()
Returns the element on top of the stack. The element is popped off the stack.

		Type e = (Type) stack.remove(size()-1);
		return e;
	
public com.sun.org.apache.bcel.internal.generic.Typepop(int i)
Pops i elements off the stack. ALWAYS RETURNS "null"!!!

		for (int j=0; j<i; j++){
			pop();
		}
		return null;
	
public voidpush(com.sun.org.apache.bcel.internal.generic.Type type)
Pushes a Type object onto the stack.

		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);
	
intsize()
Returns the size of this OperandStack; that means, how many Type objects there are.

		return stack.size();
	
public intslotsUsed()
Returns the number of stack slots used.

see
#maxStack()

		/*  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;
	
public java.lang.StringtoString()
Returns a String representation of this OperandStack instance.

		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;