📄 generatoradapter.java
字号:
* @param local the local variable to be incremented.
* @param amount the amount by which the local variable must be incremented.
*/
public void iinc(final int local, final int amount) {
mv.visitIincInsn(local, amount);
}
/**
* Generates the instructions to cast a numerical value from one type to
* another.
*
* @param from the type of the top stack value
* @param to the type into which this value must be cast.
*/
public void cast(final Type from, final Type to) {
if (from != to) {
if (from == Type.DOUBLE_TYPE) {
if (to == Type.FLOAT_TYPE) {
mv.visitInsn(Opcodes.D2F);
} else if (to == Type.LONG_TYPE) {
mv.visitInsn(Opcodes.D2L);
} else {
mv.visitInsn(Opcodes.D2I);
cast(Type.INT_TYPE, to);
}
} else if (from == Type.FLOAT_TYPE) {
if (to == Type.DOUBLE_TYPE) {
mv.visitInsn(Opcodes.F2D);
} else if (to == Type.LONG_TYPE) {
mv.visitInsn(Opcodes.F2L);
} else {
mv.visitInsn(Opcodes.F2I);
cast(Type.INT_TYPE, to);
}
} else if (from == Type.LONG_TYPE) {
if (to == Type.DOUBLE_TYPE) {
mv.visitInsn(Opcodes.L2D);
} else if (to == Type.FLOAT_TYPE) {
mv.visitInsn(Opcodes.L2F);
} else {
mv.visitInsn(Opcodes.L2I);
cast(Type.INT_TYPE, to);
}
} else {
if (to == Type.BYTE_TYPE) {
mv.visitInsn(Opcodes.I2B);
} else if (to == Type.CHAR_TYPE) {
mv.visitInsn(Opcodes.I2C);
} else if (to == Type.DOUBLE_TYPE) {
mv.visitInsn(Opcodes.I2D);
} else if (to == Type.FLOAT_TYPE) {
mv.visitInsn(Opcodes.I2F);
} else if (to == Type.LONG_TYPE) {
mv.visitInsn(Opcodes.I2L);
} else if (to == Type.SHORT_TYPE) {
mv.visitInsn(Opcodes.I2S);
}
}
}
}
// ------------------------------------------------------------------------
// Instructions to do boxing and unboxing operations
// ------------------------------------------------------------------------
/**
* Generates the instructions to box the top stack value. This value is
* replaced by its boxed equivalent on top of the stack.
*
* @param type the type of the top stack value.
*/
public void box(final Type type) {
if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
return;
}
if (type == Type.VOID_TYPE) {
push((String) null);
} else {
Type boxed = type;
switch (type.getSort()) {
case Type.BYTE:
boxed = BYTE_TYPE;
break;
case Type.BOOLEAN:
boxed = BOOLEAN_TYPE;
break;
case Type.SHORT:
boxed = SHORT_TYPE;
break;
case Type.CHAR:
boxed = CHARACTER_TYPE;
break;
case Type.INT:
boxed = INTEGER_TYPE;
break;
case Type.FLOAT:
boxed = FLOAT_TYPE;
break;
case Type.LONG:
boxed = LONG_TYPE;
break;
case Type.DOUBLE:
boxed = DOUBLE_TYPE;
break;
}
newInstance(boxed);
if (type.getSize() == 2) {
// Pp -> Ppo -> oPpo -> ooPpo -> ooPp -> o
dupX2();
dupX2();
pop();
} else {
// p -> po -> opo -> oop -> o
dupX1();
swap();
}
invokeConstructor(boxed, new Method("<init>",
Type.VOID_TYPE,
new Type[] { type }));
}
}
/**
* Generates the instructions to unbox the top stack value. This value is
* replaced by its unboxed equivalent on top of the stack.
*
* @param type the type of the top stack value.
*/
public void unbox(final Type type) {
Type t = NUMBER_TYPE;
Method sig = null;
switch (type.getSort()) {
case Type.VOID:
return;
case Type.CHAR:
t = CHARACTER_TYPE;
sig = CHAR_VALUE;
break;
case Type.BOOLEAN:
t = BOOLEAN_TYPE;
sig = BOOLEAN_VALUE;
break;
case Type.DOUBLE:
sig = DOUBLE_VALUE;
break;
case Type.FLOAT:
sig = FLOAT_VALUE;
break;
case Type.LONG:
sig = LONG_VALUE;
break;
case Type.INT:
case Type.SHORT:
case Type.BYTE:
sig = INT_VALUE;
}
if (sig == null) {
checkCast(type);
} else {
checkCast(t);
invokeVirtual(t, sig);
}
}
// ------------------------------------------------------------------------
// Instructions to jump to other instructions
// ------------------------------------------------------------------------
/**
* Creates a new {@link Label}.
*
* @return a new {@link Label}.
*/
public Label newLabel() {
return new Label();
}
/**
* Marks the current code position with the given label.
*
* @param label a label.
*/
public void mark(final Label label) {
mv.visitLabel(label);
}
/**
* Marks the current code position with a new label.
*
* @return the label that was created to mark the current code position.
*/
public Label mark() {
Label label = new Label();
mv.visitLabel(label);
return label;
}
/**
* Generates the instructions to jump to a label based on the comparison of
* the top two stack values.
*
* @param type the type of the top two stack values.
* @param mode how these values must be compared. One of EQ, NE, LT, GE, GT,
* LE.
* @param label where to jump if the comparison result is <tt>true</tt>.
*/
public void ifCmp(final Type type, final int mode, final Label label) {
int intOp = -1;
switch (type.getSort()) {
case Type.LONG:
mv.visitInsn(Opcodes.LCMP);
break;
case Type.DOUBLE:
mv.visitInsn(Opcodes.DCMPG);
break;
case Type.FLOAT:
mv.visitInsn(Opcodes.FCMPG);
break;
case Type.ARRAY:
case Type.OBJECT:
switch (mode) {
case EQ:
mv.visitJumpInsn(Opcodes.IF_ACMPEQ, label);
return;
case NE:
mv.visitJumpInsn(Opcodes.IF_ACMPNE, label);
return;
}
throw new IllegalArgumentException("Bad comparison for type "
+ type);
default:
switch (mode) {
case EQ:
intOp = Opcodes.IF_ICMPEQ;
break;
case NE:
intOp = Opcodes.IF_ICMPNE;
break;
case GE:
intOp = Opcodes.IF_ICMPGE;
break;
case LT:
intOp = Opcodes.IF_ICMPLT;
break;
case LE:
intOp = Opcodes.IF_ICMPLE;
break;
case GT:
intOp = Opcodes.IF_ICMPGT;
break;
}
mv.visitJumpInsn(intOp, label);
return;
}
int jumpMode = mode;
switch (mode) {
case GE:
jumpMode = LT;
break;
case LE:
jumpMode = GT;
break;
}
mv.visitJumpInsn(jumpMode, label);
}
/**
* Generates the instructions to jump to a label based on the comparison of
* the top two integer stack values.
*
* @param mode how these values must be compared. One of EQ, NE, LT, GE, GT,
* LE.
* @param label where to jump if the comparison result is <tt>true</tt>.
*/
public void ifICmp(final int mode, final Label label) {
ifCmp(Type.INT_TYPE, mode, label);
}
/**
* Generates the instructions to jump to a label based on the comparison of
* the top integer stack value with zero.
*
* @param mode how these values must be compared. One of EQ, NE, LT, GE, GT,
* LE.
* @param label where to jump if the comparison result is <tt>true</tt>.
*/
public void ifZCmp(final int mode, final Label label) {
mv.visitJumpInsn(mode, label);
}
/**
* Generates the instruction to jump to the given label if the top stack
* value is null.
*
* @param label where to jump if the condition is <tt>true</tt>.
*/
public void ifNull(final Label label) {
mv.visitJumpInsn(Opcodes.IFNULL, label);
}
/**
* Generates the instruction to jump to the given label if the top stack
* value is not null.
*
* @param label where to jump if the condition is <tt>true</tt>.
*/
public void ifNonNull(final Label label) {
mv.visitJumpInsn(Opcodes.IFNONNULL, label);
}
/**
* Generates the instruction to jump to the given label.
*
* @param label where to jump if the condition is <tt>true</tt>.
*/
public void goTo(final Label label) {
mv.visitJumpInsn(Opcodes.GOTO, label);
}
/**
* Generates a RET instruction.
*
* @param local a local variable identifier, as returned by
* {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
*/
public void ret(final int local) {
mv.visitVarInsn(Opcodes.RET, local);
}
/**
* Generates the instructions for a switch statement.
*
* @param keys the switch case keys.
* @param generator a generator to generate the code for the switch cases.
*/
public void tableSwitch(
final int[] keys,
final TableSwitchGenerator generator)
{
float density;
if (keys.length == 0) {
density = 0;
} else {
density = (float) keys.length
/ (keys[keys.length - 1] - keys[0] + 1);
}
tableSwitch(keys, generator, density >= 0.5f);
}
/**
* Generates the instructions for a switch statement.
*
* @param keys the switch case keys.
* @param generator a generator to generate the code for the switch cases.
* @param useTable <tt>true</tt> to use a TABLESWITCH instruction, or
* <tt>false</tt> to use a LOOKUPSWITCH instruction.
*/
public void tableSwitch(
final int[] keys,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -