Repository: groovy Updated Branches: refs/heads/GROOVY_2_5_X e4c4d663f -> 46bad1d83
Minor refactoring: remove the duplicated code (cherry picked from commit ae713cb) Project: http://git-wip-us.apache.org/repos/asf/groovy/repo Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/9c95e8d1 Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/9c95e8d1 Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/9c95e8d1 Branch: refs/heads/GROOVY_2_5_X Commit: 9c95e8d19f4bf04890ce2a85f32342721c7b9dd8 Parents: e4c4d66 Author: sunlan <sun...@apache.org> Authored: Tue Feb 6 08:57:16 2018 +0800 Committer: sunlan <sun...@apache.org> Committed: Tue Feb 6 17:12:15 2018 +0800 ---------------------------------------------------------------------- .../groovy/classgen/asm/BytecodeHelper.java | 120 +++++++++++++++---- .../groovy/classgen/asm/OperandStack.java | 47 +++----- 2 files changed, 114 insertions(+), 53 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/groovy/blob/9c95e8d1/src/main/java/org/codehaus/groovy/classgen/asm/BytecodeHelper.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/BytecodeHelper.java b/src/main/java/org/codehaus/groovy/classgen/asm/BytecodeHelper.java index d680731..491cd7b 100644 --- a/src/main/java/org/codehaus/groovy/classgen/asm/BytecodeHelper.java +++ b/src/main/java/org/codehaus/groovy/classgen/asm/BytecodeHelper.java @@ -508,26 +508,6 @@ public class BytecodeHelper implements Opcodes { ret.append(end); } - public static void load(MethodVisitor mv, ClassNode type, int idx) { - if (type == ClassHelper.double_TYPE) { - mv.visitVarInsn(DLOAD, idx); - } else if (type == ClassHelper.float_TYPE) { - mv.visitVarInsn(FLOAD, idx); - } else if (type == ClassHelper.long_TYPE) { - mv.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) { - mv.visitVarInsn(ILOAD, idx); - } else { - mv.visitVarInsn(ALOAD, idx); - } - } - - public static void doCast(MethodVisitor mv, ClassNode type) { if (type == ClassHelper.OBJECT_TYPE) return; if (ClassHelper.isPrimitiveType(type) && type != ClassHelper.VOID_TYPE) { @@ -674,4 +654,104 @@ public class BytecodeHelper implements Opcodes { } return h; } + + /** + * Converts a primitive type to boolean. + * + * @param mv method visitor + * @param type primitive type to convert + */ + public static void convertPrimitiveToBoolean(MethodVisitor mv, ClassNode type) { + if (type == ClassHelper.boolean_TYPE) { + return; + } + // Special handling is done for floating point types in order to + // handle checking for 0 or NaN values. + if (type == ClassHelper.double_TYPE) { + convertDoubleToBoolean(mv, type); + return; + } else if (type == ClassHelper.float_TYPE) { + convertFloatToBoolean(mv, type); + return; + } + Label trueLabel = new Label(); + Label falseLabel = new Label(); + // Convert long to int for IFEQ comparison using LCMP + if (type==ClassHelper.long_TYPE) { + mv.visitInsn(LCONST_0); + mv.visitInsn(LCMP); + } + // This handles byte, short, char and int + mv.visitJumpInsn(IFEQ, falseLabel); + mv.visitInsn(ICONST_1); + mv.visitJumpInsn(GOTO, trueLabel); + mv.visitLabel(falseLabel); + mv.visitInsn(ICONST_0); + mv.visitLabel(trueLabel); + } + + private static void convertDoubleToBoolean(MethodVisitor mv, ClassNode type) { + Label trueLabel = new Label(); + Label falseLabel = new Label(); + Label falseLabelWithPop = new Label(); + mv.visitInsn(DUP2); // will need the extra for isNaN call if required + mv.visitInsn(DCONST_0); + mv.visitInsn(DCMPL); + mv.visitJumpInsn(IFEQ, falseLabelWithPop); + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "isNaN", "(D)Z", false); + mv.visitJumpInsn(IFNE, falseLabel); + mv.visitInsn(ICONST_1); + mv.visitJumpInsn(GOTO, trueLabel); + mv.visitLabel(falseLabelWithPop); + mv.visitInsn(POP2); + mv.visitLabel(falseLabel); + mv.visitInsn(ICONST_0); + mv.visitLabel(trueLabel); + } + + private static void convertFloatToBoolean(MethodVisitor mv, ClassNode type) { + Label trueLabel = new Label(); + Label falseLabel = new Label(); + Label falseLabelWithPop = new Label(); + mv.visitInsn(DUP); // will need the extra for isNaN call if required + mv.visitInsn(FCONST_0); + mv.visitInsn(FCMPL); + mv.visitJumpInsn(IFEQ, falseLabelWithPop); + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "isNaN", "(F)Z", false); + mv.visitJumpInsn(IFNE, falseLabel); + mv.visitInsn(ICONST_1); + mv.visitJumpInsn(GOTO, trueLabel); + mv.visitLabel(falseLabelWithPop); + mv.visitInsn(POP); + mv.visitLabel(falseLabel); + mv.visitInsn(ICONST_0); + mv.visitLabel(trueLabel); + } + + public static void load(MethodVisitor mv, ClassNode type, int idx) { + storeOrLoadVar(mv, idx, type, DLOAD, FLOAD, LLOAD, ILOAD, ALOAD); + } + + static void store(MethodVisitor mv, ClassNode type, int idx) { + storeOrLoadVar(mv, idx, type, DSTORE, FSTORE, LSTORE, ISTORE, ASTORE); + } + + private static void storeOrLoadVar(MethodVisitor mv, int idx, ClassNode type, int dVarInsn, int fVarInsn, int lVarInsn, int iVarInsn, int aVarInsn) { + if (type == ClassHelper.double_TYPE) { + mv.visitVarInsn(dVarInsn, idx); + } else if (type == ClassHelper.float_TYPE) { + mv.visitVarInsn(fVarInsn, idx); + } else if (type == ClassHelper.long_TYPE) { + mv.visitVarInsn(lVarInsn, idx); + } else if ( + type == ClassHelper.boolean_TYPE + || type == ClassHelper.char_TYPE + || type == ClassHelper.byte_TYPE + || type == ClassHelper.int_TYPE + || type == ClassHelper.short_TYPE) { + mv.visitVarInsn(iVarInsn, idx); + } else { + mv.visitVarInsn(aVarInsn, idx); + } + } } http://git-wip-us.apache.org/repos/asf/groovy/blob/9c95e8d1/src/main/java/org/codehaus/groovy/classgen/asm/OperandStack.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/OperandStack.java b/src/main/java/org/codehaus/groovy/classgen/asm/OperandStack.java index 20d02ff..ace3056 100644 --- a/src/main/java/org/codehaus/groovy/classgen/asm/OperandStack.java +++ b/src/main/java/org/codehaus/groovy/classgen/asm/OperandStack.java @@ -39,7 +39,6 @@ import java.util.List; import static org.objectweb.asm.Opcodes.ACONST_NULL; import static org.objectweb.asm.Opcodes.ALOAD; -import static org.objectweb.asm.Opcodes.ASTORE; import static org.objectweb.asm.Opcodes.BIPUSH; import static org.objectweb.asm.Opcodes.CHECKCAST; import static org.objectweb.asm.Opcodes.D2F; @@ -48,7 +47,6 @@ import static org.objectweb.asm.Opcodes.D2L; import static org.objectweb.asm.Opcodes.DCMPL; import static org.objectweb.asm.Opcodes.DCONST_0; import static org.objectweb.asm.Opcodes.DCONST_1; -import static org.objectweb.asm.Opcodes.DSTORE; import static org.objectweb.asm.Opcodes.DUP; import static org.objectweb.asm.Opcodes.DUP2; import static org.objectweb.asm.Opcodes.DUP2_X1; @@ -61,7 +59,6 @@ import static org.objectweb.asm.Opcodes.FCMPL; import static org.objectweb.asm.Opcodes.FCONST_0; import static org.objectweb.asm.Opcodes.FCONST_1; import static org.objectweb.asm.Opcodes.FCONST_2; -import static org.objectweb.asm.Opcodes.FSTORE; import static org.objectweb.asm.Opcodes.GETSTATIC; import static org.objectweb.asm.Opcodes.GOTO; import static org.objectweb.asm.Opcodes.I2B; @@ -79,14 +76,12 @@ import static org.objectweb.asm.Opcodes.ICONST_5; import static org.objectweb.asm.Opcodes.IFEQ; import static org.objectweb.asm.Opcodes.INVOKESPECIAL; import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL; -import static org.objectweb.asm.Opcodes.ISTORE; import static org.objectweb.asm.Opcodes.L2D; import static org.objectweb.asm.Opcodes.L2F; import static org.objectweb.asm.Opcodes.L2I; import static org.objectweb.asm.Opcodes.LCMP; import static org.objectweb.asm.Opcodes.LCONST_0; import static org.objectweb.asm.Opcodes.LCONST_1; -import static org.objectweb.asm.Opcodes.LSTORE; import static org.objectweb.asm.Opcodes.NEW; import static org.objectweb.asm.Opcodes.POP; import static org.objectweb.asm.Opcodes.POP2; @@ -316,16 +311,23 @@ public class OperandStack { * replace top level element with new element of given type */ public void replace(ClassNode type) { + int size = ensureStackNotEmpty(stack); + stack.set(size - 1, type); + } + + private int ensureStackNotEmpty(List<ClassNode> stack) { int size = stack.size(); + try { - if (size==0) throw new ArrayIndexOutOfBoundsException("size==0"); + if (size == 0) throw new ArrayIndexOutOfBoundsException("size==0"); } catch (ArrayIndexOutOfBoundsException ai) { - System.err.println("index problem in "+controller.getSourceUnit().getName()); + System.err.println("index problem in " + controller.getSourceUnit().getName()); throw ai; } - stack.set(size-1, type); + + return size; } - + /** * replace n top level elements with new element of given type */ @@ -688,22 +690,7 @@ public class OperandStack { mv.visitMethodInsn(INVOKEVIRTUAL, "groovy/lang/Reference", "set", "(Ljava/lang/Object;)V", false); } else { doGroovyCast(type); - if (type == ClassHelper.double_TYPE) { - mv.visitVarInsn(DSTORE, idx); - } else if (type == ClassHelper.float_TYPE) { - mv.visitVarInsn(FSTORE, idx); - } else if (type == ClassHelper.long_TYPE) { - mv.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) { - mv.visitVarInsn(ISTORE, idx); - } else { - mv.visitVarInsn(ASTORE, idx); - } + BytecodeHelper.store(mv, type, idx); } // remove RHS value from operand stack remove(1); @@ -726,13 +713,7 @@ public class OperandStack { } public ClassNode getTopOperand() { - int size = stack.size(); - try { - if (size==0) throw new ArrayIndexOutOfBoundsException("size==0"); - } catch (ArrayIndexOutOfBoundsException ai) { - System.err.println("index problem in "+controller.getSourceUnit().getName()); - throw ai; - } - return stack.get(size-1); + int size = ensureStackNotEmpty(stack); + return stack.get(size - 1); } }