protected ByteVector write(final ClassWriter cw,
final byte[] code,
final int len,
final int maxStack,
final int maxLocals) {
final ByteVector bv = new ByteVector();
// TODO verify this value (MAX_SHORT)
final boolean isExtCodeSize = code != null && code.length > StackMapTableAttribute.MAX_SHORT;
writeSize( this.frames.size() - 1,
bv,
isExtCodeSize );
if ( this.frames.size() < 2 ) {
return bv;
}
final boolean isExtLocals = maxLocals > StackMapTableAttribute.MAX_SHORT;
final boolean isExtStack = maxStack > StackMapTableAttribute.MAX_SHORT;
// skip the first frame
StackMapFrame frame = (StackMapFrame) this.frames.get( 0 );
List locals = frame.locals;
int offset = frame.label.getOffset();
for ( int i = 1; i < this.frames.size(); i++ ) {
frame = (StackMapFrame) this.frames.get( i );
final List clocals = frame.locals;
final List cstack = frame.stack;
final int coffset = frame.label.getOffset();
final int clocalsSize = clocals.size();
final int cstackSize = cstack.size();
int localsSize = locals.size();
final int delta = coffset - offset;
int type = StackMapTableAttribute.FULL_FRAME;
int k = 0;
if ( cstackSize == 0 ) {
k = clocalsSize - localsSize;
switch ( k ) {
case -3 :
case -2 :
case -1 :
type = StackMapTableAttribute.CHOP_FRAME; // CHOP or FULL
localsSize = clocalsSize; // for full_frame check
break;
case 0 :
// SAME, SAME_EXTENDED or FULL
type = delta < 64 ? StackMapTableAttribute.SAME_FRAME : StackMapTableAttribute.SAME_FRAME_EXTENDED;
break;
case 1 :
case 2 :
case 3 :
type = StackMapTableAttribute.APPEND_FRAME; // APPEND or FULL
break;
}
} else if ( localsSize == clocalsSize && cstackSize == 1 ) {
// SAME_LOCAL_1_STACK or FULL
type = delta < 63 ? StackMapTableAttribute.SAME_LOCALS_1_STACK_ITEM_FRAME : StackMapTableAttribute.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED;
}
if ( type != StackMapTableAttribute.FULL_FRAME ) {
// verify if stack and locals are the same
for ( int j = 0; j < localsSize && type != StackMapTableAttribute.FULL_FRAME; j++ ) {
if ( !locals.get( j ).equals( clocals.get( j ) ) ) {
type = StackMapTableAttribute.FULL_FRAME;
}
}
}
switch ( type ) {
case SAME_FRAME :
bv.putByte( delta );
break;
case SAME_LOCALS_1_STACK_ITEM_FRAME :
bv.putByte( StackMapTableAttribute.SAME_LOCALS_1_STACK_ITEM_FRAME + delta );
writeTypeInfos( bv,
cw,
cstack,
0,
1 );
break;
case SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED :
bv.putByte( StackMapTableAttribute.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED );
writeSize( delta,
bv,
isExtCodeSize );
writeTypeInfos( bv,
cw,
cstack,
0,
1 );
break;
case SAME_FRAME_EXTENDED :
bv.putByte( StackMapTableAttribute.SAME_FRAME_EXTENDED );
writeSize( delta,
bv,
isExtCodeSize );
break;
case CHOP_FRAME :
bv.putByte( StackMapTableAttribute.SAME_FRAME_EXTENDED + k ); // negative k
writeSize( delta,
bv,
isExtCodeSize );
break;
case APPEND_FRAME :
bv.putByte( StackMapTableAttribute.SAME_FRAME_EXTENDED + k ); // positive k
writeSize( delta,
bv,
isExtCodeSize );
writeTypeInfos( bv,
cw,
clocals,
clocalsSize - 1,
clocalsSize );
break;
case FULL_FRAME :
bv.putByte( StackMapTableAttribute.FULL_FRAME );
writeSize( delta,
bv,
isExtCodeSize );
writeSize( clocalsSize,
bv,