📄 frame.java
字号:
/**
* Pops a type from the output frame stack.
*
* @param desc the descriptor of the type to be popped. Can also be a method
* descriptor (in this case this method pops the types corresponding
* to the method arguments).
*/
private void pop(final String desc) {
char c = desc.charAt(0);
if (c == '(') {
pop((MethodWriter.getArgumentsAndReturnSizes(desc) >> 2) - 1);
} else if (c == 'J' || c == 'D') {
pop(2);
} else {
pop(1);
}
}
/**
* Adds a new type to the list of types on which a constructor is invoked in
* the basic block.
*
* @param var a type on a which a constructor is invoked.
*/
private void init(final int var) {
// creates and/or resizes the initializations array if necessary
if (initializations == null) {
initializations = new int[2];
}
int n = initializations.length;
if (initializationCount >= n) {
int[] t = new int[Math.max(initializationCount + 1, 2 * n)];
System.arraycopy(initializations, 0, t, 0, n);
initializations = t;
}
// stores the type to be initialized
initializations[initializationCount++] = var;
}
/**
* Replaces the given type with the appropriate type if it is one of the
* types on which a constructor is invoked in the basic block.
*
* @param cw the ClassWriter to which this label belongs.
* @param t a type
* @return t or, if t is one of the types on which a constructor is invoked
* in the basic block, the type corresponding to this constructor.
*/
private int init(final ClassWriter cw, final int t) {
int s;
if (t == UNINITIALIZED_THIS) {
s = OBJECT | cw.addType(cw.thisName);
} else if ((t & (DIM | BASE_KIND)) == UNINITIALIZED) {
String type = cw.typeTable[t & BASE_VALUE].strVal1;
s = OBJECT | cw.addType(type);
} else {
return t;
}
for (int j = 0; j < initializationCount; ++j) {
int u = initializations[j];
int dim = u & DIM;
int kind = u & KIND;
if (kind == LOCAL) {
u = dim + inputLocals[u & VALUE];
} else if (kind == STACK) {
u = dim + inputStack[inputStack.length - (u & VALUE)];
}
if (t == u) {
return s;
}
}
return t;
}
/**
* Initializes the input frame of the first basic block from the method
* descriptor.
*
* @param cw the ClassWriter to which this label belongs.
* @param access the access flags of the method to which this label belongs.
* @param args the formal parameter types of this method.
* @param maxLocals the maximum number of local variables of this method.
*/
void initInputFrame(
final ClassWriter cw,
final int access,
final Type[] args,
final int maxLocals)
{
inputLocals = new int[maxLocals];
inputStack = new int[0];
int i = 0;
if ((access & Opcodes.ACC_STATIC) == 0) {
if ((access & MethodWriter.ACC_CONSTRUCTOR) == 0) {
inputLocals[i++] = OBJECT | cw.addType(cw.thisName);
} else {
inputLocals[i++] = UNINITIALIZED_THIS;
}
}
for (int j = 0; j < args.length; ++j) {
int t = type(cw, args[j].getDescriptor());
inputLocals[i++] = t;
if (t == LONG || t == DOUBLE) {
inputLocals[i++] = TOP;
}
}
while (i < maxLocals) {
inputLocals[i++] = TOP;
}
}
/**
* Simulates the action of the given instruction on the output stack frame.
*
* @param opcode the opcode of the instruction.
* @param arg the operand of the instruction, if any.
* @param cw the class writer to which this label belongs.
* @param item the operand of the instructions, if any.
*/
void execute(
final int opcode,
final int arg,
final ClassWriter cw,
final Item item)
{
int t1, t2, t3, t4;
switch (opcode) {
case Opcodes.NOP:
case Opcodes.INEG:
case Opcodes.LNEG:
case Opcodes.FNEG:
case Opcodes.DNEG:
case Opcodes.I2B:
case Opcodes.I2C:
case Opcodes.I2S:
case Opcodes.GOTO:
case Opcodes.RETURN:
break;
case Opcodes.ACONST_NULL:
push(NULL);
break;
case Opcodes.ICONST_M1:
case Opcodes.ICONST_0:
case Opcodes.ICONST_1:
case Opcodes.ICONST_2:
case Opcodes.ICONST_3:
case Opcodes.ICONST_4:
case Opcodes.ICONST_5:
case Opcodes.BIPUSH:
case Opcodes.SIPUSH:
case Opcodes.ILOAD:
push(INTEGER);
break;
case Opcodes.LCONST_0:
case Opcodes.LCONST_1:
case Opcodes.LLOAD:
push(LONG);
push(TOP);
break;
case Opcodes.FCONST_0:
case Opcodes.FCONST_1:
case Opcodes.FCONST_2:
case Opcodes.FLOAD:
push(FLOAT);
break;
case Opcodes.DCONST_0:
case Opcodes.DCONST_1:
case Opcodes.DLOAD:
push(DOUBLE);
push(TOP);
break;
case Opcodes.LDC:
switch (item.type) {
case ClassWriter.INT:
push(INTEGER);
break;
case ClassWriter.LONG:
push(LONG);
push(TOP);
break;
case ClassWriter.FLOAT:
push(FLOAT);
break;
case ClassWriter.DOUBLE:
push(DOUBLE);
push(TOP);
break;
case ClassWriter.CLASS:
push(OBJECT | cw.addType("java/lang/Class"));
break;
// case ClassWriter.STR:
default:
push(OBJECT | cw.addType("java/lang/String"));
}
break;
case Opcodes.ALOAD:
push(get(arg));
break;
case Opcodes.IALOAD:
case Opcodes.BALOAD:
case Opcodes.CALOAD:
case Opcodes.SALOAD:
pop(2);
push(INTEGER);
break;
case Opcodes.LALOAD:
case Opcodes.D2L:
pop(2);
push(LONG);
push(TOP);
break;
case Opcodes.FALOAD:
pop(2);
push(FLOAT);
break;
case Opcodes.DALOAD:
case Opcodes.L2D:
pop(2);
push(DOUBLE);
push(TOP);
break;
case Opcodes.AALOAD:
pop(1);
t1 = pop();
push(ELEMENT_OF + t1);
break;
case Opcodes.ISTORE:
case Opcodes.FSTORE:
case Opcodes.ASTORE:
t1 = pop();
set(arg, t1);
if (arg > 0) {
t2 = get(arg - 1);
// if t2 is of kind STACK or LOCAL we cannot know its size!
if (t2 == LONG || t2 == DOUBLE) {
set(arg - 1, TOP);
}
}
break;
case Opcodes.LSTORE:
case Opcodes.DSTORE:
pop(1);
t1 = pop();
set(arg, t1);
set(arg + 1, TOP);
if (arg > 0) {
t2 = get(arg - 1);
// if t2 is of kind STACK or LOCAL we cannot know its size!
if (t2 == LONG || t2 == DOUBLE) {
set(arg - 1, TOP);
}
}
break;
case Opcodes.IASTORE:
case Opcodes.BASTORE:
case Opcodes.CASTORE:
case Opcodes.SASTORE:
case Opcodes.FASTORE:
case Opcodes.AASTORE:
pop(3);
break;
case Opcodes.LASTORE:
case Opcodes.DASTORE:
pop(4);
break;
case Opcodes.POP:
case Opcodes.IFEQ:
case Opcodes.IFNE:
case Opcodes.IFLT:
case Opcodes.IFGE:
case Opcodes.IFGT:
case Opcodes.IFLE:
case Opcodes.IRETURN:
case Opcodes.FRETURN:
case Opcodes.ARETURN:
case Opcodes.TABLESWITCH:
case Opcodes.LOOKUPSWITCH:
case Opcodes.ATHROW:
case Opcodes.MONITORENTER:
case Opcodes.MONITOREXIT:
case Opcodes.IFNULL:
case Opcodes.IFNONNULL:
pop(1);
break;
case Opcodes.POP2:
case Opcodes.IF_ICMPEQ:
case Opcodes.IF_ICMPNE:
case Opcodes.IF_ICMPLT:
case Opcodes.IF_ICMPGE:
case Opcodes.IF_ICMPGT:
case Opcodes.IF_ICMPLE:
case Opcodes.IF_ACMPEQ:
case Opcodes.IF_ACMPNE:
case Opcodes.LRETURN:
case Opcodes.DRETURN:
pop(2);
break;
case Opcodes.DUP:
t1 = pop();
push(t1);
push(t1);
break;
case Opcodes.DUP_X1:
t1 = pop();
t2 = pop();
push(t1);
push(t2);
push(t1);
break;
case Opcodes.DUP_X2:
t1 = pop();
t2 = pop();
t3 = pop();
push(t1);
push(t3);
push(t2);
push(t1);
break;
case Opcodes.DUP2:
t1 = pop();
t2 = pop();
push(t2);
push(t1);
push(t2);
push(t1);
break;
case Opcodes.DUP2_X1:
t1 = pop();
t2 = pop();
t3 = pop();
push(t2);
push(t1);
push(t3);
push(t2);
push(t1);
break;
case Opcodes.DUP2_X2:
t1 = pop();
t2 = pop();
t3 = pop();
t4 = pop();
push(t2);
push(t1);
push(t4);
push(t3);
push(t2);
push(t1);
break;
case Opcodes.SWAP:
t1 = pop();
t2 = pop();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -