opu.lljvm-python.0.2.0-EXPERIMENTAL.source-code.VerifyFrame Maven / Gradle / Ivy
The newest version!
/**
* VerifyFrame are part of StackMap/StackMapFrame attributes
* @author $Author: Daniel Reynaud $
* @author $Author: Iouri Kharon $
* @version $Revision: 1.1 $
*/
package jas;
import java.io.*;
import java.util.Vector;
import java.util.Enumeration;
public class VerifyFrame
{
private static final int SAME_FRAME_S0_min = 0;
private static final int SAME_FRAME_S0_max = 63;
private static final int SAME_FRAME_S1_min = 64; // + vi
private static final int SAME_FRAME_S1_max = 127;
private static final int SAME_FRAME_S1 = 247; // + off, vi
private static final int CHOP_FRAME_S0_min = 248; // + off
// private static final int CHOP_FRAME_S0_max = 250;
private static final int SAME_FRAME_S0 = 251; // +off
// private static final int APPEND_FRAME_S0_min = 252; // +off, vi[n]
private static final int APPEND_FRAME_S0_max = 254;
private static final int FULL_FRAME = 255;
private Vector stack, locals;
private int offset;
private Label off_label;
private boolean offset_defined;
public VerifyFrame(Vector InitialFrame)
{ stack = new Vector();
locals = InitialFrame;
if(locals == null)
locals = new Vector();
offset_defined = false; }
private void defineOffset() throws jasError
{ if(offset_defined) throw new jasError("offset already defined");
offset_defined = true; }
public void setOffset(int offset) throws jasError
{ defineOffset();
this.offset = offset; }
public void setOffset(Label label) throws jasError
{ defineOffset();
off_label = label; }
public void addStackItem(String item, String val) throws jasError
{ stack.add(new VerificationTypeInfo(item, val)); }
public void addLocalsItem(String item, String val) throws jasError
{ locals.add(new VerificationTypeInfo(item, val)); }
public boolean haveOffset()
{ return offset_defined; }
// make copy of locals frame (with type-independed counter)
public Vector getFrame(int count) throws jasError
{
if(count > locals.size())
throw new jasError("Counter exceed range", true);
Vector result = new Vector(locals);
if(count != 0) // else -- full copy
result.setSize(count);
return result;
}
public int getOffset(CodeAttr ce) throws jasError
{
if(off_label != null) {
offset = ce.getPc(off_label);
off_label = null; // for speed in next's request
}
return offset;
}
void resolve(ClassEnv e)
{
Enumeration en = stack.elements();
while(en.hasMoreElements())
((VerificationTypeInfo)en.nextElement()).resolve(e);
en = locals.elements();
while(en.hasMoreElements())
((VerificationTypeInfo)en.nextElement()).resolve(e);
}
void write(ClassEnv e, CodeAttr ce, DataOutputStream out,
VerifyFrame prev)
throws IOException, jasError
{
int off = getOffset(ce);
int stack_size = stack.size();
int locals_size = locals.size();
if(prev != this) { // JDK >= 6
if(prev != null) { // not first element
int prev_off = prev.getOffset(ce);
if(prev_off >= off)
throw new jasError("Write unsorted StackMapFrame");
off -= prev_off + 1;
}
if(stack_size <= 1) { // else can't compact
boolean can_compact = true;
int prev_size = 0;
if(prev == null) { // first record
if(stack_size == 0) {
if(locals_size > (APPEND_FRAME_S0_max - SAME_FRAME_S0))
can_compact = false;
} else if(locals_size != 0)
can_compact = false;
} else { // not first record
int cmpcn = locals_size;
prev_size = prev.locals.size();
int delta = locals_size - prev_size;
if(stack_size == 0) {
if(delta >= 0) {
if(delta > (APPEND_FRAME_S0_max - SAME_FRAME_S0))
can_compact = false;
cmpcn -= delta;
} else if(delta < (CHOP_FRAME_S0_min - SAME_FRAME_S0))
can_compact = false;
} else if(delta != 0) can_compact = false;
if(can_compact)
while(--cmpcn >= 0)
if(!((VerificationTypeInfo)
locals.elementAt(cmpcn)).isEqual(e, ce,
((VerificationTypeInfo)
prev.locals.elementAt(cmpcn))))
{
can_compact = false;
break;
}
}
if(can_compact) {
if(stack_size != 0) { // only if SAME_FRAME_S1...
if(off <= (SAME_FRAME_S1_max - SAME_FRAME_S1_min))
out.writeByte((byte)(off + SAME_FRAME_S1_min));
else {
out.writeByte((byte)SAME_FRAME_S1);
out.writeShort((short)off);
}
((VerificationTypeInfo)stack.elementAt(0)).write(e, ce, out);
return;
}
// stack is empty
int wrdt = locals_size - prev_size;
if( wrdt == 0
&& off <= (SAME_FRAME_S0_max - SAME_FRAME_S0_min)) {
out.writeByte((byte)(off + SAME_FRAME_S0_min));
return;
}
out.writeByte((byte)(SAME_FRAME_S0 + wrdt));
out.writeShort((short)off);
while(--wrdt >= 0)
((VerificationTypeInfo)
locals.elementAt(prev_size++)).write(e, ce, out);
return;
}
}
// can't compact -- write full frame
out.writeByte((byte)FULL_FRAME);
} // end of StackMapFrame(JDK>=1.6) mode
out.writeShort((short)off);
out.writeShort((short)locals_size); // number_of_locals
// System.out.println("number of local items "+locals_size);
Enumeration en = locals.elements();
while(--locals_size >= 0)
((VerificationTypeInfo)en.nextElement()).write(e, ce, out);
out.writeShort((short)stack_size); // number_of_stack_items
// System.out.println("number of stack items "+stack_size);
en = stack.elements();
while(--stack_size >= 0)
((VerificationTypeInfo)en.nextElement()).write(e, ce, out);
}
}