📄 bytecodehelper.java
字号:
else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) { cv.visitIntInsn(SIPUSH, value); } else { cv.visitLdcInsn(new Integer(value)); } } } public void doCast(Class type) { if (type!=Object.class) { if (type.isPrimitive() && type!=Void.TYPE) { unbox(type); } else { cv.visitTypeInsn( CHECKCAST, type.isArray() ? getTypeDescription(type) : getClassInternalName(type.getName())); } } } public void doCast(ClassNode type) { if (type==ClassHelper.OBJECT_TYPE) return; if (ClassHelper.isPrimitiveType(type) && type!=ClassHelper.VOID_TYPE) { unbox(type); } else { 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 * @param holder */ 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 loadThis() { cv.visitVarInsn(ALOAD, 0); } 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 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); } /** * 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 * @return */ 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); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -