com.markcrocker.purifier.testcases
Class SpecialCases

java.lang.Object
  |
  +--javax.microedition.midlet.MIDlet
        |
        +--com.markcrocker.purifier.testcases.SpecialCases
All Implemented Interfaces:
javax.microedition.lcdui.CommandListener, javax.microedition.lcdui.ItemStateListener

public class SpecialCases
extends javax.microedition.midlet.MIDlet
implements javax.microedition.lcdui.CommandListener, javax.microedition.lcdui.ItemStateListener

The SpecialCases class file is designed to provide a set of Java structures that can be used to check the Purifier StackMapGen.generate against special cases that it has been designed to recognize and compensate for.


Field Summary
(package private)  javax.microedition.lcdui.Display display
           
(package private)  javax.microedition.lcdui.TextBox Hello
           
 
Constructor Summary
SpecialCases()
           
 
Method Summary
 void commandAction(javax.microedition.lcdui.Command c, javax.microedition.lcdui.Displayable d)
           
 void destroyApp(boolean unconditional)
           
 void itemStateChanged(javax.microedition.lcdui.Item item)
           
 void legitimateBogusInStackMap()
          Produces a StackMap that legitimately has an ITEM_Bogus in the StackMap.
 void multipleBranchesWithSameTarget()
          All branches in this method end up going to the iinc instruction at the end of the method.
 void newObjectOnStack()
          Puts an ITEM_NewObject on the stack.
 void pauseApp()
           
 void startApp()
           
 void takesLongPrimitivesAndObjects(long i, java.lang.String s, int j, java.lang.String t, long k, java.lang.String u, int l, java.lang.String v)
          Longs take up two slots in local variables.
 void typeNotDeclared()
          the string, startsNull is stored on the LocalVariables array as an ITEM_Null at first, because there is no way to tell what type it is when the Purifier gets to the aconst_null instruction.
 void unreferencedObjectSignatureInStackMap()
          Has an object signature that isn't in the ConstantPool.
 
Methods inherited from class javax.microedition.midlet.MIDlet
getAppProperty, notifyDestroyed, notifyPaused, resumeRequest
 
Methods inherited from class java.lang.Object
, clone, equals, finalize, getClass, hashCode, notify, notifyAll, registerNatives, toString, wait, wait, wait
 

Field Detail

display

javax.microedition.lcdui.Display display

Hello

javax.microedition.lcdui.TextBox Hello
Constructor Detail

SpecialCases

public SpecialCases()
Method Detail

startApp

public void startApp()
              throws javax.microedition.midlet.MIDletStateChangeException
Overrides:
startApp in class javax.microedition.midlet.MIDlet

pauseApp

public void pauseApp()
Overrides:
pauseApp in class javax.microedition.midlet.MIDlet

destroyApp

public void destroyApp(boolean unconditional)
                throws javax.microedition.midlet.MIDletStateChangeException
Overrides:
destroyApp in class javax.microedition.midlet.MIDlet

itemStateChanged

public void itemStateChanged(javax.microedition.lcdui.Item item)
Specified by:
itemStateChanged in interface javax.microedition.lcdui.ItemStateListener

commandAction

public void commandAction(javax.microedition.lcdui.Command c,
                          javax.microedition.lcdui.Displayable d)
Specified by:
commandAction in interface javax.microedition.lcdui.CommandListener

typeNotDeclared

public void typeNotDeclared()
the string, startsNull is stored on the LocalVariables array as an ITEM_Null at first, because there is no way to tell what type it is when the Purifier gets to the aconst_null instruction. Inside of the if block, the variable is set to [Ljava.lang.String;. Then at the iinc instruction, a conflict is detected between the two Frames. One has an ITEM_Null in the LocalVariables and the other has a [Ljava.lang.String; and the resolveConflicts method correctly determines that the latter is the correct one to use.

legitimateBogusInStackMap

public void legitimateBogusInStackMap()
Produces a StackMap that legitimately has an ITEM_Bogus in the StackMap. This is because the int j is stored in LocalVariables slot 2 and is not initialized unless the if block is used. Since j has only got a transient value and isn't used outside of the if block, then at the point that the StackMap entry is created the LocalVariables slot 2 is null (not ITEM_Null). Although trailing nulls are simply trimmed off of the StackMap, nulls in the middle are represented as ITEM_Bogus, which is what happens in this case.

takesLongPrimitivesAndObjects

public void takesLongPrimitivesAndObjects(long i,
                                          java.lang.String s,
                                          int j,
                                          java.lang.String t,
                                          long k,
                                          java.lang.String u,
                                          int l,
                                          java.lang.String v)
Longs take up two slots in local variables. Requires attention to detail when setting up frame. The initial frame looks like:
Local Variables:
0: (type=Object, class=com.markcrocker.purifier.testcases.SpecialCases)
1: (type=Long)
2: null
3: (type=Object, class=java.lang.String)
4: (type=Integer)
5: (type=Object, class=java.lang.String)
6: (type=Long)
7: null
8: (type=Object, class=java.lang.String)
9: (type=Integer)
10: (type=Object, class=java.lang.String)
OperandStack:
Slots used: 0 MaxStack: 4.
The fact that slots 1 and 6 are Longs and 2 and 7 are nulls is the important point here. In CLDC 1.1, there has been a new type, ITEM_Top to deal with this situation and it is set up with the other way around. That is, slots 1 and 6 would hold ITEM_Top entries and 2 and 7 would hold the ITEM_Long entries.

unreferencedObjectSignatureInStackMap

public void unreferencedObjectSignatureInStackMap()
Has an object signature that isn't in the ConstantPool. It occurs because the .equals method expects a type of Ljava.lang.Object;, which isn't actually used anywhere in the rest of the method or any of the other methods in this class, so there's no point of putting an entry for it in the ConstantPool. This doesn't cause any problems because the invokeInstruction method recognizes that the Ljava.lang.String; that is used for the equals method argument is a better entry to use than the unknown object.

multipleBranchesWithSameTarget

public void multipleBranchesWithSameTarget()
All branches in this method end up going to the iinc instruction at the end of the method. Since Integer J and Integer I are just used inside of if blocks and do not appear outside, they are junk variables. However, the branch targets that contain them add them to the LocalVariables array (entries 2 and 3), so, when the iinc is investigated, there is a conflict because of the extra entries in the LocalVariables. The resolveConflicts method correctly notices that they are opposed by null entries in the straight-through Frame, so they are eliminated.

newObjectOnStack

public void newObjectOnStack()
Puts an ITEM_NewObject on the stack. Also illustrates the stack order swap issue.