com.markcrocker.purifier
Class LocalVariables

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

public class LocalVariables
extends java.lang.Object

This class implements an array of local variables used for StackMap generation. Data is stored as StackMapTypes, which is not entirely consistent with symbolic JVM storage because some StackMapType entries represent two storage words. Consequently, the two set methods check for longs or doubles and modify the subsequent entry appropriately.

Author:
Enver Haase, Mark Crocker

Field Summary
private  boolean astoreConflictOverride
           
private  int astoreOverrideIndex
           
private  int javaLangObjectIndex
           
private  org.apache.bcel.classfile.StackMapType[] locals
          The StackMapType[] containing the local variable information.
private static org.apache.log4j.Logger log
           
 
Constructor Summary
LocalVariables(int maxLocals)
          Constructs a new LocalVariables object, and leaves entries as nulls.
LocalVariables(org.apache.bcel.generic.MethodGen mg, org.apache.bcel.generic.ConstantPoolGen cpg)
          Construct pre-initialized LocalVariables suitable for normal Method invokation.
LocalVariables(org.apache.bcel.classfile.StackMapType[] stackMapTypes)
          Constructs a new LocalVariables object from an array of existing StackMapTypes
 
Method Summary
static void addStackMapTypeToStringBuffer(org.apache.bcel.classfile.StackMapType smt, java.lang.StringBuffer s)
           
protected  java.lang.Object clone()
          Returns a deep copy of this object.
 boolean equals(java.lang.Object o)
           
 boolean getAstoreConflictOverride()
           
 int getAstoreOverrideIndex()
           
 LocalVariables getClone()
          Returns a (correctly typed) clone of this object.
 int getIndex(int i)
          Returns the ConstantPool index of the local variable slot i.
 int getJavaLangObjectIndex()
           
 org.apache.bcel.classfile.StackMapType[] getLocals(org.apache.bcel.classfile.ConstantPool cp)
          Returns a copy of the local variables.
 int getMaxLocals()
          Returns the number of local variable slots this LocalVariables instance has.
 org.apache.bcel.classfile.StackMapType getStackMapType(int i)
          Returns the local variable at slot i.
 byte getType(int i)
          Returns the type of the local variable slot i.
private static void indent(java.lang.StringBuffer sb, java.lang.String indentString, int indentLevel)
           
 void methodEntrySetup(org.apache.bcel.generic.MethodGen mg, org.apache.bcel.generic.ConstantPoolGen cpg)
          Setup LocalVariables to be pre-initialized in a way that is suitable for normal Method invokation.
 LocalVariables resolveConflicts(LocalVariables challenger)
          If a target has already been visited and a discrepancy exists between the local variables on the new Frame and the stored Frame, then the conflict has to be resolved.
 void set(int i, byte type, int index, org.apache.bcel.classfile.ConstantPool cp)
          Sets a new Type for the given local variable slot.
 void set(int i, org.apache.bcel.classfile.StackMapType stackMapType)
          Sets a new Type for the given local variable slot.
 void setAstoreOverride(int astoreOverrideIndex, int javaLangObjectIndex)
           
static boolean stackMapTypeEquals(org.apache.bcel.classfile.StackMapType smta, org.apache.bcel.classfile.StackMapType smtb)
           
static java.lang.String stackMapTypeToString(org.apache.bcel.classfile.StackMapType smt)
           
static java.lang.String stackMapTypeToString(org.apache.bcel.classfile.StackMapType smt, java.lang.String indentString, int indentLevel)
           
 java.lang.String toString()
          Returns a String representation of the LocalVariables object.
 java.lang.String toString(java.lang.String indentString, int indentLevel)
          Returns a String representation of the LocalVariables object, 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

locals

private org.apache.bcel.classfile.StackMapType[] locals
The StackMapType[] containing the local variable information.

astoreConflictOverride

private boolean astoreConflictOverride

astoreOverrideIndex

private int astoreOverrideIndex

javaLangObjectIndex

private int javaLangObjectIndex
Constructor Detail

LocalVariables

public LocalVariables(int maxLocals)
Constructs a new LocalVariables object, and leaves entries as nulls.

LocalVariables

public LocalVariables(org.apache.bcel.classfile.StackMapType[] stackMapTypes)
Constructs a new LocalVariables object from an array of existing StackMapTypes

LocalVariables

public LocalVariables(org.apache.bcel.generic.MethodGen mg,
                      org.apache.bcel.generic.ConstantPoolGen cpg)
Construct pre-initialized LocalVariables suitable for normal Method invokation. Uses a MethodGen and ConstantPoolGen to derive the necessary data that is to be loaded into the LocalVariables
Method Detail

getType

public byte getType(int i)
Returns the type of the local variable slot i.

getIndex

public int getIndex(int i)
Returns the ConstantPool index of the local variable slot i.

getStackMapType

public org.apache.bcel.classfile.StackMapType getStackMapType(int i)
Returns the local variable at slot i.

getLocals

public org.apache.bcel.classfile.StackMapType[] getLocals(org.apache.bcel.classfile.ConstantPool cp)
Returns a copy of the local variables. Since the StackMap generator in Sun's preverifier truncates trailing nulls, this method needs to do that too. nulls in the middle of the table generate an ITEM_Bogus StackMapType.

clone

protected java.lang.Object clone()
Returns a deep copy of this object. The clone operates on a new local variable array. However, the StackMapType objects in the array are shared.
Overrides:
clone in class java.lang.Object

set

public void set(int i,
                byte type,
                int index,
                org.apache.bcel.classfile.ConstantPool cp)
Sets a new Type for the given local variable slot. Note that the element being stored is a StackMapType which might actually represent more than one word on the actual JVM's storage structure. Consequently if a long or double is stored, this method will set the subsequent LocalVariable to null to provide at least some indication that accessing it is probably invalid to access that element.

set

public void set(int i,
                org.apache.bcel.classfile.StackMapType stackMapType)
Sets a new Type for the given local variable slot. Note that the element being stored is a StackMapType which might actually represent more than one word on the actual JVM's storage structure. Consequently if a long or double is stored, this method will set the subsequent LocalVariable to type null to provide at least some indication that accessing it is probably invalid.

getClone

public LocalVariables getClone()
Returns a (correctly typed) clone of this object. This is equivalent to ((LocalVariables) this.clone()).

getMaxLocals

public int getMaxLocals()
Returns the number of local variable slots this LocalVariables instance has.

equals

public boolean equals(java.lang.Object o)
Overrides:
equals in class java.lang.Object

stackMapTypeEquals

public static boolean stackMapTypeEquals(org.apache.bcel.classfile.StackMapType smta,
                                         org.apache.bcel.classfile.StackMapType smtb)

methodEntrySetup

public void methodEntrySetup(org.apache.bcel.generic.MethodGen mg,
                             org.apache.bcel.generic.ConstantPoolGen cpg)
Setup LocalVariables to be pre-initialized in a way that is suitable for normal Method invokation. Uses a MethodGen and ConstantPoolGen to derive the necessary data that is to be loaded into the LocalVariables

setAstoreOverride

public void setAstoreOverride(int astoreOverrideIndex,
                              int javaLangObjectIndex)

getAstoreConflictOverride

public boolean getAstoreConflictOverride()

getAstoreOverrideIndex

public int getAstoreOverrideIndex()

getJavaLangObjectIndex

public int getJavaLangObjectIndex()

resolveConflicts

public LocalVariables resolveConflicts(LocalVariables challenger)
If a target has already been visited and a discrepancy exists between the local variables on the new Frame and the stored Frame, then the conflict has to be resolved. This feature is required because multiple branches that branch to or end up leading to a common branch target may have a difference in the "junk" elements in the LocalVariables table that may happen to have been used and abandonned by a particular branch source, but are not used by the branch target code. These extra values may be left in the local variables table, but they are irrelevant to the code following the branch target. Sun's perverifier purges the extra entries. It is possible that Sun has chosen to do this avoid any possible confusion that these extra elements may produce resulting in an unambiguous local variables table.

There is also another, related source of confusion caused by the fact that some branch sources will use a subtype of the class that a variable is intended to hold. Using a subtype is perfectly valid, however, when comparing the Frames, there appears to be a conflict. Consequently, these apparent conflicts also need to be resolved and the most general type needs to be the one that is stored in the Frame's local variables. The Java VM Specification refers to this as "merging".

Returns:
normally a null Frame. If there is a dispute in local variable table entries, a 'corrected' Frame is returned.

toString

public java.lang.String toString()
Returns a String representation of the LocalVariables object.
Overrides:
toString in class java.lang.Object

toString

public java.lang.String toString(java.lang.String indentString,
                                 int indentLevel)
Returns a String representation of the LocalVariables object, 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.

addStackMapTypeToStringBuffer

public static void addStackMapTypeToStringBuffer(org.apache.bcel.classfile.StackMapType smt,
                                                 java.lang.StringBuffer s)

stackMapTypeToString

public static java.lang.String stackMapTypeToString(org.apache.bcel.classfile.StackMapType smt,
                                                    java.lang.String indentString,
                                                    int indentLevel)

stackMapTypeToString

public static java.lang.String stackMapTypeToString(org.apache.bcel.classfile.StackMapType smt)

indent

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