📄 generatoradapter.java
字号:
final TableSwitchGenerator generator,
final boolean useTable)
{
for (int i = 1; i < keys.length; ++i) {
if (keys[i] < keys[i - 1]) {
throw new IllegalArgumentException("keys must be sorted ascending");
}
}
Label def = newLabel();
Label end = newLabel();
if (keys.length > 0) {
int len = keys.length;
int min = keys[0];
int max = keys[len - 1];
int range = max - min + 1;
if (useTable) {
Label[] labels = new Label[range];
Arrays.fill(labels, def);
for (int i = 0; i < len; ++i) {
labels[keys[i] - min] = newLabel();
}
mv.visitTableSwitchInsn(min, max, def, labels);
for (int i = 0; i < range; ++i) {
Label label = labels[i];
if (label != def) {
mark(label);
generator.generateCase(i + min, end);
}
}
} else {
Label[] labels = new Label[len];
for (int i = 0; i < len; ++i) {
labels[i] = newLabel();
}
mv.visitLookupSwitchInsn(def, keys, labels);
for (int i = 0; i < len; ++i) {
mark(labels[i]);
generator.generateCase(keys[i], end);
}
}
}
mark(def);
generator.generateDefault();
mark(end);
}
/**
* Generates the instruction to return the top stack value to the caller.
*/
public void returnValue() {
mv.visitInsn(returnType.getOpcode(Opcodes.IRETURN));
}
// ------------------------------------------------------------------------
// Instructions to load and store fields
// ------------------------------------------------------------------------
/**
* Generates a get field or set field instruction.
*
* @param opcode the instruction's opcode.
* @param ownerType the class in which the field is defined.
* @param name the name of the field.
* @param fieldType the type of the field.
*/
private void fieldInsn(
final int opcode,
final Type ownerType,
final String name,
final Type fieldType)
{
mv.visitFieldInsn(opcode,
ownerType.getInternalName(),
name,
fieldType.getDescriptor());
}
/**
* Generates the instruction to push the value of a static field on the
* stack.
*
* @param owner the class in which the field is defined.
* @param name the name of the field.
* @param type the type of the field.
*/
public void getStatic(final Type owner, final String name, final Type type)
{
fieldInsn(Opcodes.GETSTATIC, owner, name, type);
}
/**
* Generates the instruction to store the top stack value in a static field.
*
* @param owner the class in which the field is defined.
* @param name the name of the field.
* @param type the type of the field.
*/
public void putStatic(final Type owner, final String name, final Type type)
{
fieldInsn(Opcodes.PUTSTATIC, owner, name, type);
}
/**
* Generates the instruction to push the value of a non static field on the
* stack.
*
* @param owner the class in which the field is defined.
* @param name the name of the field.
* @param type the type of the field.
*/
public void getField(final Type owner, final String name, final Type type) {
fieldInsn(Opcodes.GETFIELD, owner, name, type);
}
/**
* Generates the instruction to store the top stack value in a non static
* field.
*
* @param owner the class in which the field is defined.
* @param name the name of the field.
* @param type the type of the field.
*/
public void putField(final Type owner, final String name, final Type type) {
fieldInsn(Opcodes.PUTFIELD, owner, name, type);
}
// ------------------------------------------------------------------------
// Instructions to invoke methods
// ------------------------------------------------------------------------
/**
* Generates an invoke method instruction.
*
* @param opcode the instruction's opcode.
* @param type the class in which the method is defined.
* @param method the method to be invoked.
*/
private void invokeInsn(
final int opcode,
final Type type,
final Method method)
{
String owner = type.getSort() == Type.ARRAY
? type.getDescriptor()
: type.getInternalName();
mv.visitMethodInsn(opcode,
owner,
method.getName(),
method.getDescriptor());
}
/**
* Generates the instruction to invoke a normal method.
*
* @param owner the class in which the method is defined.
* @param method the method to be invoked.
*/
public void invokeVirtual(final Type owner, final Method method) {
invokeInsn(Opcodes.INVOKEVIRTUAL, owner, method);
}
/**
* Generates the instruction to invoke a constructor.
*
* @param type the class in which the constructor is defined.
* @param method the constructor to be invoked.
*/
public void invokeConstructor(final Type type, final Method method) {
invokeInsn(Opcodes.INVOKESPECIAL, type, method);
}
/**
* Generates the instruction to invoke a static method.
*
* @param owner the class in which the method is defined.
* @param method the method to be invoked.
*/
public void invokeStatic(final Type owner, final Method method) {
invokeInsn(Opcodes.INVOKESTATIC, owner, method);
}
/**
* Generates the instruction to invoke an interface method.
*
* @param owner the class in which the method is defined.
* @param method the method to be invoked.
*/
public void invokeInterface(final Type owner, final Method method) {
invokeInsn(Opcodes.INVOKEINTERFACE, owner, method);
}
// ------------------------------------------------------------------------
// Instructions to create objects and arrays
// ------------------------------------------------------------------------
/**
* Generates a type dependent instruction.
*
* @param opcode the instruction's opcode.
* @param type the instruction's operand.
*/
private void typeInsn(final int opcode, final Type type) {
String desc;
if (type.getSort() == Type.ARRAY) {
desc = type.getDescriptor();
} else {
desc = type.getInternalName();
}
mv.visitTypeInsn(opcode, desc);
}
/**
* Generates the instruction to create a new object.
*
* @param type the class of the object to be created.
*/
public void newInstance(final Type type) {
typeInsn(Opcodes.NEW, type);
}
/**
* Generates the instruction to create a new array.
*
* @param type the type of the array elements.
*/
public void newArray(final Type type) {
int typ;
switch (type.getSort()) {
case Type.BOOLEAN:
typ = Opcodes.T_BOOLEAN;
break;
case Type.CHAR:
typ = Opcodes.T_CHAR;
break;
case Type.BYTE:
typ = Opcodes.T_BYTE;
break;
case Type.SHORT:
typ = Opcodes.T_SHORT;
break;
case Type.INT:
typ = Opcodes.T_INT;
break;
case Type.FLOAT:
typ = Opcodes.T_FLOAT;
break;
case Type.LONG:
typ = Opcodes.T_LONG;
break;
case Type.DOUBLE:
typ = Opcodes.T_DOUBLE;
break;
default:
typeInsn(Opcodes.ANEWARRAY, type);
return;
}
mv.visitIntInsn(Opcodes.NEWARRAY, typ);
}
// ------------------------------------------------------------------------
// Miscelaneous instructions
// ------------------------------------------------------------------------
/**
* Generates the instruction to compute the length of an array.
*/
public void arrayLength() {
mv.visitInsn(Opcodes.ARRAYLENGTH);
}
/**
* Generates the instruction to throw an exception.
*/
public void throwException() {
mv.visitInsn(Opcodes.ATHROW);
}
/**
* Generates the instructions to create and throw an exception. The
* exception class must have a constructor with a single String argument.
*
* @param type the class of the exception to be thrown.
* @param msg the detailed message of the exception.
*/
public void throwException(final Type type, final String msg) {
newInstance(type);
dup();
push(msg);
invokeConstructor(type, Method.getMethod("void <init> (String)"));
throwException();
}
/**
* Generates the instruction to check that the top stack value is of the
* given type.
*
* @param type a class or interface type.
*/
public void checkCast(final Type type) {
if (!type.equals(OBJECT_TYPE)) {
typeInsn(Opcodes.CHECKCAST, type);
}
}
/**
* Generates the instruction to test if the top stack value is of the given
* type.
*
* @param type a class or interface type.
*/
public void instanceOf(final Type type) {
typeInsn(Opcodes.INSTANCEOF, type);
}
/**
* Generates the instruction to get the monitor of the top stack value.
*/
public void monitorEnter() {
mv.visitInsn(Opcodes.MONITORENTER);
}
/**
* Generates the instruction to release the monitor of the top stack value.
*/
public void monitorExit() {
mv.visitInsn(Opcodes.MONITOREXIT);
}
// ------------------------------------------------------------------------
// Non instructions
// ------------------------------------------------------------------------
/**
* Marks the end of the visited method.
*/
public void endMethod() {
if ((access & Opcodes.ACC_ABSTRACT) == 0) {
mv.visitMaxs(0, 0);
}
mv.visitEnd();
}
/**
* Marks the start of an exception handler.
*
* @param start beginning of the exception handler's scope (inclusive).
* @param end end of the exception handler's scope (exclusive).
* @param exception internal name of the type of exceptions handled by the
* handler.
*/
public void catchException(
final Label start,
final Label end,
final Type exception)
{
mv.visitTryCatchBlock(start, end, mark(), exception.getInternalName());
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -