List of usage examples for org.objectweb.asm Opcodes ACONST_NULL
int ACONST_NULL
To view the source code for org.objectweb.asm Opcodes ACONST_NULL.
Click Source Link
From source file:com.nginious.http.xsp.expr.RightFunction.java
License:Apache License
/** * Creates bytecode for evaluating this right function. The specified method visitor * and type are used for generating bytecode. * //from ww w. j ava2 s .co m * @param visitor the method visitor * @param type the type */ void compile(MethodVisitor visitor, Type type) { value.compile(visitor, Type.STRING); visitor.visitVarInsn(Opcodes.ASTORE, 1); Label nullLabel = new Label(); Label notNullLabel = new Label(); visitor.visitVarInsn(Opcodes.ALOAD, 1); visitor.visitJumpInsn(Opcodes.IFNULL, nullLabel); visitor.visitVarInsn(Opcodes.ALOAD, 1); visitor.visitVarInsn(Opcodes.ALOAD, 1); visitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "length", "()I"); value2.compile(visitor, Type.INT); visitor.visitInsn(Opcodes.ISUB); visitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "substring", "(I)Ljava/lang/String;"); visitor.visitJumpInsn(Opcodes.GOTO, notNullLabel); visitor.visitLabel(nullLabel); visitor.visitInsn(Opcodes.ACONST_NULL); visitor.visitLabel(notNullLabel); }
From source file:com.nginious.http.xsp.expr.SubstrFunction.java
License:Apache License
/** * Creates bytecode for evaluating this substring function. The specified method visitor * and type are used for generating bytecode. * //from ww w . j av a 2 s .co m * @param visitor the method visitor * @param type the type */ void compile(MethodVisitor visitor, Type type) { value.compile(visitor, Type.STRING); visitor.visitVarInsn(Opcodes.ASTORE, 1); value2.compile(visitor, Type.INT); visitor.visitVarInsn(Opcodes.ISTORE, 2); value3.compile(visitor, Type.INT); visitor.visitVarInsn(Opcodes.ISTORE, 3); Label nullLabel = new Label(); Label notNullLabel = new Label(); // check for null string visitor.visitVarInsn(Opcodes.ALOAD, 1); visitor.visitJumpInsn(Opcodes.IFNULL, nullLabel); // start < 0 Label label1 = new Label(); visitor.visitLdcInsn(0); visitor.visitVarInsn(Opcodes.ILOAD, 2); visitor.visitJumpInsn(Opcodes.IF_ICMPLT, label1); visitor.visitLdcInsn(0); visitor.visitVarInsn(Opcodes.ISTORE, 2); // start > value.length Label label2 = new Label(); visitor.visitLabel(label1); visitor.visitVarInsn(Opcodes.ALOAD, 1); visitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "length", "()I"); visitor.visitVarInsn(Opcodes.ILOAD, 2); visitor.visitJumpInsn(Opcodes.IF_ICMPGT, label2); visitor.visitVarInsn(Opcodes.ALOAD, 1); visitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "length", "()I"); visitor.visitVarInsn(Opcodes.ISTORE, 2); // end < start Label label3 = new Label(); visitor.visitLabel(label2); visitor.visitVarInsn(Opcodes.ILOAD, 2); visitor.visitVarInsn(Opcodes.ILOAD, 3); visitor.visitJumpInsn(Opcodes.IF_ICMPLT, label3); visitor.visitVarInsn(Opcodes.ILOAD, 2); visitor.visitVarInsn(Opcodes.ISTORE, 3); // end > value1.length Label label4 = new Label(); visitor.visitLabel(label3); visitor.visitVarInsn(Opcodes.ALOAD, 1); visitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "length", "()I"); visitor.visitVarInsn(Opcodes.ILOAD, 3); visitor.visitJumpInsn(Opcodes.IF_ICMPGT, label4); visitor.visitVarInsn(Opcodes.ALOAD, 1); visitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "length", "()I"); visitor.visitVarInsn(Opcodes.ISTORE, 3); // substr visitor.visitLabel(label4); visitor.visitVarInsn(Opcodes.ALOAD, 1); visitor.visitVarInsn(Opcodes.ILOAD, 2); visitor.visitVarInsn(Opcodes.ILOAD, 3); visitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "substring", "(II)Ljava/lang/String;"); visitor.visitJumpInsn(Opcodes.GOTO, notNullLabel); visitor.visitLabel(nullLabel); visitor.visitInsn(Opcodes.ACONST_NULL); visitor.visitLabel(notNullLabel); }
From source file:com.offbynull.coroutines.instrumenter.asm.InstructionUtils.java
License:Open Source License
/** * Generates instruction to push a null on to the stack. * @return instructions to push a null/*from ww w . j a v a2s. co m*/ */ public static InsnList loadNull() { InsnList ret = new InsnList(); ret.add(new InsnNode(Opcodes.ACONST_NULL)); return ret; }
From source file:com.offbynull.coroutines.instrumenter.asm.InstructionUtils.java
License:Open Source License
private static InsnList loadOperandStack(Variable arrayStackVar, Variable tempObjectVar, Frame<BasicValue> frame, int start, int end) { Validate.notNull(arrayStackVar);/*w w w . j ava2 s. com*/ Validate.notNull(tempObjectVar); Validate.notNull(frame); Validate.isTrue(arrayStackVar.getType().equals(Type.getType(Object[].class))); Validate.isTrue(tempObjectVar.getType().equals(Type.getType(Object.class))); validateLocalIndicies(arrayStackVar.getIndex(), tempObjectVar.getIndex()); Validate.isTrue(start >= 0); Validate.isTrue(end >= start); // end is exclusive Validate.isTrue(end <= frame.getStackSize()); InsnList ret = new InsnList(); // Restore the stack for (int i = start; i < end; i++) { BasicValue basicValue = frame.getStack(i); Type type = basicValue.getType(); // If type is 'Lnull;', this means that the slot has been assigned null and that "there has been no merge yet that would 'raise' // the type toward some class or interface type" (from ASM mailing list). We know this slot will always contain null at this // point in the code so there's no specific value to load up from the array. Instead we push a null in to that slot, thereby // keeping the same 'Lnull;' type originally assigned to that slot (it doesn't make sense to do a CHECKCAST because 'null' is // not a real class and can never be a real class -- null is a reserved word in Java). if (type.getSort() == Type.OBJECT && "Lnull;".equals(type.getDescriptor())) { ret.add(new InsnNode(Opcodes.ACONST_NULL)); continue; } // Load item from stack storage array ret.add(new VarInsnNode(Opcodes.ALOAD, arrayStackVar.getIndex())); ret.add(new LdcInsnNode(i)); ret.add(new InsnNode(Opcodes.AALOAD)); // Convert the item to an object (if not already an object) and stores it in local vars table. Item removed from stack. switch (type.getSort()) { case Type.BOOLEAN: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Boolean")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false)); break; case Type.BYTE: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Byte")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false)); break; case Type.SHORT: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Short")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false)); break; case Type.CHAR: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Character")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C", false)); break; case Type.INT: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Integer")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false)); break; case Type.FLOAT: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Float")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false)); break; case Type.LONG: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Long")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false)); break; case Type.DOUBLE: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Double")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false)); break; case Type.ARRAY: case Type.OBJECT: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, basicValue.getType().getInternalName())); break; case Type.METHOD: case Type.VOID: default: throw new IllegalArgumentException(); } } return ret; }
From source file:com.offbynull.coroutines.instrumenter.asm.InstructionUtils.java
License:Open Source License
/** * Generates instructions to save the operand stack to an object array. * @param arrayStackVar variable that the object array containing operand stack is stored * @param tempObjectVar variable to use for temporary objects * @param frame execution frame at the instruction where the operand stack is to be saved * @return instructions to save the operand stack in to an array and save it to the local variables table * @throws NullPointerException if any argument is {@code null} * @throws IllegalArgumentException if variables have the same index, or if variables have been released, or if variables are of wrong * type/* w w w .ja v a2 s . co m*/ */ public static InsnList saveOperandStack(Variable arrayStackVar, Variable tempObjectVar, Frame<BasicValue> frame) { Validate.notNull(arrayStackVar); Validate.notNull(tempObjectVar); Validate.notNull(frame); Validate.isTrue(arrayStackVar.getType().equals(Type.getType(Object[].class))); Validate.isTrue(tempObjectVar.getType().equals(Type.getType(Object.class))); validateLocalIndicies(arrayStackVar.getIndex(), tempObjectVar.getIndex()); InsnList ret = new InsnList(); // Create stack storage array and save it in local vars table ret.add(new LdcInsnNode(frame.getStackSize())); ret.add(new TypeInsnNode(Opcodes.ANEWARRAY, "java/lang/Object")); ret.add(new VarInsnNode(Opcodes.ASTORE, arrayStackVar.getIndex())); // Save the stack for (int i = frame.getStackSize() - 1; i >= 0; i--) { BasicValue basicValue = frame.getStack(i); Type type = basicValue.getType(); // If type is 'Lnull;', this means that the slot has been assigned null and that "there has been no merge yet that would 'raise' // the type toward some class or interface type" (from ASM mailing list). We know this slot will always contain null at this // point in the code so we can avoid saving it (but we still need to do a POP to get rid of it). When we load it back up, we can // simply push a null in to that slot, thereby keeping the same 'Lnull;' type. if ("Lnull;".equals(type.getDescriptor())) { ret.add(new InsnNode(Opcodes.POP)); continue; } // Convert the item to an object (if not already an object) and stores it in local vars table. Item removed from stack. switch (type.getSort()) { case Type.BOOLEAN: ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;")); ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex())); break; case Type.BYTE: ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false)); ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex())); break; case Type.SHORT: ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false)); ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex())); break; case Type.CHAR: ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false)); ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex())); break; case Type.INT: ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false)); ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex())); break; case Type.FLOAT: ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false)); ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex())); break; case Type.LONG: ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false)); ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex())); break; case Type.DOUBLE: ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false)); ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex())); break; case Type.ARRAY: case Type.OBJECT: ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex())); break; case Type.METHOD: case Type.VOID: default: throw new IllegalArgumentException(); } // Store item in to stack storage array ret.add(new VarInsnNode(Opcodes.ALOAD, arrayStackVar.getIndex())); ret.add(new LdcInsnNode(i)); ret.add(new VarInsnNode(Opcodes.ALOAD, tempObjectVar.getIndex())); ret.add(new InsnNode(Opcodes.AASTORE)); } // Restore the stack for (int i = 0; i < frame.getStackSize(); i++) { BasicValue basicValue = frame.getStack(i); Type type = basicValue.getType(); // If type is 'Lnull;', this means that the slot has been assigned null and that "there has been no merge yet that would 'raise' // the type toward some class or interface type" (from ASM mailing list). We know this slot will always contain null at this // point in the code so there's no specific value to load up from the array. Instead we push a null in to that slot, thereby // keeping the same 'Lnull;' type originally assigned to that slot (it doesn't make sense to do a CHECKCAST because 'null' is // not a real class and can never be a real class -- null is a reserved word in Java). if (type.getSort() == Type.OBJECT && "Lnull;".equals(type.getDescriptor())) { ret.add(new InsnNode(Opcodes.ACONST_NULL)); continue; } // Load item from stack storage array ret.add(new VarInsnNode(Opcodes.ALOAD, arrayStackVar.getIndex())); ret.add(new LdcInsnNode(i)); ret.add(new InsnNode(Opcodes.AALOAD)); // Convert the item to an object (if not already an object) and stores it in local vars table. Item removed from stack. switch (type.getSort()) { case Type.BOOLEAN: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Boolean")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false)); break; case Type.BYTE: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Byte")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false)); break; case Type.SHORT: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Short")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false)); break; case Type.CHAR: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Character")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C", false)); break; case Type.INT: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Integer")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false)); break; case Type.FLOAT: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Float")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false)); break; case Type.LONG: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Long")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false)); break; case Type.DOUBLE: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Double")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false)); break; case Type.ARRAY: case Type.OBJECT: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, basicValue.getType().getInternalName())); break; case Type.METHOD: case Type.VOID: default: throw new IllegalArgumentException(); } } return ret; }
From source file:com.offbynull.coroutines.instrumenter.asm.InstructionUtils.java
License:Open Source License
/** * Generates instructions to load the local variables table from an object array. * * @param arrayLocalsVar variable that the object array containing local variables table is stored * @param tempObjectVar variable to use for temporary objects * @param frame execution frame at the instruction for which the local variables table is to be restored * @return instructions to load the local variables table from an array * @throws NullPointerException if any argument is {@code null} * @throws IllegalArgumentException if variables have the same index, or if variables have been released, or if variables are of wrong * type/*from w w w .j a va 2 s .c om*/ */ public static InsnList loadLocalVariableTable(Variable arrayLocalsVar, Variable tempObjectVar, Frame<BasicValue> frame) { Validate.notNull(arrayLocalsVar); Validate.notNull(tempObjectVar); Validate.notNull(frame); Validate.isTrue(arrayLocalsVar.getType().equals(Type.getType(Object[].class))); Validate.isTrue(tempObjectVar.getType().equals(Type.getType(Object.class))); validateLocalIndicies(arrayLocalsVar.getIndex(), tempObjectVar.getIndex()); InsnList ret = new InsnList(); // Load the locals for (int i = 0; i < frame.getLocals(); i++) { BasicValue basicValue = frame.getLocal(i); Type type = basicValue.getType(); // If type == null, basicValue is pointing to uninitialized var -- basicValue.toString() will return ".". This means that this // slot contains nothing to load. So, skip this slot if we encounter it (such that it will remain uninitialized). if (type == null) { continue; } // If type is 'Lnull;', this means that the slot has been assigned null and that "there has been no merge yet that would 'raise' // the type toward some class or interface type" (from ASM mailing list). We know this slot will always contain null at this // point in the code so there's no specific value to load up from the array. Instead we push a null in to that slot, thereby // keeping the same 'Lnull;' type originally assigned to that slot (it doesn't make sense to do a CHECKCAST because 'null' is // not a real class and can never be a real class -- null is a reserved word in Java). if (type.getSort() == Type.OBJECT && "Lnull;".equals(type.getDescriptor())) { ret.add(new InsnNode(Opcodes.ACONST_NULL)); ret.add(new VarInsnNode(Opcodes.ASTORE, i)); continue; } // Load item from locals storage array ret.add(new VarInsnNode(Opcodes.ALOAD, arrayLocalsVar.getIndex())); ret.add(new LdcInsnNode(i)); ret.add(new InsnNode(Opcodes.AALOAD)); // Convert the item from an object stores it in local vars table. switch (type.getSort()) { case Type.BOOLEAN: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Boolean")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false)); ret.add(new VarInsnNode(Opcodes.ISTORE, i)); break; case Type.BYTE: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Byte")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false)); ret.add(new VarInsnNode(Opcodes.ISTORE, i)); break; case Type.SHORT: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Short")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false)); ret.add(new VarInsnNode(Opcodes.ISTORE, i)); break; case Type.CHAR: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Character")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C", false)); ret.add(new VarInsnNode(Opcodes.ISTORE, i)); break; case Type.INT: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Integer")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false)); ret.add(new VarInsnNode(Opcodes.ISTORE, i)); break; case Type.FLOAT: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Float")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false)); ret.add(new VarInsnNode(Opcodes.FSTORE, i)); break; case Type.LONG: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Long")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false)); ret.add(new VarInsnNode(Opcodes.LSTORE, i)); break; case Type.DOUBLE: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Double")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false)); ret.add(new VarInsnNode(Opcodes.DSTORE, i)); break; case Type.ARRAY: case Type.OBJECT: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, basicValue.getType().getInternalName())); ret.add(new VarInsnNode(Opcodes.ASTORE, i)); break; case Type.METHOD: case Type.VOID: default: throw new IllegalStateException(); } } return ret; }
From source file:com.offbynull.coroutines.instrumenter.asm.InstructionUtils.java
License:Open Source License
/** * Generates instructions that returns a dummy value. Return values are as follows: * <ul>/*from w ww . ja v a2s . co m*/ * <li>void -> no value</li> * <li>boolean -> false</li> * <li>byte/short/char/int -> 0</li> * <li>long -> 0L</li> * <li>float -> 0.0f</li> * <li>double -> 0.0</li> * <li>Object -> null</li> * </ul> * * @param returnType return type of the method this generated bytecode is for * @return instructions to return a dummy value * @throws NullPointerException if any argument is {@code null} * @throws IllegalArgumentException if {@code returnType}'s sort is of {@link Type#METHOD} */ public static InsnList returnDummy(Type returnType) { Validate.notNull(returnType); Validate.isTrue(returnType.getSort() != Type.METHOD); InsnList ret = new InsnList(); switch (returnType.getSort()) { case Type.VOID: ret.add(new InsnNode(Opcodes.RETURN)); break; case Type.BOOLEAN: case Type.BYTE: case Type.SHORT: case Type.CHAR: case Type.INT: ret.add(new InsnNode(Opcodes.ICONST_0)); ret.add(new InsnNode(Opcodes.IRETURN)); break; case Type.LONG: ret.add(new InsnNode(Opcodes.LCONST_0)); ret.add(new InsnNode(Opcodes.LRETURN)); break; case Type.FLOAT: ret.add(new InsnNode(Opcodes.FCONST_0)); ret.add(new InsnNode(Opcodes.FRETURN)); break; case Type.DOUBLE: ret.add(new InsnNode(Opcodes.DCONST_0)); ret.add(new InsnNode(Opcodes.DRETURN)); break; case Type.OBJECT: case Type.ARRAY: ret.add(new InsnNode(Opcodes.ACONST_NULL)); ret.add(new InsnNode(Opcodes.ARETURN)); break; default: throw new IllegalStateException(); } return ret; }
From source file:com.offbynull.coroutines.instrumenter.ContinuationGenerators.java
License:Open Source License
/** * Generates instructions that returns a dummy value. Return values are as follows: * <ul>/* ww w. j ava2 s.c o m*/ * <li>void -> no value</li> * <li>boolean -> false</li> * <li>byte/short/char/int -> 0</li> * <li>long -> 0L</li> * <li>float -> 0.0f</li> * <li>double -> 0.0</li> * <li>Object -> null</li> * </ul> * * @param returnType return type of the method this generated bytecode is for * @return instructions to return a dummy value * @throws NullPointerException if any argument is {@code null} * @throws IllegalArgumentException if {@code returnType}'s sort is of {@link Type#METHOD} */ private static InsnList returnDummy(Type returnType) { Validate.notNull(returnType); Validate.isTrue(returnType.getSort() != Type.METHOD); InsnList ret = new InsnList(); switch (returnType.getSort()) { case Type.VOID: ret.add(new InsnNode(Opcodes.RETURN)); break; case Type.BOOLEAN: case Type.BYTE: case Type.SHORT: case Type.CHAR: case Type.INT: ret.add(new InsnNode(Opcodes.ICONST_0)); ret.add(new InsnNode(Opcodes.IRETURN)); break; case Type.LONG: ret.add(new InsnNode(Opcodes.LCONST_0)); ret.add(new InsnNode(Opcodes.LRETURN)); break; case Type.FLOAT: ret.add(new InsnNode(Opcodes.FCONST_0)); ret.add(new InsnNode(Opcodes.FRETURN)); break; case Type.DOUBLE: ret.add(new InsnNode(Opcodes.DCONST_0)); ret.add(new InsnNode(Opcodes.DRETURN)); break; case Type.OBJECT: case Type.ARRAY: ret.add(new InsnNode(Opcodes.ACONST_NULL)); ret.add(new InsnNode(Opcodes.ARETURN)); break; default: throw new IllegalStateException(); } return ret; }
From source file:com.offbynull.coroutines.instrumenter.LocalsStateGenerators.java
License:Open Source License
/** * Generates instructions to load the local variables table. * @param markerType debug marker type//w ww. j a va2 s . c om * @param storageVars variables to load locals from * @param frame execution frame at the instruction for which the local variables table is to be restored * @return instructions to load the local variables table from an array * @throws NullPointerException if any argument is {@code null} */ public static InsnList loadLocals(MarkerType markerType, StorageVariables storageVars, Frame<BasicValue> frame) { Validate.notNull(markerType); Validate.notNull(storageVars); Validate.notNull(frame); Variable intsVar = storageVars.getIntStorageVar(); Variable floatsVar = storageVars.getFloatStorageVar(); Variable longsVar = storageVars.getLongStorageVar(); Variable doublesVar = storageVars.getDoubleStorageVar(); Variable objectsVar = storageVars.getObjectStorageVar(); int intsCounter = 0; int floatsCounter = 0; int longsCounter = 0; int doublesCounter = 0; int objectsCounter = 0; InsnList ret = new InsnList(); // Load the locals ret.add(debugMarker(markerType, "Loading locals")); for (int i = 0; i < frame.getLocals(); i++) { BasicValue basicValue = frame.getLocal(i); Type type = basicValue.getType(); // If type == null, basicValue is pointing to uninitialized var -- basicValue.toString() will return ".". This means that this // slot contains nothing to load. So, skip this slot if we encounter it (such that it will remain uninitialized). if (type == null) { ret.add(debugMarker(markerType, "Skipping uninitialized value at " + i)); continue; } // If type is 'Lnull;', this means that the slot has been assigned null and that "there has been no merge yet that would 'raise' // the type toward some class or interface type" (from ASM mailing list). We know this slot will always contain null at this // point in the code so there's no specific value to load up from the array. Instead we push a null in to that slot, thereby // keeping the same 'Lnull;' type originally assigned to that slot (it doesn't make sense to do a CHECKCAST because 'null' is // not a real class and can never be a real class -- null is a reserved word in Java). if (type.getSort() == Type.OBJECT && "Lnull;".equals(type.getDescriptor())) { ret.add(debugMarker(markerType, "Putting null value at " + i)); ret.add(new InsnNode(Opcodes.ACONST_NULL)); ret.add(new VarInsnNode(Opcodes.ASTORE, i)); continue; } // Load the locals switch (type.getSort()) { case Type.BOOLEAN: case Type.BYTE: case Type.SHORT: case Type.CHAR: case Type.INT: ret.add(debugMarker(markerType, "Loading int to LVT index " + i + " from storage index " + intsCounter)); ret.add(new VarInsnNode(Opcodes.ALOAD, intsVar.getIndex())); // [int[]] ret.add(new LdcInsnNode(intsCounter)); // [int[], idx] ret.add(new InsnNode(Opcodes.IALOAD)); // [val] ret.add(new VarInsnNode(Opcodes.ISTORE, i)); // [] intsCounter++; break; case Type.FLOAT: ret.add(debugMarker(markerType, "Loading float to LVT index " + i + " from storage index " + floatsCounter)); ret.add(new VarInsnNode(Opcodes.ALOAD, floatsVar.getIndex())); // [float[]] ret.add(new LdcInsnNode(floatsCounter)); // [float[], idx] ret.add(new InsnNode(Opcodes.FALOAD)); // [val] ret.add(new VarInsnNode(Opcodes.FSTORE, i)); // [] floatsCounter++; break; case Type.LONG: ret.add(debugMarker(markerType, "Loading long to LVT index " + i + " from storage index " + longsCounter)); ret.add(new VarInsnNode(Opcodes.ALOAD, longsVar.getIndex())); // [long[]] ret.add(new LdcInsnNode(longsCounter)); // [long[], idx] ret.add(new InsnNode(Opcodes.LALOAD)); // [val_PART1, val_PART2] ret.add(new VarInsnNode(Opcodes.LSTORE, i)); // [] longsCounter++; break; case Type.DOUBLE: ret.add(debugMarker(markerType, "Loading double to LVT index " + i + " from storage index " + doublesCounter)); ret.add(new VarInsnNode(Opcodes.ALOAD, doublesVar.getIndex())); // [double[]] ret.add(new LdcInsnNode(doublesCounter)); // [double[], idx] ret.add(new InsnNode(Opcodes.DALOAD)); // [val_PART1, val_PART2] ret.add(new VarInsnNode(Opcodes.DSTORE, i)); // [] doublesCounter++; break; case Type.ARRAY: case Type.OBJECT: ret.add(debugMarker(markerType, "Loading object to LVT index " + i + " from storage index " + objectsCounter)); ret.add(new VarInsnNode(Opcodes.ALOAD, objectsVar.getIndex())); // [Object[]] ret.add(new LdcInsnNode(objectsCounter)); // [Object[], idx] ret.add(new InsnNode(Opcodes.AALOAD)); // [val] // must cast, otherwise the jvm won't know the type that's in the localvariable slot and it'll fail when the code tries // to access a method/field on it ret.add(new TypeInsnNode(Opcodes.CHECKCAST, basicValue.getType().getInternalName())); ret.add(new VarInsnNode(Opcodes.ASTORE, i)); // [] objectsCounter++; break; case Type.METHOD: case Type.VOID: default: throw new IllegalStateException(); } } return ret; }
From source file:com.offbynull.coroutines.instrumenter.OperandStackStateGenerators.java
License:Open Source License
/** * Generates instructions to load a certain number of items to the top of the operand stack. * @param markerType debug marker type//from ww w . j ava 2 s . co m * @param storageVars variables to load operand stack from * @param frame execution frame at the instruction where the operand stack is to be loaded * @param storageStackStartIdx stack position where {@code storageVars} starts from * @param storageStackLoadIdx stack position where loading should start from * @param count number of stack items to load * @return instructions to load the operand stack from the specified storage variables * @throws NullPointerException if any argument is {@code null} * @throws IllegalArgumentException if any numeric argument is negative, or if you're trying to load stack items that aren't available * in the storage vars (stack items before {@code storageStackStartIdx}), or if you're trying to load too many items on the stack (such * that it goes past {@code frame.getStackSize()}) */ public static InsnList loadOperandStack(MarkerType markerType, StorageVariables storageVars, Frame<BasicValue> frame, int storageStackStartIdx, // stack idx which the storage was started at int storageStackLoadIdx, // stack idx we should start loading at int count) { Validate.notNull(markerType); Validate.notNull(storageVars); Validate.notNull(frame); // no negs allowed Validate.isTrue(storageStackStartIdx >= 0); Validate.isTrue(storageStackLoadIdx >= 0); Validate.isTrue(count >= 0); Validate.isTrue(storageStackLoadIdx >= storageStackStartIdx); Validate.isTrue(storageStackStartIdx + count <= frame.getStackSize()); Validate.isTrue(storageStackStartIdx + count >= 0); // likely will never overflow unless crazy high count passedin, but just in case Variable intsVar = storageVars.getIntStorageVar(); Variable floatsVar = storageVars.getFloatStorageVar(); Variable longsVar = storageVars.getLongStorageVar(); Variable doublesVar = storageVars.getDoubleStorageVar(); Variable objectsVar = storageVars.getObjectStorageVar(); int intsCounter = 0; int floatsCounter = 0; int longsCounter = 0; int doublesCounter = 0; int objectsCounter = 0; InsnList ret = new InsnList(); // Increment offsets for parts of the storage arrays we don't care about. We need to do this so when we load we're loading from the // correct offsets in the storage arrays for (int i = storageStackStartIdx; i < storageStackLoadIdx; i++) { BasicValue basicValue = frame.getStack(i); Type type = basicValue.getType(); // If type is 'Lnull;', this means that the slot has been assigned null and that "there has been no merge yet that would 'raise' // the type toward some class or interface type" (from ASM mailing list). We know this slot will always contain null at this // point in the code so there's no specific value to load up from the array. if (type.getSort() == Type.OBJECT && "Lnull;".equals(type.getDescriptor())) { continue; // skip } switch (type.getSort()) { case Type.BOOLEAN: case Type.BYTE: case Type.SHORT: case Type.CHAR: case Type.INT: intsCounter++; break; case Type.FLOAT: floatsCounter++; break; case Type.LONG: longsCounter++; break; case Type.DOUBLE: doublesCounter++; break; case Type.ARRAY: case Type.OBJECT: objectsCounter++; break; case Type.METHOD: case Type.VOID: default: throw new IllegalArgumentException(); } } // Restore the stack ret.add(debugMarker(markerType, "Loading stack items")); for (int i = storageStackLoadIdx; i < storageStackLoadIdx + count; i++) { BasicValue basicValue = frame.getStack(i); Type type = basicValue.getType(); // If type is 'Lnull;', this means that the slot has been assigned null and that "there has been no merge yet that would 'raise' // the type toward some class or interface type" (from ASM mailing list). We know this slot will always contain null at this // point in the code so there's no specific value to load up from the array. Instead we push a null in to that slot, thereby // keeping the same 'Lnull;' type originally assigned to that slot (it doesn't make sense to do a CHECKCAST because 'null' is // not a real class and can never be a real class -- null is a reserved word in Java). if (type.getSort() == Type.OBJECT && "Lnull;".equals(type.getDescriptor())) { ret.add(debugMarker(markerType, "Loading null value at " + i)); ret.add(new InsnNode(Opcodes.ACONST_NULL)); continue; } // Load item from stack storage array ret.add(debugMarker(markerType, "Loading from container at" + i)); // Convert the item to an object (if not already an object) and stores it in local vars table. Item removed from stack. switch (type.getSort()) { case Type.BOOLEAN: case Type.BYTE: case Type.SHORT: case Type.CHAR: case Type.INT: ret.add(debugMarker(markerType, "Loading int at " + i + " from storage index " + intsCounter)); ret.add(new VarInsnNode(Opcodes.ALOAD, intsVar.getIndex())); // [int[]] ret.add(new LdcInsnNode(intsCounter)); // [int[], idx] ret.add(new InsnNode(Opcodes.IALOAD)); // [val] intsCounter++; break; case Type.FLOAT: ret.add(debugMarker(markerType, "Loading float at " + i + " from storage index " + floatsCounter)); ret.add(new VarInsnNode(Opcodes.ALOAD, floatsVar.getIndex())); // [float[]] ret.add(new LdcInsnNode(floatsCounter)); // [float[], idx] ret.add(new InsnNode(Opcodes.FALOAD)); // [val] floatsCounter++; break; case Type.LONG: ret.add(debugMarker(markerType, "Loading long at " + i + " from storage index " + longsCounter)); ret.add(new VarInsnNode(Opcodes.ALOAD, longsVar.getIndex())); // [long[]] ret.add(new LdcInsnNode(longsCounter)); // [long[], idx] ret.add(new InsnNode(Opcodes.LALOAD)); // [val_PART1, val_PART2] longsCounter++; break; case Type.DOUBLE: ret.add(debugMarker(markerType, "Loading double at " + i + " from storage index " + doublesCounter)); ret.add(new VarInsnNode(Opcodes.ALOAD, doublesVar.getIndex())); // [double[]] ret.add(new LdcInsnNode(doublesCounter)); // [double[], idx] ret.add(new InsnNode(Opcodes.DALOAD)); // [val_PART1, val_PART2] doublesCounter++; break; case Type.ARRAY: case Type.OBJECT: ret.add(debugMarker(markerType, "Loading object at " + i + " from storage index " + objectsCounter)); ret.add(new VarInsnNode(Opcodes.ALOAD, objectsVar.getIndex())); // [Object[]] ret.add(new LdcInsnNode(objectsCounter)); // [Object[], idx] ret.add(new InsnNode(Opcodes.AALOAD)); // [val] ret.add(new TypeInsnNode(Opcodes.CHECKCAST, basicValue.getType().getInternalName())); objectsCounter++; break; case Type.METHOD: case Type.VOID: default: throw new IllegalArgumentException(); } } return ret; }