📄 frame.java
字号:
// -2, //DMUL, // -
// -1, //IDIV, // -
// -2, //LDIV, // -
// -1, //FDIV, // -
// -2, //DDIV, // -
// -1, //IREM, // -
// -2, //LREM, // -
// -1, //FREM, // -
// -2, //DREM, // -
// 0, //INEG, // -
// 0, //LNEG, // -
// 0, //FNEG, // -
// 0, //DNEG, // -
// -1, //ISHL, // -
// -1, //LSHL, // -
// -1, //ISHR, // -
// -1, //LSHR, // -
// -1, //IUSHR, // -
// -1, //LUSHR, // -
// -1, //IAND, // -
// -2, //LAND, // -
// -1, //IOR, // -
// -2, //LOR, // -
// -1, //IXOR, // -
// -2, //LXOR, // -
// 0, //IINC, // visitIincInsn
// 1, //I2L, // visitInsn
// 0, //I2F, // -
// 1, //I2D, // -
// -1, //L2I, // -
// -1, //L2F, // -
// 0, //L2D, // -
// 0, //F2I, // -
// 1, //F2L, // -
// 1, //F2D, // -
// -1, //D2I, // -
// 0, //D2L, // -
// -1, //D2F, // -
// 0, //I2B, // -
// 0, //I2C, // -
// 0, //I2S, // -
// -3, //LCMP, // -
// -1, //FCMPL, // -
// -1, //FCMPG, // -
// -3, //DCMPL, // -
// -3, //DCMPG, // -
// -1, //IFEQ, // visitJumpInsn
// -1, //IFNE, // -
// -1, //IFLT, // -
// -1, //IFGE, // -
// -1, //IFGT, // -
// -1, //IFLE, // -
// -2, //IF_ICMPEQ, // -
// -2, //IF_ICMPNE, // -
// -2, //IF_ICMPLT, // -
// -2, //IF_ICMPGE, // -
// -2, //IF_ICMPGT, // -
// -2, //IF_ICMPLE, // -
// -2, //IF_ACMPEQ, // -
// -2, //IF_ACMPNE, // -
// 0, //GOTO, // -
// 1, //JSR, // -
// 0, //RET, // visitVarInsn
// -1, //TABLESWITCH, // visiTableSwitchInsn
// -1, //LOOKUPSWITCH, // visitLookupSwitch
// -1, //IRETURN, // visitInsn
// -2, //LRETURN, // -
// -1, //FRETURN, // -
// -2, //DRETURN, // -
// -1, //ARETURN, // -
// 0, //RETURN, // -
// NA, //GETSTATIC, // visitFieldInsn
// NA, //PUTSTATIC, // -
// NA, //GETFIELD, // -
// NA, //PUTFIELD, // -
// NA, //INVOKEVIRTUAL, // visitMethodInsn
// NA, //INVOKESPECIAL, // -
// NA, //INVOKESTATIC, // -
// NA, //INVOKEINTERFACE, // -
// NA, //UNUSED, // NOT VISITED
// 1, //NEW, // visitTypeInsn
// 0, //NEWARRAY, // visitIntInsn
// 0, //ANEWARRAY, // visitTypeInsn
// 0, //ARRAYLENGTH, // visitInsn
// NA, //ATHROW, // -
// 0, //CHECKCAST, // visitTypeInsn
// 0, //INSTANCEOF, // -
// -1, //MONITORENTER, // visitInsn
// -1, //MONITOREXIT, // -
// NA, //WIDE, // NOT VISITED
// NA, //MULTIANEWARRAY, // visitMultiANewArrayInsn
// -1, //IFNULL, // visitJumpInsn
// -1, //IFNONNULL, // -
// NA, //GOTO_W, // -
// NA, //JSR_W, // -
// };
// for (i = 0; i < b.length; ++i) {
// System.err.print((char)('E' + b[i]));
// }
// System.err.println();
}
/**
* The label (i.e. basic block) to which these input and output stack map
* frames correspond.
*/
Label owner;
/**
* The input stack map frame locals.
*/
int[] inputLocals;
/**
* The input stack map frame stack.
*/
int[] inputStack;
/**
* The output stack map frame locals.
*/
private int[] outputLocals;
/**
* The output stack map frame stack.
*/
private int[] outputStack;
/**
* Relative size of the output stack. The exact semantics of this field
* depends on the algorithm that is used.
*
* When only the maximum stack size is computed, this field is the size of
* the output stack relatively to the top of the input stack.
*
* When the stack map frames are completely computed, this field is the
* actual number of types in {@link #outputStack}.
*/
private int outputStackTop;
/**
* Number of types that are initialized in the basic block.
*
* @see #initializations
*/
private int initializationCount;
/**
* The types that are initialized in the basic block. A constructor
* invocation on an UNINITIALIZED or UNINITIALIZED_THIS type must replace
* <i>every occurence</i> of this type in the local variables and in the
* operand stack. This cannot be done during the first phase of the
* algorithm since, during this phase, the local variables and the operand
* stack are not completely computed. It is therefore necessary to store the
* types on which constructors are invoked in the basic block, in order to
* do this replacement during the second phase of the algorithm, where the
* frames are fully computed. Note that this array can contain types that
* are relative to input locals or to the input stack (see below for the
* description of the algorithm).
*/
private int[] initializations;
/**
* Returns the output frame local variable type at the given index.
*
* @param local the index of the local that must be returned.
* @return the output frame local variable type at the given index.
*/
private int get(final int local) {
if (outputLocals == null || local >= outputLocals.length) {
// this local has never been assigned in this basic block,
// so it is still equal to its value in the input frame
return LOCAL | local;
} else {
int type = outputLocals[local];
if (type == 0) {
// this local has never been assigned in this basic block,
// so it is still equal to its value in the input frame
type = outputLocals[local] = LOCAL | local;
}
return type;
}
}
/**
* Sets the output frame local variable type at the given index.
*
* @param local the index of the local that must be set.
* @param type the value of the local that must be set.
*/
private void set(final int local, final int type) {
// creates and/or resizes the output local variables array if necessary
if (outputLocals == null) {
outputLocals = new int[10];
}
int n = outputLocals.length;
if (local >= n) {
int[] t = new int[Math.max(local + 1, 2 * n)];
System.arraycopy(outputLocals, 0, t, 0, n);
outputLocals = t;
}
// sets the local variable
outputLocals[local] = type;
}
/**
* Pushes a new type onto the output frame stack.
*
* @param type the type that must be pushed.
*/
private void push(final int type) {
// creates and/or resizes the output stack array if necessary
if (outputStack == null) {
outputStack = new int[10];
}
int n = outputStack.length;
if (outputStackTop >= n) {
int[] t = new int[Math.max(outputStackTop + 1, 2 * n)];
System.arraycopy(outputStack, 0, t, 0, n);
outputStack = t;
}
// pushes the type on the output stack
outputStack[outputStackTop++] = type;
// updates the maximun height reached by the output stack, if needed
int top = owner.inputStackTop + outputStackTop;
if (top > owner.outputStackMax) {
owner.outputStackMax = top;
}
}
/**
* Pushes a new type onto the output frame stack.
*
* @param cw the ClassWriter to which this label belongs.
* @param desc the descriptor of the type to be pushed. Can also be a method
* descriptor (in this case this method pushes its return type onto
* the output frame stack).
*/
private void push(final ClassWriter cw, final String desc) {
int type = type(cw, desc);
if (type != 0) {
push(type);
if (type == LONG || type == DOUBLE) {
push(TOP);
}
}
}
/**
* Returns the int encoding of the given type.
*
* @param cw the ClassWriter to which this label belongs.
* @param desc a type descriptor.
* @return the int encoding of the given type.
*/
private int type(final ClassWriter cw, final String desc) {
String t;
int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
switch (desc.charAt(index)) {
case 'V':
return 0;
case 'Z':
case 'C':
case 'B':
case 'S':
case 'I':
return INTEGER;
case 'F':
return FLOAT;
case 'J':
return LONG;
case 'D':
return DOUBLE;
case 'L':
// stores the internal name, not the descriptor!
t = desc.substring(index + 1, desc.length() - 1);
return OBJECT | cw.addType(t);
// case '[':
default:
// extracts the dimensions and the element type
int data;
int dims = index + 1;
while (desc.charAt(dims) == '[') {
++dims;
}
switch (desc.charAt(dims)) {
case 'Z':
data = BOOLEAN;
break;
case 'C':
data = CHAR;
break;
case 'B':
data = BYTE;
break;
case 'S':
data = SHORT;
break;
case 'I':
data = INTEGER;
break;
case 'F':
data = FLOAT;
break;
case 'J':
data = LONG;
break;
case 'D':
data = DOUBLE;
break;
// case 'L':
default:
// stores the internal name, not the descriptor
t = desc.substring(dims + 1, desc.length() - 1);
data = OBJECT | cw.addType(t);
}
return (dims - index) << 28 | data;
}
}
/**
* Pops a type from the output frame stack and returns its value.
*
* @return the type that has been popped from the output frame stack.
*/
private int pop() {
if (outputStackTop > 0) {
return outputStack[--outputStackTop];
} else {
// if the output frame stack is empty, pops from the input stack
return STACK | -(--owner.inputStackTop);
}
}
/**
* Pops the given number of types from the output frame stack.
*
* @param elements the number of types that must be popped.
*/
private void pop(final int elements) {
if (outputStackTop >= elements) {
outputStackTop -= elements;
} else {
// if the number of elements to be popped is greater than the number
// of elements in the output stack, clear it, and pops the remaining
// elements from the input stack.
owner.inputStackTop -= elements - outputStackTop;
outputStackTop = 0;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -