com.markcrocker.purifier
Class OperandStack

java.lang.Object
  |
  +--com.markcrocker.purifier.OperandStack

public class OperandStack
extends java.lang.Object

This class implements a stack used that is used for StackMap generation. Data is stored as StackMapTypes, which is not entirely consistent with a real JVM operand stack because some StackMapType entries represent two storage words. Consequently, several methods are designed to with this in mind.

Author:
Enver Haase, Mark Crocker

Field Summary
private static org.apache.log4j.Logger log
           
private  int maxStack
          The maximum number of stack slots this OperandStack instance may hold.
private  java.util.ArrayList stack
          We hold the StackMapTypes here.
 
Constructor Summary
OperandStack(int maxStack)
          Creates an empty stack with a maximum of maxStack slots.
OperandStack(int maxStack, org.apache.bcel.classfile.StackMapType stackMapType)
          Creates an otherwise empty stack with a maximum of maxStack slots and the StackMapType 'stackMaptype' object at the top.
 
Method Summary
 void clear()
          Clears the stack.
protected  java.lang.Object clone()
          Returns a deep copy of this object.
 boolean equals(java.lang.Object o)
          Returns true if and only if this OperandStack equals another, meaning equal lengths and equal objects on the stacks.
 OperandStack getClone()
          Returns a correctly typed clone of this object.
 int getMaxStack()
          Returns the number of stack slots this stack can hold.
(package private)  int getSimulatedJVMsize()
          Returns the simulated size of the JVM operand stack that this OperandStack object represents; that means, how many words would be on the operand stack of the real JVM.
 int getSize()
          Returns the size of this OperandStack; that means, how many StackMapType objects there are.
 org.apache.bcel.classfile.StackMapType[] getStackItems()
          Converts OperandStack StackMapTypes.
private  void indent(java.lang.StringBuffer sb, java.lang.String indentString, int indentLevel)
           
 boolean isEmpty()
          Returns true IFF this OperandStack is empty.
 void merge(OperandStack challenger)
          Merges two OperandStacks according to JVM Specification 4.9.2
 org.apache.bcel.classfile.StackMapType peek()
          Returns the element on top of the stack.
 org.apache.bcel.classfile.StackMapType peek(int i)
          Returns the element that's i elements below the top element; that means, if i==0 the top element is returned.
 org.apache.bcel.classfile.StackMapType pop()
          Returns the element on top of the stack.
 org.apache.bcel.classfile.StackMapType pop(int i)
          Pops i elements off the stack.
 void push(org.apache.bcel.classfile.StackMapType type)
          Pushes a StackMapType object onto the stack.
 org.apache.bcel.classfile.StackMapType simulatedJVMPeek(int i)
          Returns the element that's i elements below the top element of the simulated JVM operand stack; that means, iff i==0 the top element is returned.
 org.apache.bcel.classfile.StackMapType simulatedJVMPop(int i)
          Pops i elements off the stack.
(package private)  int size()
          Alias for getSize().
 java.lang.String toString()
          Returns a String representation of this OperandStack instance.
 java.lang.String toString(java.lang.String indentString, int indentLevel)
          Returns a String representation of this OperandStack instance prepending each line with the indent string.
 
Methods inherited from class java.lang.Object
, finalize, getClass, hashCode, notify, notifyAll, registerNatives, wait, wait, wait
 

Field Detail

log

private static org.apache.log4j.Logger log

stack

private java.util.ArrayList stack
We hold the StackMapTypes here.

maxStack

private int maxStack
The maximum number of stack slots this OperandStack instance may hold. Note that this is the number of real JVM stack words. Since some StackMapTypes represent types that require two words, the actual number of StackMapType objects stored may only equal maxStack if none of them are of type ITEM_Long or ITEM_Double.
Constructor Detail

OperandStack

public OperandStack(int maxStack)
Creates an empty stack with a maximum of maxStack slots.

OperandStack

public OperandStack(int maxStack,
                    org.apache.bcel.classfile.StackMapType stackMapType)
Creates an otherwise empty stack with a maximum of maxStack slots and the StackMapType 'stackMaptype' object at the top.
Method Detail

clone

protected java.lang.Object clone()
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.
Overrides:
clone in class java.lang.Object

getClone

public OperandStack getClone()
Returns a correctly typed clone of this object.
See Also:
clone()

clear

public void clear()
Clears the stack.

equals

public boolean equals(java.lang.Object o)
Returns true if and only if this OperandStack equals another, meaning equal lengths and equal objects on the stacks. This is somewhat limited because StackMapType does not have an equals method itself.
Overrides:
equals in class java.lang.Object

isEmpty

public boolean isEmpty()
Returns true IFF this OperandStack is empty.

getMaxStack

public int getMaxStack()
Returns the number of stack slots this stack can hold. Note that this stack holds StackMapTypes, some of which may actually represent values that take up more than one word on the real operand stack.

peek

public org.apache.bcel.classfile.StackMapType peek()
Returns the element on top of the stack. The element is not popped off the stack! Note that the element is a StackMapType which might actually represent more than one word on the actual JVM's aperand stack.

peek

public org.apache.bcel.classfile.StackMapType peek(int i)
Returns the element that's i elements below the top element; that means, if i==0 the top element is returned. The element is not popped off the stack! Note that the element is a StackMapType which might actually represent more than one word on the actual JVM's aperand stack.
See Also:
simulatedJVMPeek(int index)

simulatedJVMPeek

public org.apache.bcel.classfile.StackMapType simulatedJVMPeek(int i)
Returns the element that's i elements below the top element of the simulated JVM operand stack; that means, iff i==0 the top element is returned. The element is not popped off the stack! To simulate the real operand stack, StackMapType objects that are longs or doubles count as two stack items on the simulated JVM aperand stack. Extra overhead in counting real operand stack depth can make this a slow method. Asking for indecies in the middle of longs is is illegal and will throw an exception.

pop

public org.apache.bcel.classfile.StackMapType pop()
Returns the element on top of the stack. The element is popped off the stack. Note that the element is a StackMapType which might actually represent more than one word on the actual JVM's aperand stack.

pop

public org.apache.bcel.classfile.StackMapType pop(int i)
Pops i elements off the stack. ALWAYS RETURNS "null"!!! Note that the elements are StackMapTypes which might actually represent more than one word on the actual JVM's aperand stack.
See Also:
simulatedJVMPop(int)

simulatedJVMPop

public org.apache.bcel.classfile.StackMapType simulatedJVMPop(int i)
Pops i elements off the stack. ALWAYS RETURNS "null"!!! Note that the elements are StackMapTypes which might actually represent more than one word on the actual JVM's aperand stack.
See Also:
simulatedJVMPop(int)

push

public void push(org.apache.bcel.classfile.StackMapType type)
Pushes a StackMapType object onto the stack. Note that a StackMapType might actually represent more than one word on the actual JVM's aperand stack.

size

int size()
Alias for getSize().
See Also:
getSize()

getSize

public int getSize()
Returns the size of this OperandStack; that means, how many StackMapType objects there are. Note that each element is a StackMapType which might actually represent more than one word on the actual JVM's aperand stack. To calculate the stack size of the real JVM stack, use getSimulatedJVMsize() instead.
See Also:
getSimulatedJVMsize()

getSimulatedJVMsize

int getSimulatedJVMsize()
Returns the simulated size of the JVM operand stack that this OperandStack object represents; that means, how many words would be on the operand stack of the real JVM. Note that each element on the OperandStack is a StackMapType which might actually represent more than one word on the actual JVM's aperand stack. If you want to know the number of StackMapTypes on the OperandStack, then use the getSize method instead.
See Also:
getSize()

getStackItems

public org.apache.bcel.classfile.StackMapType[] getStackItems()
Converts OperandStack StackMapTypes. Used in building stack portion of StackMapEntry that is part of a StackMap, which is used in J2ME class preverification. Note that StackMap requires that the OperandStack be in reverse order to the way it is actually stored.

merge

public void merge(OperandStack challenger)
Merges two OperandStacks according to JVM Specification 4.9.2

toString

public java.lang.String toString()
Returns a String representation of this OperandStack instance.
Overrides:
toString in class java.lang.Object

toString

public java.lang.String toString(java.lang.String indentString,
                                 int indentLevel)
Returns a String representation of this OperandStack instance prepending each line with the indent string.
Parameters:
indentString - String to prepend to each line to allow indent matching.
indentLevel - How many copies of indent string to append.

indent

private void indent(java.lang.StringBuffer sb,
                    java.lang.String indentString,
                    int indentLevel)