下面列出了org.objectweb.asm.Opcodes# F_APPEND 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* Constructs a new {@link FrameNode}.
*
* @param type
* the type of this frame. Must be {@link Opcodes#F_NEW} for expanded frames, or {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND}, {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed frames.
* @param numLocal
* number of local variables of this stack map frame.
* @param local
* the types of the local variables of this stack map frame. Elements of this list can be Integer, String or LabelNode objects (for primitive, reference and uninitialized types respectively - see {@link MethodVisitor}).
* @param numStack
* number of operand stack elements of this stack map frame.
* @param stack
* the types of the operand stack elements of this stack map frame. Elements of this list can be Integer, String or LabelNode objects (for primitive, reference and uninitialized types respectively - see {@link MethodVisitor}).
*/
public FrameNode(final int type, final int numLocal, final Object[] local, final int numStack, final Object[] stack) {
super(-1);
this.type = type;
switch (type) {
case Opcodes.F_NEW:
case Opcodes.F_FULL:
this.local = Util.asArrayList(numLocal, local);
this.stack = Util.asArrayList(numStack, stack);
break;
case Opcodes.F_APPEND:
this.local = Util.asArrayList(numLocal, local);
break;
case Opcodes.F_CHOP:
this.local = Util.asArrayList(numLocal);
break;
case Opcodes.F_SAME:
break;
case Opcodes.F_SAME1:
this.stack = Util.asArrayList(1, stack);
break;
default:
throw new IllegalArgumentException();
}
}
@Override
public void accept(final MethodVisitor methodVisitor) {
switch (type) {
case Opcodes.F_NEW:
case Opcodes.F_FULL:
methodVisitor.visitFrame(type, local.size(), asArray(local), stack.size(), asArray(stack));
break;
case Opcodes.F_APPEND:
methodVisitor.visitFrame(type, local.size(), asArray(local), 0, null);
break;
case Opcodes.F_CHOP:
methodVisitor.visitFrame(type, local.size(), null, 0, null);
break;
case Opcodes.F_SAME:
methodVisitor.visitFrame(type, 0, null, 0, null);
break;
case Opcodes.F_SAME1:
methodVisitor.visitFrame(type, 0, null, 1, asArray(stack));
break;
default:
throw new IllegalArgumentException();
}
}
@Override
public void accept(final MethodVisitor methodVisitor) {
switch (type) {
case Opcodes.F_NEW:
case Opcodes.F_FULL:
methodVisitor.visitFrame(type, local.size(), asArray(local), stack.size(), asArray(stack));
break;
case Opcodes.F_APPEND:
methodVisitor.visitFrame(type, local.size(), asArray(local), 0, null);
break;
case Opcodes.F_CHOP:
methodVisitor.visitFrame(type, local.size(), null, 0, null);
break;
case Opcodes.F_SAME:
methodVisitor.visitFrame(type, 0, null, 0, null);
break;
case Opcodes.F_SAME1:
methodVisitor.visitFrame(type, 0, null, 1, asArray(stack));
break;
default:
throw new IllegalArgumentException();
}
}
/**
* Makes the given visitor visit this stack map frame.
*
* @param mv
* a method visitor.
*/
@Override
public void accept(final MethodVisitor mv) {
switch (type) {
case Opcodes.F_NEW:
case Opcodes.F_FULL:
mv.visitFrame(type, local.size(), asArray(local), stack.size(), asArray(stack));
break;
case Opcodes.F_APPEND:
mv.visitFrame(type, local.size(), asArray(local), 0, null);
break;
case Opcodes.F_CHOP:
mv.visitFrame(type, local.size(), null, 0, null);
break;
case Opcodes.F_SAME:
mv.visitFrame(type, 0, null, 0, null);
break;
case Opcodes.F_SAME1:
mv.visitFrame(type, 0, null, 1, asArray(stack));
break;
}
}
@Override
public void accept(final MethodVisitor methodVisitor) {
switch (type) {
case Opcodes.F_NEW:
case Opcodes.F_FULL:
methodVisitor.visitFrame(type, local.size(), asArray(local), stack.size(), asArray(stack));
break;
case Opcodes.F_APPEND:
methodVisitor.visitFrame(type, local.size(), asArray(local), 0, null);
break;
case Opcodes.F_CHOP:
methodVisitor.visitFrame(type, local.size(), null, 0, null);
break;
case Opcodes.F_SAME:
methodVisitor.visitFrame(type, 0, null, 0, null);
break;
case Opcodes.F_SAME1:
methodVisitor.visitFrame(type, 0, null, 1, asArray(stack));
break;
default:
throw new IllegalArgumentException();
}
}
@Override
public void accept(final MethodVisitor methodVisitor) {
switch (type) {
case Opcodes.F_NEW:
case Opcodes.F_FULL:
methodVisitor.visitFrame(type, local.size(), asArray(local), stack.size(), asArray(stack));
break;
case Opcodes.F_APPEND:
methodVisitor.visitFrame(type, local.size(), asArray(local), 0, null);
break;
case Opcodes.F_CHOP:
methodVisitor.visitFrame(type, local.size(), null, 0, null);
break;
case Opcodes.F_SAME:
methodVisitor.visitFrame(type, 0, null, 0, null);
break;
case Opcodes.F_SAME1:
methodVisitor.visitFrame(type, 0, null, 1, asArray(stack));
break;
default:
throw new IllegalArgumentException();
}
}
@Override
public void visitFrame(
final int type,
final int numLocal,
final Object[] local,
final int numStack,
final Object[] stack) {
stringBuilder.setLength(0);
stringBuilder.append(ltab);
stringBuilder.append("FRAME ");
switch (type) {
case Opcodes.F_NEW:
case Opcodes.F_FULL:
stringBuilder.append("FULL [");
appendFrameTypes(numLocal, local);
stringBuilder.append("] [");
appendFrameTypes(numStack, stack);
stringBuilder.append(']');
break;
case Opcodes.F_APPEND:
stringBuilder.append("APPEND [");
appendFrameTypes(numLocal, local);
stringBuilder.append(']');
break;
case Opcodes.F_CHOP:
stringBuilder.append("CHOP ").append(numLocal);
break;
case Opcodes.F_SAME:
stringBuilder.append("SAME");
break;
case Opcodes.F_SAME1:
stringBuilder.append("SAME1 ");
appendFrameTypes(1, stack);
break;
default:
throw new IllegalArgumentException();
}
stringBuilder.append('\n');
text.add(stringBuilder.toString());
}
@Override
public void visitFrame(final int type, final int nLocal, final Object[] local, final int nStack, final Object[] stack) {
AttributesImpl attrs = new AttributesImpl();
switch (type) {
case Opcodes.F_NEW:
case Opcodes.F_FULL:
if (type == Opcodes.F_NEW) {
attrs.addAttribute("", "type", "type", "", "NEW");
} else {
attrs.addAttribute("", "type", "type", "", "FULL");
}
sa.addStart("frame", attrs);
appendFrameTypes(true, nLocal, local);
appendFrameTypes(false, nStack, stack);
break;
case Opcodes.F_APPEND:
attrs.addAttribute("", "type", "type", "", "APPEND");
sa.addStart("frame", attrs);
appendFrameTypes(true, nLocal, local);
break;
case Opcodes.F_CHOP:
attrs.addAttribute("", "type", "type", "", "CHOP");
attrs.addAttribute("", "count", "count", "", Integer.toString(nLocal));
sa.addStart("frame", attrs);
break;
case Opcodes.F_SAME:
attrs.addAttribute("", "type", "type", "", "SAME");
sa.addStart("frame", attrs);
break;
case Opcodes.F_SAME1:
attrs.addAttribute("", "type", "type", "", "SAME1");
sa.addStart("frame", attrs);
appendFrameTypes(false, 1, stack);
break;
}
sa.addEnd("frame");
}
@Override
public void visitFrame(final int type, final int nLocal, final Object[] local, final int nStack, final Object[] stack) {
buf.setLength(0);
buf.append(ltab);
buf.append("FRAME ");
switch (type) {
case Opcodes.F_NEW:
case Opcodes.F_FULL:
buf.append("FULL [");
appendFrameTypes(nLocal, local);
buf.append("] [");
appendFrameTypes(nStack, stack);
buf.append(']');
break;
case Opcodes.F_APPEND:
buf.append("APPEND [");
appendFrameTypes(nLocal, local);
buf.append(']');
break;
case Opcodes.F_CHOP:
buf.append("CHOP ").append(nLocal);
break;
case Opcodes.F_SAME:
buf.append("SAME");
break;
case Opcodes.F_SAME1:
buf.append("SAME1 ");
appendFrameTypes(1, stack);
break;
}
buf.append('\n');
text.add(buf.toString());
}
/**
* Constructs a new {@link FrameNode}.
*
* @param type the type of this frame. Must be {@link Opcodes#F_NEW} for expanded frames, or
* {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND}, {@link Opcodes#F_CHOP}, {@link
* Opcodes#F_SAME} or {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed frames.
* @param numLocal number of local variables of this stack map frame.
* @param local the types of the local variables of this stack map frame. Elements of this list
* can be Integer, String or LabelNode objects (for primitive, reference and uninitialized
* types respectively - see {@link MethodVisitor}).
* @param numStack number of operand stack elements of this stack map frame.
* @param stack the types of the operand stack elements of this stack map frame. Elements of this
* list can be Integer, String or LabelNode objects (for primitive, reference and
* uninitialized types respectively - see {@link MethodVisitor}).
*/
public FrameNode(
final int type,
final int numLocal,
final Object[] local,
final int numStack,
final Object[] stack) {
super(-1);
this.type = type;
switch (type) {
case Opcodes.F_NEW:
case Opcodes.F_FULL:
this.local = Util.asArrayList(numLocal, local);
this.stack = Util.asArrayList(numStack, stack);
break;
case Opcodes.F_APPEND:
this.local = Util.asArrayList(numLocal, local);
break;
case Opcodes.F_CHOP:
this.local = Util.asArrayList(numLocal);
break;
case Opcodes.F_SAME:
break;
case Opcodes.F_SAME1:
this.stack = Util.asArrayList(1, stack);
break;
default:
throw new IllegalArgumentException();
}
}
@Override
public void visitFrame(
final int type,
final int numLocal,
final Object[] local,
final int numStack,
final Object[] stack) {
stringBuilder.setLength(0);
stringBuilder.append(ltab);
stringBuilder.append("FRAME ");
switch (type) {
case Opcodes.F_NEW:
case Opcodes.F_FULL:
stringBuilder.append("FULL [");
appendFrameTypes(numLocal, local);
stringBuilder.append("] [");
appendFrameTypes(numStack, stack);
stringBuilder.append(']');
break;
case Opcodes.F_APPEND:
stringBuilder.append("APPEND [");
appendFrameTypes(numLocal, local);
stringBuilder.append(']');
break;
case Opcodes.F_CHOP:
stringBuilder.append("CHOP ").append(numLocal);
break;
case Opcodes.F_SAME:
stringBuilder.append("SAME");
break;
case Opcodes.F_SAME1:
stringBuilder.append("SAME1 ");
appendFrameTypes(1, stack);
break;
default:
throw new IllegalArgumentException();
}
stringBuilder.append('\n');
text.add(stringBuilder.toString());
}
/**
* Constructs a new {@link FrameNode}.
*
* @param type the type of this frame. Must be {@link Opcodes#F_NEW} for expanded frames, or
* {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND}, {@link Opcodes#F_CHOP}, {@link
* Opcodes#F_SAME} or {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed frames.
* @param numLocal number of local variables of this stack map frame.
* @param local the types of the local variables of this stack map frame. Elements of this list
* can be Integer, String or LabelNode objects (for primitive, reference and uninitialized
* types respectively - see {@link MethodVisitor}).
* @param numStack number of operand stack elements of this stack map frame.
* @param stack the types of the operand stack elements of this stack map frame. Elements of this
* list can be Integer, String or LabelNode objects (for primitive, reference and
* uninitialized types respectively - see {@link MethodVisitor}).
*/
public FrameNode(
final int type,
final int numLocal,
final Object[] local,
final int numStack,
final Object[] stack) {
super(-1);
this.type = type;
switch (type) {
case Opcodes.F_NEW:
case Opcodes.F_FULL:
this.local = Util.asArrayList(numLocal, local);
this.stack = Util.asArrayList(numStack, stack);
break;
case Opcodes.F_APPEND:
this.local = Util.asArrayList(numLocal, local);
break;
case Opcodes.F_CHOP:
this.local = Util.asArrayList(numLocal);
break;
case Opcodes.F_SAME:
break;
case Opcodes.F_SAME1:
this.stack = Util.asArrayList(1, stack);
break;
default:
throw new IllegalArgumentException();
}
}
@Override
public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
switch (type) {
case Opcodes.F_NEW:
// Expanded form.
previousFrame =
FrameInfo.create(
convertTypesInStackMapFrame(nLocal, local),
convertTypesInStackMapFrame(nStack, stack));
break;
case Opcodes.F_SAME:
// This frame type indicates that the frame has exactly the same local variables as the
// previous frame and that the operand stack is empty.
previousFrame = FrameInfo.create(previousFrame.locals(), ImmutableList.of());
break;
case Opcodes.F_SAME1:
// This frame type indicates that the frame has exactly the same local variables as the
// previous frame and that the operand stack has one entry.
previousFrame =
FrameInfo.create(previousFrame.locals(), convertTypesInStackMapFrame(nStack, stack));
break;
case Opcodes.F_APPEND:
// This frame type indicates that the frame has the same locals as the previous frame except
// that k additional locals are defined, and that the operand stack is empty.
previousFrame =
FrameInfo.create(
appendArrayToList(previousFrame.locals(), nLocal, local), ImmutableList.of());
break;
case Opcodes.F_CHOP:
// This frame type indicates that the frame has the same local variables as the previous
// frame except that the last k local variables are absent, and that the operand stack is
// empty.
previousFrame =
FrameInfo.create(
removeBackFromList(previousFrame.locals(), nLocal), ImmutableList.of());
break;
case Opcodes.F_FULL:
previousFrame =
FrameInfo.create(
convertTypesInStackMapFrame(nLocal, local),
convertTypesInStackMapFrame(nStack, stack));
break;
default:
// continue below
}
// Update types for operand stack and local variables.
operandStack.clear();
operandStack.addAll(previousFrame.stack());
localVariableSlots.clear();
localVariableSlots.addAll(previousFrame.locals());
super.visitFrame(type, nLocal, local, nStack, stack);
}
@Override
public void visitFrame(
final int type,
final int numLocal,
final Object[] local,
final int numStack,
final Object[] stack) {
stringBuilder.setLength(0);
switch (type) {
case Opcodes.F_NEW:
case Opcodes.F_FULL:
declareFrameTypes(numLocal, local);
declareFrameTypes(numStack, stack);
if (type == Opcodes.F_NEW) {
stringBuilder.append(name).append(".visitFrame(Opcodes.F_NEW, ");
} else {
stringBuilder.append(name).append(".visitFrame(Opcodes.F_FULL, ");
}
stringBuilder.append(numLocal).append(NEW_OBJECT_ARRAY);
appendFrameTypes(numLocal, local);
stringBuilder.append("}, ").append(numStack).append(NEW_OBJECT_ARRAY);
appendFrameTypes(numStack, stack);
stringBuilder.append('}');
break;
case Opcodes.F_APPEND:
declareFrameTypes(numLocal, local);
stringBuilder
.append(name)
.append(".visitFrame(Opcodes.F_APPEND,")
.append(numLocal)
.append(NEW_OBJECT_ARRAY);
appendFrameTypes(numLocal, local);
stringBuilder.append("}, 0, null");
break;
case Opcodes.F_CHOP:
stringBuilder
.append(name)
.append(".visitFrame(Opcodes.F_CHOP,")
.append(numLocal)
.append(", null, 0, null");
break;
case Opcodes.F_SAME:
stringBuilder.append(name).append(".visitFrame(Opcodes.F_SAME, 0, null, 0, null");
break;
case Opcodes.F_SAME1:
declareFrameTypes(1, stack);
stringBuilder
.append(name)
.append(".visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {");
appendFrameTypes(1, stack);
stringBuilder.append('}');
break;
default:
throw new IllegalArgumentException();
}
stringBuilder.append(");\n");
text.add(stringBuilder.toString());
}
@Override
public void visitFrame(
final int type,
final int numLocal,
final Object[] local,
final int numStack,
final Object[] stack) {
if (insnCount == lastFrameInsnIndex) {
throw new IllegalStateException("At most one frame can be visited at a given code location.");
}
lastFrameInsnIndex = insnCount;
int maxNumLocal;
int maxNumStack;
switch (type) {
case Opcodes.F_NEW:
case Opcodes.F_FULL:
maxNumLocal = Integer.MAX_VALUE;
maxNumStack = Integer.MAX_VALUE;
break;
case Opcodes.F_SAME:
maxNumLocal = 0;
maxNumStack = 0;
break;
case Opcodes.F_SAME1:
maxNumLocal = 0;
maxNumStack = 1;
break;
case Opcodes.F_APPEND:
case Opcodes.F_CHOP:
maxNumLocal = 3;
maxNumStack = 0;
break;
default:
throw new IllegalArgumentException("Invalid frame type " + type);
}
if (numLocal > maxNumLocal) {
throw new IllegalArgumentException(
"Invalid numLocal=" + numLocal + " for frame type " + type);
}
if (numStack > maxNumStack) {
throw new IllegalArgumentException(
"Invalid numStack=" + numStack + " for frame type " + type);
}
if (type != Opcodes.F_CHOP) {
if (numLocal > 0 && (local == null || local.length < numLocal)) {
throw new IllegalArgumentException("Array local[] is shorter than numLocal");
}
for (int i = 0; i < numLocal; ++i) {
checkFrameValue(local[i]);
}
}
if (numStack > 0 && (stack == null || stack.length < numStack)) {
throw new IllegalArgumentException("Array stack[] is shorter than numStack");
}
for (int i = 0; i < numStack; ++i) {
checkFrameValue(stack[i]);
}
if (type == Opcodes.F_NEW) {
++numExpandedFrames;
} else {
++numCompressedFrames;
}
if (numExpandedFrames > 0 && numCompressedFrames > 0) {
throw new IllegalArgumentException("Expanded and compressed frames must not be mixed.");
}
super.visitFrame(type, numLocal, local, numStack, stack);
}
@Override
public void visitFrame(
final int type,
final int numLocal,
final Object[] local,
final int numStack,
final Object[] stack) {
if (insnCount == lastFrameInsnIndex) {
throw new IllegalStateException("At most one frame can be visited at a given code location.");
}
lastFrameInsnIndex = insnCount;
int maxNumLocal;
int maxNumStack;
switch (type) {
case Opcodes.F_NEW:
case Opcodes.F_FULL:
maxNumLocal = Integer.MAX_VALUE;
maxNumStack = Integer.MAX_VALUE;
break;
case Opcodes.F_SAME:
maxNumLocal = 0;
maxNumStack = 0;
break;
case Opcodes.F_SAME1:
maxNumLocal = 0;
maxNumStack = 1;
break;
case Opcodes.F_APPEND:
case Opcodes.F_CHOP:
maxNumLocal = 3;
maxNumStack = 0;
break;
default:
throw new IllegalArgumentException("Invalid frame type " + type);
}
if (numLocal > maxNumLocal) {
throw new IllegalArgumentException(
"Invalid numLocal=" + numLocal + " for frame type " + type);
}
if (numStack > maxNumStack) {
throw new IllegalArgumentException(
"Invalid numStack=" + numStack + " for frame type " + type);
}
if (type != Opcodes.F_CHOP) {
if (numLocal > 0 && (local == null || local.length < numLocal)) {
throw new IllegalArgumentException("Array local[] is shorter than numLocal");
}
for (int i = 0; i < numLocal; ++i) {
checkFrameValue(local[i]);
}
}
if (numStack > 0 && (stack == null || stack.length < numStack)) {
throw new IllegalArgumentException("Array stack[] is shorter than numStack");
}
for (int i = 0; i < numStack; ++i) {
checkFrameValue(stack[i]);
}
if (type == Opcodes.F_NEW) {
++numExpandedFrames;
} else {
++numCompressedFrames;
}
if (numExpandedFrames > 0 && numCompressedFrames > 0) {
throw new IllegalArgumentException("Expanded and compressed frames must not be mixed.");
}
super.visitFrame(type, numLocal, local, numStack, stack);
}
@Override
public void visitFrame(final int type, final int nLocal, final Object[] local, final int nStack, final Object[] stack) {
buf.setLength(0);
switch (type) {
case Opcodes.F_NEW:
case Opcodes.F_FULL:
declareFrameTypes(nLocal, local);
declareFrameTypes(nStack, stack);
if (type == Opcodes.F_NEW) {
buf.append(name).append(".visitFrame(Opcodes.F_NEW, ");
} else {
buf.append(name).append(".visitFrame(Opcodes.F_FULL, ");
}
buf.append(nLocal).append(", new Object[] {");
appendFrameTypes(nLocal, local);
buf.append("}, ").append(nStack).append(", new Object[] {");
appendFrameTypes(nStack, stack);
buf.append('}');
break;
case Opcodes.F_APPEND:
declareFrameTypes(nLocal, local);
buf.append(name).append(".visitFrame(Opcodes.F_APPEND,").append(nLocal).append(", new Object[] {");
appendFrameTypes(nLocal, local);
buf.append("}, 0, null");
break;
case Opcodes.F_CHOP:
buf.append(name).append(".visitFrame(Opcodes.F_CHOP,").append(nLocal).append(", null, 0, null");
break;
case Opcodes.F_SAME:
buf.append(name).append(".visitFrame(Opcodes.F_SAME, 0, null, 0, null");
break;
case Opcodes.F_SAME1:
declareFrameTypes(1, stack);
buf.append(name).append(".visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {");
appendFrameTypes(1, stack);
buf.append('}');
break;
}
buf.append(");\n");
text.add(buf.toString());
}
@Override
public void visitFrame(final int type, final int nLocal, final Object[] local, final int nStack, final Object[] stack) {
if (insnCount == lastFrame) {
throw new IllegalStateException("At most one frame can be visited at a given code location.");
}
lastFrame = insnCount;
int mLocal;
int mStack;
switch (type) {
case Opcodes.F_NEW:
case Opcodes.F_FULL:
mLocal = Integer.MAX_VALUE;
mStack = Integer.MAX_VALUE;
break;
case Opcodes.F_SAME:
mLocal = 0;
mStack = 0;
break;
case Opcodes.F_SAME1:
mLocal = 0;
mStack = 1;
break;
case Opcodes.F_APPEND:
case Opcodes.F_CHOP:
mLocal = 3;
mStack = 0;
break;
default:
throw new IllegalArgumentException("Invalid frame type " + type);
}
if (nLocal > mLocal) {
throw new IllegalArgumentException("Invalid nLocal=" + nLocal + " for frame type " + type);
}
if (nStack > mStack) {
throw new IllegalArgumentException("Invalid nStack=" + nStack + " for frame type " + type);
}
if (type != Opcodes.F_CHOP) {
if (nLocal > 0 && (local == null || local.length < nLocal)) {
throw new IllegalArgumentException("Array local[] is shorter than nLocal");
}
for (int i = 0; i < nLocal; ++i) {
checkFrameValue(local[i]);
}
}
if (nStack > 0 && (stack == null || stack.length < nStack)) {
throw new IllegalArgumentException("Array stack[] is shorter than nStack");
}
for (int i = 0; i < nStack; ++i) {
checkFrameValue(stack[i]);
}
if (type == Opcodes.F_NEW) {
++expandedFrames;
} else {
++compressedFrames;
}
if (expandedFrames > 0 && compressedFrames > 0) {
throw new RuntimeException("Expanded and compressed frames must not be mixed.");
}
super.visitFrame(type, nLocal, local, nStack, stack);
}
@Override
public void visitFrame(
final int type,
final int numLocal,
final Object[] local,
final int numStack,
final Object[] stack) {
stringBuilder.setLength(0);
switch (type) {
case Opcodes.F_NEW:
case Opcodes.F_FULL:
declareFrameTypes(numLocal, local);
declareFrameTypes(numStack, stack);
if (type == Opcodes.F_NEW) {
stringBuilder.append(name).append(".visitFrame(Opcodes.F_NEW, ");
} else {
stringBuilder.append(name).append(".visitFrame(Opcodes.F_FULL, ");
}
stringBuilder.append(numLocal).append(NEW_OBJECT_ARRAY);
appendFrameTypes(numLocal, local);
stringBuilder.append("}, ").append(numStack).append(NEW_OBJECT_ARRAY);
appendFrameTypes(numStack, stack);
stringBuilder.append('}');
break;
case Opcodes.F_APPEND:
declareFrameTypes(numLocal, local);
stringBuilder
.append(name)
.append(".visitFrame(Opcodes.F_APPEND,")
.append(numLocal)
.append(NEW_OBJECT_ARRAY);
appendFrameTypes(numLocal, local);
stringBuilder.append("}, 0, null");
break;
case Opcodes.F_CHOP:
stringBuilder
.append(name)
.append(".visitFrame(Opcodes.F_CHOP,")
.append(numLocal)
.append(", null, 0, null");
break;
case Opcodes.F_SAME:
stringBuilder.append(name).append(".visitFrame(Opcodes.F_SAME, 0, null, 0, null");
break;
case Opcodes.F_SAME1:
declareFrameTypes(1, stack);
stringBuilder
.append(name)
.append(".visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {");
appendFrameTypes(1, stack);
stringBuilder.append('}');
break;
default:
throw new IllegalArgumentException();
}
stringBuilder.append(");\n");
text.add(stringBuilder.toString());
}
@Override
public void visitFrame(
final int type,
final int numLocal,
final Object[] local,
final int numStack,
final Object[] stack) {
if (insnCount == lastFrameInsnIndex) {
throw new IllegalStateException("At most one frame can be visited at a given code location.");
}
lastFrameInsnIndex = insnCount;
int maxNumLocal;
int maxNumStack;
switch (type) {
case Opcodes.F_NEW:
case Opcodes.F_FULL:
maxNumLocal = Integer.MAX_VALUE;
maxNumStack = Integer.MAX_VALUE;
break;
case Opcodes.F_SAME:
maxNumLocal = 0;
maxNumStack = 0;
break;
case Opcodes.F_SAME1:
maxNumLocal = 0;
maxNumStack = 1;
break;
case Opcodes.F_APPEND:
case Opcodes.F_CHOP:
maxNumLocal = 3;
maxNumStack = 0;
break;
default:
throw new IllegalArgumentException("Invalid frame type " + type);
}
if (numLocal > maxNumLocal) {
throw new IllegalArgumentException(
"Invalid numLocal=" + numLocal + " for frame type " + type);
}
if (numStack > maxNumStack) {
throw new IllegalArgumentException(
"Invalid numStack=" + numStack + " for frame type " + type);
}
if (type != Opcodes.F_CHOP) {
if (numLocal > 0 && (local == null || local.length < numLocal)) {
throw new IllegalArgumentException("Array local[] is shorter than numLocal");
}
for (int i = 0; i < numLocal; ++i) {
checkFrameValue(local[i]);
}
}
if (numStack > 0 && (stack == null || stack.length < numStack)) {
throw new IllegalArgumentException("Array stack[] is shorter than numStack");
}
for (int i = 0; i < numStack; ++i) {
checkFrameValue(stack[i]);
}
if (type == Opcodes.F_NEW) {
++numExpandedFrames;
} else {
++numCompressedFrames;
}
if (numExpandedFrames > 0 && numCompressedFrames > 0) {
throw new IllegalArgumentException("Expanded and compressed frames must not be mixed.");
}
super.visitFrame(type, numLocal, local, numStack, stack);
}