bytecodehelper.java
来自「Groovy动态语言 运行在JVM中的动态语言 可以方便的处理业务逻辑变化大的业」· Java 代码 · 共 709 行 · 第 1/2 页
JAVA
709 行
cv.visitTypeInsn(
CHECKCAST,
type.isArray() ? getTypeDescription(type) : getClassInternalName(type));
}
}
public void load(ClassNode type, int idx) {
if (type==ClassHelper.double_TYPE) {
cv.visitVarInsn(DLOAD, idx);
}
else if (type==ClassHelper.float_TYPE) {
cv.visitVarInsn(FLOAD, idx);
}
else if (type==ClassHelper.long_TYPE) {
cv.visitVarInsn(LLOAD, idx);
}
else if (
type==ClassHelper.boolean_TYPE
|| type==ClassHelper.char_TYPE
|| type==ClassHelper.byte_TYPE
|| type==ClassHelper.int_TYPE
|| type==ClassHelper.short_TYPE)
{
cv.visitVarInsn(ILOAD, idx);
}
else {
cv.visitVarInsn(ALOAD, idx);
}
}
public void load(Variable v) {
load(v.getType(), v.getIndex());
}
public void store(Variable v, boolean markStart) {
ClassNode type = v.getType();
unbox(type);
int idx = v.getIndex();
if (type==ClassHelper.double_TYPE) {
cv.visitVarInsn(DSTORE, idx);
}
else if (type==ClassHelper.float_TYPE) {
cv.visitVarInsn(FSTORE, idx);
}
else if (type==ClassHelper.long_TYPE) {
cv.visitVarInsn(LSTORE, idx);
}
else if (
type==ClassHelper.boolean_TYPE
|| type==ClassHelper.char_TYPE
|| type==ClassHelper.byte_TYPE
|| type==ClassHelper.int_TYPE
|| type==ClassHelper.short_TYPE) {
cv.visitVarInsn(ISTORE, idx);
}
else {
cv.visitVarInsn(ASTORE, idx);
}
}
public void store(Variable v) {
store(v, false);
}
/**
* load the constant on the operand stack. primitives auto-boxed.
*/
void loadConstant (Object value) {
if (value == null) {
cv.visitInsn(ACONST_NULL);
}
else if (value instanceof String) {
cv.visitLdcInsn(value);
}
else if (value instanceof Character) {
String className = "java/lang/Character";
cv.visitTypeInsn(NEW, className);
cv.visitInsn(DUP);
cv.visitLdcInsn(value);
String methodType = "(C)V";
cv.visitMethodInsn(INVOKESPECIAL, className, "<init>", methodType);
}
else if (value instanceof Number) {
/** todo it would be more efficient to generate class constants */
Number n = (Number) value;
String className = BytecodeHelper.getClassInternalName(value.getClass().getName());
cv.visitTypeInsn(NEW, className);
cv.visitInsn(DUP);
String methodType;
if (n instanceof Integer) {
//pushConstant(n.intValue());
cv.visitLdcInsn(n);
methodType = "(I)V";
}
else if (n instanceof Double) {
cv.visitLdcInsn(n);
methodType = "(D)V";
}
else if (n instanceof Float) {
cv.visitLdcInsn(n);
methodType = "(F)V";
}
else if (n instanceof Long) {
cv.visitLdcInsn(n);
methodType = "(J)V";
}
else if (n instanceof BigDecimal) {
cv.visitLdcInsn(n.toString());
methodType = "(Ljava/lang/String;)V";
}
else if (n instanceof BigInteger) {
cv.visitLdcInsn(n.toString());
methodType = "(Ljava/lang/String;)V";
}
else if (n instanceof Short) {
cv.visitLdcInsn(n);
methodType = "(S)V";
}
else if (n instanceof Byte) {
cv.visitLdcInsn(n);
methodType = "(B)V";
}
else {
throw new ClassGeneratorException(
"Cannot generate bytecode for constant: " + value
+ " of type: " + value.getClass().getName()
+ ". Numeric constant type not supported.");
}
cv.visitMethodInsn(INVOKESPECIAL, className, "<init>", methodType);
}
else if (value instanceof Boolean) {
Boolean bool = (Boolean) value;
String text = (bool.booleanValue()) ? "TRUE" : "FALSE";
cv.visitFieldInsn(GETSTATIC, "java/lang/Boolean", text, "Ljava/lang/Boolean;");
}
else if (value instanceof Class) {
Class vc = (Class) value;
if (vc.getName().equals("java.lang.Void")) {
// load nothing here for void
} else {
throw new ClassGeneratorException(
"Cannot generate bytecode for constant: " + value + " of type: " + value.getClass().getName());
}
}
else {
throw new ClassGeneratorException(
"Cannot generate bytecode for constant: " + value + " of type: " + value.getClass().getName());
}
}
/**
* load the value of the variable on the operand stack. unbox it if it's a reference
* @param variable
*/
public void loadVar(Variable variable) {
int index = variable.getIndex();
if (variable.isHolder()) {
cv.visitVarInsn(ALOAD, index);
cv.visitMethodInsn(INVOKEVIRTUAL, "groovy/lang/Reference", "get", "()Ljava/lang/Object;");
} else {
load(variable);
if (variable!=Variable.THIS_VARIABLE && variable!=Variable.SUPER_VARIABLE) {
box(variable.getType());
}
}
}
public void storeVar(Variable variable) {
String type = variable.getTypeName();
int index = variable.getIndex();
if (variable.isHolder()) {
cv.visitVarInsn(ALOAD, index);
cv.visitInsn(SWAP);
cv.visitMethodInsn(INVOKEVIRTUAL, "groovy/lang/Reference", "set", "(Ljava/lang/Object;)V");
}
else {
store(variable,false);
}
}
public void putField(FieldNode fld) {
putField(fld, getClassInternalName(fld.getOwner()));
}
public void putField(FieldNode fld, String ownerName) {
cv.visitFieldInsn(PUTFIELD, ownerName, fld.getName(), getTypeDescription(fld.getType()));
}
public void swapObjectWith(ClassNode type) {
if (type==ClassHelper.long_TYPE || type==ClassHelper.double_TYPE) {
cv.visitInsn(DUP_X2);
cv.visitInsn(POP);
} else {
cv.visitInsn(SWAP);
}
}
public void swapWithObject(ClassNode type) {
if (type==ClassHelper.long_TYPE || type==ClassHelper.double_TYPE) {
cv.visitInsn(DUP2_X1);
cv.visitInsn(POP2);
} else {
cv.visitInsn(SWAP);
}
}
public static ClassNode boxOnPrimitive(ClassNode type) {
if (!type.isArray()) return ClassHelper.getWrapper(type);
return boxOnPrimitive(type.getComponentType()).makeArray();
}
/**
* convert boolean to Boolean
*/
public void boxBoolean() {
Label l0 = new Label();
cv.visitJumpInsn(IFEQ, l0);
cv.visitFieldInsn(GETSTATIC, "java/lang/Boolean", "TRUE", "Ljava/lang/Boolean;");
Label l1 = new Label();
cv.visitJumpInsn(GOTO, l1);
cv.visitLabel(l0);
cv.visitFieldInsn(GETSTATIC, "java/lang/Boolean", "FALSE", "Ljava/lang/Boolean;");
cv.visitLabel(l1);
}
/**
* negate a boolean on stack. true->false, false->true
*/
public void negateBoolean(){
// code to negate the primitive boolean
Label endLabel = new Label();
Label falseLabel = new Label();
cv.visitJumpInsn(IFNE,falseLabel);
cv.visitInsn(ICONST_1);
cv.visitJumpInsn(GOTO,endLabel);
cv.visitLabel(falseLabel);
cv.visitInsn(ICONST_0);
cv.visitLabel(endLabel);
}
/**
* load a message on the stack and remove it right away. Good for put a mark in the generated bytecode for debugging purpose.
* @param msg
*/
public void mark(String msg) {
cv.visitLdcInsn(msg);
cv.visitInsn(POP);
}
/**
* returns a name that Class.forName() can take. Notablely for arrays:
* [I, [Ljava.lang.String; etc
* Regular object type: java.lang.String
* @param name
*/
public static String formatNameForClassLoading(String name) {
if (name.equals("int")
|| name.equals("long")
|| name.equals("short")
|| name.equals("float")
|| name.equals("double")
|| name.equals("byte")
|| name.equals("char")
|| name.equals("boolean")
|| name.equals("void")
) {
return name;
}
if (name == null) {
return "java.lang.Object;";
}
if (name.startsWith("[")) {
return name.replace('/', '.');
}
if (name.startsWith("L")) {
name = name.substring(1);
if (name.endsWith(";")) {
name = name.substring(0, name.length() - 1);
}
return name.replace('/', '.');
}
String prefix = "";
if (name.endsWith("[]")) { // todo need process multi
prefix = "[";
name = name.substring(0, name.length() - 2);
if (name.equals("int")) {
return prefix + "I";
}
else if (name.equals("long")) {
return prefix + "J";
}
else if (name.equals("short")) {
return prefix + "S";
}
else if (name.equals("float")) {
return prefix + "F";
}
else if (name.equals("double")) {
return prefix + "D";
}
else if (name.equals("byte")) {
return prefix + "B";
}
else if (name.equals("char")) {
return prefix + "C";
}
else if (name.equals("boolean")) {
return prefix + "Z";
}
else {
return prefix + "L" + name.replace('/', '.') + ";";
}
}
return name.replace('/', '.');
}
public void dup() {
cv.visitInsn(DUP);
}
public void doReturn(ClassNode returnType) {
if (returnType==ClassHelper.double_TYPE) {
cv.visitInsn(DRETURN);
} else if (returnType==ClassHelper.float_TYPE) {
cv.visitInsn(FRETURN);
} else if (returnType==ClassHelper.long_TYPE) {
cv.visitInsn(LRETURN);
} else if (
returnType==ClassHelper.boolean_TYPE
|| returnType==ClassHelper.char_TYPE
|| returnType==ClassHelper.byte_TYPE
|| returnType==ClassHelper.int_TYPE
|| returnType==ClassHelper.short_TYPE)
{
//byte,short,boolean,int are all IRETURN
cv.visitInsn(IRETURN);
} else if (returnType==ClassHelper.VOID_TYPE){
cv.visitInsn(RETURN);
} else {
cv.visitInsn(ARETURN);
}
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?