opu.lljvm-python.0.2.0-EXPERIMENTAL.source-code.StackMap Maven / Gradle / Ivy
The newest version!
/**
* @see StackMapAttr
* @see StackMapFrameAttr
* @author $Author: Daniel Reynaud $
* @author $Author: Iouri Kharon $
* @version $Revision: 1.3 $
*/
package jas;
import java.io.*;
import java.util.Vector;
import java.util.Enumeration;
public class StackMap
{
static private final int JDK_SMF_MIN = 50;
static CP attr = null;
static boolean java6 = false;
protected Vector frames;
public static void reinit()
{ attr = null;
java6 = false; }
protected StackMap(CP attr)
{ this.attr = attr;
frames = new Vector(); }
public StackMap(ClassEnv e)
{
if(attr == null)
{
if(e.version_hi >= JDK_SMF_MIN) java6 = true;
attr = new AsciiCP(java6 ? "StackMapTable" : "StackMap");
}
frames = new Vector();
}
public void addFrame(VerifyFrame f)
{ frames.add(f); }
// get copy of previous locals frame (possible with choping)
public Vector getLastFrame(int count) throws jasError
{
if(frames.isEmpty())
return null;
return ((VerifyFrame)frames.lastElement()).getFrame(count);
}
// this method call BEFORE write method
public int size(ClassEnv e, CodeAttr ce)
{
try {
if(java6) shellSort(ce);
return write(e, ce, null);
} catch(IOException ex) {
System.err.println("UNEXPECTED IO EXCEPTION");
ex.printStackTrace();
} catch(jasError ex) {
System.err.println("UNEXPECTED JAS ERROR");
ex.printStackTrace();
}
return 0;
}
void resolve(ClassEnv e)
{ e.addCPItem(attr);
Enumeration en = frames.elements();
while(en.hasMoreElements())
((VerifyFrame)en.nextElement()).resolve(e);
}
int write(ClassEnv e, CodeAttr ce, DataOutputStream out)
throws IOException, jasError
{
// writing to a buffer first, so that we can print the length
ByteArrayOutputStream buf = new ByteArrayOutputStream();
DataOutputStream bufout = new DataOutputStream(buf);
// not fully compliant to the CLDC spec !
bufout.writeShort(frames.size());
VerifyFrame prev = null; // prepare for StackMapFrameAttr
Enumeration en = frames.elements();
while(en.hasMoreElements())
{
VerifyFrame cur = (VerifyFrame)en.nextElement();
if(!java6) prev = cur; // as flag
cur.write(e, ce, bufout, prev);
prev = cur;
}
int len = buf.toByteArray().length;
if(out != null) // else, call for size calculation
{
out.writeShort(e.getCPIndex(attr));
out.writeInt(len);
buf.writeTo(out);
}
return (2 + 4) + len;
}
// sort (method of Shell) frames by offset (before writing)
// used for StackMapFrameAttr mode.
private void shellSort(CodeAttr ce) throws jasError
{
int n = frames.size();
if(--n <= 0) return;
int g = 3;
if(g > n) g = 1;
do {
int i = g;
do {
VerifyFrame tmp = (VerifyFrame)frames.elementAt(i);
int jn, j, ts = tmp.getOffset(ce);
for(j = i; j >= g; j = jn) {
jn = j - g;
VerifyFrame t1 = (VerifyFrame)frames.elementAt(jn);
if(t1.getOffset(ce) <= ts) break;
frames.setElementAt(t1, j);
}
frames.setElementAt(tmp, j);
}while(++i <= n);
}while((g /= 2) > 0);
}
}
/* --- Revision History ---------------------------------------------------
--- Iouri Kharon, May 07 2010, reset java6-mode for new compiled file
*/