List of usage examples for org.objectweb.asm MethodVisitor visitMaxs
public void visitMaxs(final int maxStack, final int maxLocals)
From source file:boilerplate.processor.adapters.ToStringAdapter.java
License:Open Source License
private void addMethod() { List<String> fieldNames = new ArrayList<String>(typeInfo.fields.size()); Map<String, FieldInfo> fields = new HashMap<String, FieldInfo>(typeInfo.fields.size()); boolean hasAnnotatedFields = typeInfo.hasAnnotatedFields(); for (FieldInfo info : typeInfo.fields) { if (!(hasAnnotatedFields ^ info.mark == Mark.INCLUDE)) { fieldNames.add(info.name);// ww w. ja va2 s . c o m fields.put(info.name, info); } } Collections.sort(fieldNames); MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null); mv.visitCode(); mv.visitTypeInsn(NEW, "java/lang/StringBuilder"); mv.visitInsn(DUP); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "()V"); mv.visitVarInsn(ASTORE, 1); for (String name : fieldNames) { FieldInfo info = fields.get(name); addField(mv, info); } mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;"); mv.visitInsn(ARETURN); mv.visitMaxs(4, 2); mv.visitEnd(); }
From source file:br.usp.each.saeg.badua.core.internal.instr.ClassInstrumenter.java
License:Open Source License
@Override public void visitEnd() { // not instrument interfaces or // classes with probe count equals to zero if (interfaceType || classProbeCount == 0) { super.visitEnd(); return;/* w w w .j a v a 2s. co m*/ } final FieldVisitor fv = cv.visitField(InstrSupport.DATAFIELD_ACC, InstrSupport.DATAFIELD_NAME, InstrSupport.DATAFIELD_DESC, null, null); fv.visitEnd(); final MethodVisitor mv = cv.visitMethod(InstrSupport.DATAMETHOD_ACC, InstrSupport.DATAMETHOD_NAME, InstrSupport.DATAMETHOD_DESC, null, null); mv.visitCode(); // Load the value of the static data field: mv.visitFieldInsn(Opcodes.GETSTATIC, className, InstrSupport.DATAFIELD_NAME, InstrSupport.DATAFIELD_DESC); mv.visitInsn(Opcodes.DUP); // Stack[1]: [J // Stack[0]: [J // Skip initialization when we already have a data array: final Label alreadyInitialized = new Label(); mv.visitJumpInsn(Opcodes.IFNONNULL, alreadyInitialized); // Stack[0]: [J mv.visitInsn(Opcodes.POP); mv.visitLdcInsn(classId); InstrSupport.push(mv, classProbeCount); mv.visitMethodInsn(Opcodes.INVOKESTATIC, InstrSupport.RUNTIME_OWNER, InstrSupport.RUNTIME_NAME, InstrSupport.RUNTIME_DESC, false); // Stack[0]: [J mv.visitInsn(Opcodes.DUP); // Stack[1]: [J // Stack[0]: [J mv.visitFieldInsn(Opcodes.PUTSTATIC, className, InstrSupport.DATAFIELD_NAME, InstrSupport.DATAFIELD_DESC); // Stack[0]: [J if (withFrames) { mv.visitFrame(Opcodes.F_NEW, 0, new Object[] {}, 1, new Object[] { InstrSupport.DATAFIELD_DESC }); } mv.visitLabel(alreadyInitialized); mv.visitInsn(Opcodes.ARETURN); mv.visitMaxs(3, 0); mv.visitEnd(); super.visitEnd(); }
From source file:br.usp.each.saeg.badua.test.validation.MaxTest.java
License:Open Source License
@Override @Before//www .j av a 2 s .c o m public void setUp() throws Exception { super.setUp(); final int classVersion = Opcodes.V1_6; final int classAccessor = Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER; final String className = "Max"; final String superName = "java/lang/Object"; final int methodAccessor = Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC; final String methodName = "max"; final String methodDesc = "([II)I"; final ClassWriter cw = new ClassWriter(0); final MethodVisitor mw; cw.visit(classVersion, classAccessor, className, null, superName, null); mw = cw.visitMethod(methodAccessor, methodName, methodDesc, null, null); mw.visitCode(); // block 0 (definitions {0, 1, 2, 3}) mw.visitInsn(Opcodes.ICONST_0); mw.visitVarInsn(Opcodes.ISTORE, 2); mw.visitVarInsn(Opcodes.ALOAD, 0); mw.visitVarInsn(Opcodes.ILOAD, 2); mw.visitIincInsn(2, 1); mw.visitInsn(Opcodes.IALOAD); mw.visitVarInsn(Opcodes.ISTORE, 3); // block 1 (p-uses {1, 2}) final Label backLoop = new Label(); mw.visitLabel(backLoop); mw.visitVarInsn(Opcodes.ILOAD, 2); mw.visitVarInsn(Opcodes.ILOAD, 1); final Label breakLoop = new Label(); mw.visitJumpInsn(Opcodes.IF_ICMPGE, breakLoop); // block 3 (p-uses {0, 2, 3}) mw.visitVarInsn(Opcodes.ALOAD, 0); mw.visitVarInsn(Opcodes.ILOAD, 2); mw.visitInsn(Opcodes.IALOAD); mw.visitVarInsn(Opcodes.ILOAD, 3); final Label jump = new Label(); mw.visitJumpInsn(Opcodes.IF_ICMPLE, jump); // block 5 (definitions {3}, uses {0, 2}) mw.visitVarInsn(Opcodes.ALOAD, 0); mw.visitVarInsn(Opcodes.ILOAD, 2); mw.visitInsn(Opcodes.IALOAD); mw.visitVarInsn(Opcodes.ISTORE, 3); // block 4 (definitions {2}, uses {2}) mw.visitLabel(jump); mw.visitIincInsn(2, 1); mw.visitJumpInsn(Opcodes.GOTO, backLoop); // block 2 ( uses {3}) mw.visitLabel(breakLoop); mw.visitVarInsn(Opcodes.ILOAD, 3); mw.visitInsn(Opcodes.IRETURN); mw.visitMaxs(2, 4); mw.visitEnd(); cw.visitEnd(); final byte[] bytes = cw.toByteArray(); klass = addClass(className, bytes); method = klass.getMethod(methodName, int[].class, int.class); classId = CRC64.checksum(bytes); RT.init(new RuntimeData()); }
From source file:bytecode.ClassExporter.java
License:Apache License
/** * Exports the given class node to a file. The location of this file is * determined by the output classpath. This will cause a * <code>RuntimeException</code> if the class is not deeply loaded. * * @param c Class node to be exported. *///from w ww . j ava 2 s . co m public static void export(ClassNode c) { // Form array of interface names. String[] interfaces = new String[c.getInterfaces().size()]; int index = 0; for (ClassNode iface : c.getInterfaces()) { interfaces[index++] = iface.getName(); } // Export Class Header ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); cw.visit(Opcodes.V1_6, Modifier.getBitField(c.getModifiers()), c.getName(), null, // NOTE: Generic signature (for debugging/reflection). (c.getSuperClass() == null) ? null : c.getSuperClass().getName(), interfaces); // TODO: Inner / Outer Classes // Debug Information if (c.getSourceFile() != null) { cw.visitSource(c.getSourceFile(), null); } // Export Fields for (Field f : c.getFields()) { cw.visitField(Modifier.getBitField(f.getModifiers()), f.getName(), f.getType().getDescriptor(), null, f.getDefaultValue()); } // Export Methods MethodVisitor mv; for (Method m : c.getMethods()) { if (!m.getModifiers().contains(Modifier.INHERITED)) { mv = cw.visitMethod(Modifier.getBitField(m.getModifiers()), m.getName(), m.getDescriptor(), null, // NOTE: Generic signature (for debugging/reflection). null // TODO: Exceptions ); // Export code unless NATIVE or ABSTRACT. if (!m.getModifiers().contains(Modifier.NATIVE) && !m.getModifiers().contains(Modifier.ABSTRACT)) { mv.visitCode(); m.getImplementation().accept(new BlockExporter(mv)); // Arguments are just dummys, the ClassWriter recalculates. mv.visitMaxs(0, 0); } mv.visitEnd(); } } cw.visitEnd(); File f = new File(outputDirectory, c.getName() + ".class"); try { f.getParentFile().mkdirs(); FileOutputStream fos = new FileOutputStream(f); fos.write(cw.toByteArray()); } catch (IOException e) { throw new RuntimeException("Could not create class file: " + f); } }
From source file:cc.adf.metrics.agent.visitor.ApplicationModuleImplModifier.java
public static void addDetailNameMethod(ClassWriter cw) { MethodVisitor mv = cw.visitMethod(ACC_PRIVATE, "getDetailName", "()Ljava/lang/String;", null, null); mv.visitCode();//from w ww .j a va2s.c o m mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKEVIRTUAL, "oracle/jbo/server/ApplicationModuleImpl", "isRoot", "()Z", false); Label l0 = new Label(); mv.visitJumpInsn(IFEQ, l0); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, "oracle/jbo/server/ApplicationModuleImpl", "getName", "()Ljava/lang/String;", false); mv.visitInsn(ARETURN); mv.visitLabel(l0); mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); mv.visitTypeInsn(NEW, "java/lang/StringBuilder"); mv.visitInsn(DUP); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "()V", false); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, "oracle/jbo/server/ApplicationModuleImpl", "getRootApplicationModule", "()Loracle/jbo/server/ApplicationModuleImpl;", false); mv.visitMethodInsn(INVOKEVIRTUAL, "oracle/jbo/server/ApplicationModuleImpl", "getName", "()Ljava/lang/String;", false); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); mv.visitLdcInsn("::"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, "oracle/jbo/server/ApplicationModuleImpl", "getName", "()Ljava/lang/String;", false); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false); mv.visitInsn(ARETURN); mv.visitMaxs(2, 1); mv.visitEnd(); }
From source file:ch.eiafr.cojac.Agent.java
License:Apache License
/** * This method works only with the FloatReplacerClasses class * It instruments it to create a static initializer block to set * all the static variables used by the agent and injected in the * instrumented application.//from w ww . j a v a2s .c o m * Warning: this is not the only place to set these variables, see class * "CojacReferences" ! * This is used when there is more than one classloader in the application */ private byte[] setGlobalFields(byte[] byteCode, ClassLoader loader) { ClassReader cr = new ClassReader(byteCode); ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES); ClassVisitor cv = new ClassVisitor(Opcodes.ASM5, cw) { @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { super.visit(version, access, name, signature, superName, interfaces); MethodVisitor mv = cv.visitMethod(Opcodes.ACC_STATIC, "<clinit>", "()V", null, null); mv.visitLdcInsn(references.getDoubleWrapper()); mv.visitMethodInsn(Opcodes.INVOKESTATIC, name, "setNgWrapper", "(Ljava/lang/String;)V", false); mv.visitLdcInsn(references.getNgWrapper()); mv.visitMethodInsn(Opcodes.INVOKESTATIC, name, "setDoubleWrapper", "(Ljava/lang/String;)V", false); mv.visitLdcInsn(references.getFloatWrapper()); mv.visitMethodInsn(Opcodes.INVOKESTATIC, name, "setFloatWrapper", "(Ljava/lang/String;)V", false); mv.visitLdcInsn(references.getBigDecimalPrecision()); mv.visitMethodInsn(Opcodes.INVOKESTATIC, name, "setBigDecimalPrecision", "(I)V", false); mv.visitLdcInsn(references.getStabilityThreshold()); mv.visitMethodInsn(Opcodes.INVOKESTATIC, name, "setStabilityThreshold", "(D)V", false); mv.visitLdcInsn(references.getCheckUnstableComparisons() ? 1 : 0); mv.visitMethodInsn(Opcodes.INVOKESTATIC, name, "setCheckUnstableComparisons", "(Z)V", false); mv.visitInsn(Opcodes.RETURN); mv.visitMaxs(0, 0); } }; cr.accept(cv, ClassReader.EXPAND_FRAMES); return cw.toByteArray(); }
From source file:ch.eiafr.cojac.instrumenters.FloatProxyMethod.java
License:Apache License
public void nativeCall(MethodVisitor mv, int access, String owner, String name, String desc) { boolean isStatic = (access & ACC_STATIC) > 0; String newDesc = replaceFloatMethodDescription(desc); MethodVisitor newMv = ccv.addProxyMethod(access & ~ACC_NATIVE, name, newDesc, null, null); int varIndex = 0; int opcode = INVOKESTATIC; if (!isStatic) { newMv.visitVarInsn(ALOAD, 0);/*from w w w. j av a 2 s. c o m*/ varIndex = 1; opcode = INVOKEVIRTUAL; } ConversionContext cc = new ConversionContext(opcode, owner, name, desc); Type args[] = Type.getArgumentTypes(newDesc); for (Type type : args) { newMv.visitVarInsn(getLoadOpcode(type), varIndex); varIndex += type.getSize(); } convertArgumentsToReal(mv, cc); // stack >> [target] allParamsArr [target] allParamsArr maybeConvertTarget(mv, cc.opcode, cc.owner); // stack >> [target] allParamsArr [newTarget] allParamsArr explodeOnStack(mv, cc, true); // stack >> [target] allParamsArr [newTarget] nprm0 nprm1 nprm2... newMv.visitMethodInsn(opcode, owner, name, desc, false); // stack >> [target] allParamsArr [possibleResult] checkArraysAfterCall(newMv, cc.convertedArrays, desc); // stack >> [target] [possibleResult] convertReturnType(newMv, desc); // stack >> [target] [newPossibleResult] newMv.visitInsn(afterFloatReplacement(Type.getReturnType(desc)).getOpcode(IRETURN)); // stack >> [target] // left on the stack... not a problem! newMv.visitMaxs(0, 0); }
From source file:ch.eiafr.cojac.instrumenters.FloatProxyMethod.java
License:Apache License
private void createConvertMethod(String convertDesc, ConversionContext cc) { if (ccv.isProxyMethod(COJAC_TYPE_CONVERT_NAME, convertDesc)) return; // the method already exists MethodVisitor newMv = ccv.addProxyMethod(ACC_STATIC, COJAC_TYPE_CONVERT_NAME, convertDesc, null, null); int varIndex = 0; newMv.visitLdcInsn(cc.outArgs.length + 1); // additional cell for the AllAsObjects array newMv.visitTypeInsn(ANEWARRAY, OBJ_TYPE.getInternalName()); // stack >> prmsArr newMv.visitInsn(DUP);/*from www. j a v a 2 s. c om*/ newMv.visitLdcInsn(cc.outArgs.length); newMv.visitInsn(DUP); newMv.visitTypeInsn(ANEWARRAY, OBJ_TYPE.getInternalName()); // stack >> prmsArr prmsArr n asObjArr newMv.visitInsn(AASTORE); // stack >> prmsArr for (int i = 0; i < cc.outArgs.length; i++) { Type ia = cc.inArgs[i]; newMv.visitInsn(DUP); newMv.visitInsn(DUP); newMv.visitLdcInsn(cc.outArgs.length); // stack >> prmsArr prmsArr prmsArr n newMv.visitInsn(AALOAD); newMv.visitTypeInsn(CHECKCAST, "[" + OBJ_TYPE.getDescriptor()); // stack >> prmsArr prmsArr asObjArr newMv.visitLdcInsn(i); // stack >> prmsArr prmsArr asObjArr i newMv.visitVarInsn(getLoadOpcode(ia), varIndex); convertPrimitiveToObject(newMv, cc.inArgs[i]); // stack >> prmsArr prmsArr asObjArr i pi newMv.visitInsn(AASTORE); // stack >> prmsArr prmsArr newMv.visitLdcInsn(i); // stack >> prmsArr prmsArr i newMv.visitVarInsn(getLoadOpcode(ia), varIndex); varIndex += cc.inArgs[i].getSize(); // stack >> prmsArr prmsArr i pi boolean keepBothVersions = (ia.getSort() == Type.ARRAY); if (keepBothVersions) { // keep the old reference (the Cojac one) newMv.visitLdcInsn(2); newMv.visitTypeInsn(ANEWARRAY, OBJ_TYPE.getInternalName()); // stack >> prmsArr prmsArr i pi piArr newMv.visitInsn(DUP_X1); // stack >> prmsArr prmsArr i piArr pi piArr newMv.visitInsn(SWAP); // stack >> prmsArr prmsArr i piArr piArr pi newMv.visitInsn(DUP_X1); newMv.visitLdcInsn(0); newMv.visitInsn(SWAP); // stack >> prmsArr prmsArr i piArr pi piArr pi 0 newMv.visitInsn(AASTORE); // stack >> prmsArr prmsArr i piArr } // stack >> prmsArr prmsArr i pi if (cc.needsConversion(i)) { convertCojacToRealType(cc.asOriginalJavaType(i), newMv); } else if (cc.shouldObjParamBeConverted && (ia.equals(OBJ_TYPE) || ia.equals(OBJ_ARRAY_TYPE))) { convertObjectToReal(newMv, ia); } /* This is where we could decide to convert back to JavaWrapper * when the argument is declared as Object * We don't do that to keep "enriched numbers" in collections * but sometimes we would like to convert, eg printf, format... */ convertPrimitiveToObject(newMv, cc.outArgs[i]); // stack >> prmsArr prmsArr i pi if (keepBothVersions) { // keep the new reference (the java one) newMv.visitInsn(SWAP); newMv.visitInsn(DUP_X1); newMv.visitInsn(SWAP); newMv.visitLdcInsn(1); newMv.visitInsn(SWAP); newMv.visitInsn(AASTORE); } // stack >> prmsArr prmsArr i pi newMv.visitInsn(AASTORE); // stack >> prmsArr } newMv.visitInsn(ARETURN); newMv.visitMaxs(0, 0); }
From source file:cn.annoreg.asm.DelegateGenerator.java
License:Open Source License
public static MethodVisitor generateStaticMethod(ClassVisitor parentClass, MethodVisitor parent, String className, String methodName, String desc, final Side side) { //This method is a little bit complicated. //We need to generate a delegate class implementing NetworkCallDelegate and a redirect //the code that originally generated here in parent, into the delegate class, //by returning a MethodVisitor under the ClassVisitor of the delegate class. //Besides, we should generate a call to NetworkCallManager into parent. //Above is the original method. Now it has a little bit change. To allow private call in //here, we need to generate the delegate method in this class instead of in a delegate class. //We make the delegate method public so that the delegate class can call it. //delegateName is a string used by both sides to identify a network-call delegate. final String delegateName = className + ":" + methodName + ":" + desc; final Type[] args = Type.getArgumentTypes(desc); final Type ret = Type.getReturnType(desc); //Check types for (Type t : args) { //TODO support these types if (!t.getDescriptor().startsWith("L") && !t.getDescriptor().startsWith("[")) { throw new RuntimeException("Unsupported argument type in network call. in method " + methodName + ", " + t.getDescriptor()); }//from www. j av a2 s. c o m } if (!ret.equals(Type.VOID_TYPE)) { throw new RuntimeException( "Unsupported return value type in network call. " + "Only void is supported."); } //Generate call to NetworkCallManager in parent. parent.visitCode(); //First parameter parent.visitLdcInsn(delegateName); //Second parameter: object array pushIntegerConst(parent, args.length); //array size parent.visitTypeInsn(Opcodes.ANEWARRAY, Type.getInternalName(Object.class)); for (int i = 0; i < args.length; ++i) { parent.visitInsn(Opcodes.DUP); pushIntegerConst(parent, i); parent.visitVarInsn(Opcodes.ALOAD, i); parent.visitInsn(Opcodes.AASTORE); } //Call cn.annoreg.mc.network.NetworkCallManager.onNetworkCall parent.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(NetworkCallManager.class), "onNetworkCall", Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(String.class), Type.getType(Object[].class))); parent.visitInsn(Opcodes.RETURN); parent.visitMaxs(5, args.length); parent.visitEnd(); //Create delegate object. final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); final String delegateId = Integer.toString(delegateNextID++); final Type delegateClassType = Type.getType("cn/annoreg/asm/NetworkCallDelegate_" + delegateId); cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC, delegateClassType.getInternalName(), null, Type.getInternalName(Object.class), new String[] { Type.getInternalName(NetworkCallDelegate.class) }); //package cn.annoreg.asm; //class NetworkCallDelegate_? implements NetworkCallDelegate { { MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null); mv.visitCode(); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Object.class), "<init>", "()V"); mv.visitInsn(Opcodes.RETURN); mv.visitMaxs(1, 1); mv.visitEnd(); } //public NetworkCallDelegate_?() {} final String delegateFunctionName = methodName + "_delegate_" + delegateId; { MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "invoke", Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(Object[].class)), null, null); mv.visitCode(); for (int i = 0; i < args.length; ++i) { mv.visitVarInsn(Opcodes.ALOAD, 1); //0 is this pushIntegerConst(mv, i); mv.visitInsn(Opcodes.AALOAD); mv.visitTypeInsn(Opcodes.CHECKCAST, args[i].getInternalName()); } mv.visitMethodInsn(Opcodes.INVOKESTATIC, //delegateClassType.getInternalName(), //changed to original class className.replace('.', '/'), delegateFunctionName, desc); mv.visitInsn(Opcodes.RETURN); mv.visitMaxs(args.length + 2, 2); mv.visitEnd(); } //@Override public void invoke(Object[] args) { // xxxx.xxxx_delegated_xxx((Type0) args[0], (Type1) args[1], ...); //} //The returned MethodVisitor will visit the original version of the method, //including its annotation, where we can get StorageOptions. return new MethodVisitor(Opcodes.ASM4, parentClass.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, delegateFunctionName, desc, null, null)) { //Remember storage options for each argument StorageOption.Option[] options = new StorageOption.Option[args.length]; int targetIndex = -1; StorageOption.Target.RangeOption range = StorageOption.Target.RangeOption.SINGLE; double sendRange = -1; { for (int i = 0; i < options.length; ++i) { options[i] = StorageOption.Option.NULL; //set default value } } @Override public AnnotationVisitor visitParameterAnnotation(final int parameter, String desc, boolean visible) { Type type = Type.getType(desc); if (type.equals(Type.getType(StorageOption.Data.class))) { options[parameter] = StorageOption.Option.DATA; } else if (type.equals(Type.getType(StorageOption.Instance.class))) { //INSTANCE as defualt options[parameter] = StorageOption.Option.INSTANCE; //Change to NULLABLE_INSTANCE if nullable set to true return new AnnotationVisitor(this.api, super.visitParameterAnnotation(parameter, desc, visible)) { @Override public void visit(String name, Object value) { if (name.equals("nullable")) { if ((Boolean) value == true) { options[parameter] = StorageOption.Option.NULLABLE_INSTANCE; } } super.visit(name, value); } }; } else if (type.equals(Type.getType(StorageOption.Update.class))) { options[parameter] = StorageOption.Option.UPDATE; } else if (type.equals(Type.getType(StorageOption.Null.class))) { options[parameter] = StorageOption.Option.NULL; } else if (type.equals(Type.getType(StorageOption.Target.class))) { if (!args[parameter].equals(Type.getType(EntityPlayer.class))) { throw new RuntimeException("Target annotation can only be used on EntityPlayer."); } if (targetIndex != -1) { throw new RuntimeException("You can not specify multiple targets."); } options[parameter] = StorageOption.Option.INSTANCE; targetIndex = parameter; return new AnnotationVisitor(this.api, super.visitParameterAnnotation(parameter, desc, visible)) { @Override public void visitEnum(String name, String desc, String value) { super.visitEnum(name, desc, value); range = StorageOption.Target.RangeOption.valueOf(value); } }; } else if (type.equals(Type.getType(StorageOption.RangedTarget.class))) { if (targetIndex != -1) { throw new RuntimeException("You can not specify multiple targets."); } range = null; targetIndex = parameter; return new AnnotationVisitor(this.api, super.visitParameterAnnotation(parameter, desc, visible)) { @Override public void visit(String name, Object value) { super.visit(name, value); sendRange = (double) value; } }; } return super.visitParameterAnnotation(parameter, desc, visible); } @Override public void visitEnd() { super.visitEnd(); //This is the last method in the delegate class. //Finish the class and do the registration. cw.visitEnd(); try { Class<?> clazz = classLoader.defineClass(delegateClassType.getClassName(), cw.toByteArray()); NetworkCallDelegate delegateObj = (NetworkCallDelegate) clazz.newInstance(); if (side == Side.CLIENT) { NetworkCallManager.registerClientDelegateClass(delegateName, delegateObj, options, targetIndex, range, sendRange); } else { NetworkCallManager.registerServerDelegateClass(delegateName, delegateObj, options); } } catch (Throwable e) { throw new RuntimeException("Can not create delegate for network call.", e); } } }; //public static void delegated(Type0 arg0, Type1, arg1, ...) { // //Code generated by caller. //} //} }
From source file:cn.annoreg.asm.DelegateGenerator.java
License:Open Source License
public static MethodVisitor generateNonStaticMethod(ClassVisitor parentClass, MethodVisitor parent, String className, String methodName, String desc, final Side side) { //convert desc to a non-static method form String nonstaticDesc;/*from ww w . j a va 2 s . c om*/ { Type staticType = Type.getMethodType(desc); Type retType = staticType.getReturnType(); Type[] argsType = staticType.getArgumentTypes(); Type[] argsTypeWithThis = new Type[argsType.length + 1]; argsTypeWithThis[0] = Type.getType('L' + className.replace('.', '/') + ';'); System.arraycopy(argsType, 0, argsTypeWithThis, 1, argsType.length); nonstaticDesc = Type.getMethodDescriptor(retType, argsTypeWithThis); } //delegateName is a string used by both sides to identify a network-call delegate. final String delegateName = className + ":" + methodName + ":" + desc; final Type[] args = Type.getArgumentTypes(nonstaticDesc); final Type ret = Type.getReturnType(nonstaticDesc); //Check types for (Type t : args) { //TODO support these types if (!t.getDescriptor().startsWith("L") && !t.getDescriptor().startsWith("[")) { throw new RuntimeException("Unsupported argument type in network call. "); } } if (!ret.equals(Type.VOID_TYPE)) { throw new RuntimeException( "Unsupported return value type in network call. " + "Only void is supported."); } //Generate call to NetworkCallManager in parent. parent.visitCode(); //First parameter parent.visitLdcInsn(delegateName); //Second parameter: object array pushIntegerConst(parent, args.length); //this (0) has been included parent.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); for (int i = 0; i < args.length; ++i) { parent.visitInsn(Opcodes.DUP); pushIntegerConst(parent, i); parent.visitVarInsn(Opcodes.ALOAD, i); parent.visitInsn(Opcodes.AASTORE); } //Call cn.annoreg.mc.network.NetworkCallManager.onNetworkCall parent.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(NetworkCallManager.class), "onNetworkCall", "(Ljava/lang/String;[Ljava/lang/Object;)V"); parent.visitInsn(Opcodes.RETURN); parent.visitMaxs(5, args.length); parent.visitEnd(); //Create delegate object. final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); final String delegateId = Integer.toString(delegateNextID++); final Type delegateClassType = Type.getType("cn/annoreg/asm/NetworkCallDelegate_" + delegateId); cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC, delegateClassType.getInternalName(), null, Type.getInternalName(Object.class), new String[] { Type.getInternalName(NetworkCallDelegate.class) }); //package cn.annoreg.asm; //class NetworkCallDelegate_? implements NetworkCallDelegate { { MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null); mv.visitCode(); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Object.class), "<init>", "()V"); mv.visitInsn(Opcodes.RETURN); mv.visitMaxs(1, 1); mv.visitEnd(); } //public NetworkCallDelegate_?() {} final String delegateMethodName = methodName + "_delegate_" + delegateId; { MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "invoke", Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(Object[].class)), null, null); mv.visitCode(); //check if this is null mv.visitVarInsn(Opcodes.ALOAD, 1); //0 is this pushIntegerConst(mv, 0); mv.visitInsn(Opcodes.AALOAD); Label lblEnd = new Label(); mv.visitJumpInsn(Opcodes.IFNULL, lblEnd); for (int i = 0; i < args.length; ++i) { mv.visitVarInsn(Opcodes.ALOAD, 1); //0 is this pushIntegerConst(mv, i); mv.visitInsn(Opcodes.AALOAD); mv.visitTypeInsn(Opcodes.CHECKCAST, args[i].getInternalName()); } mv.visitMethodInsn(Opcodes.INVOKESTATIC, //delegateClassType.getInternalName(), className.replace('.', '/'), delegateMethodName, nonstaticDesc); mv.visitLabel(lblEnd); mv.visitInsn(Opcodes.RETURN); mv.visitMaxs(args.length + 2, 2); mv.visitEnd(); } //@Override public void invoke(Object[] args) { // delegated((Type0) args[0], (Type1) args[1], ...); //} //The returned MethodVisitor will visit the original version of the method, //including its annotation, where we can get StorageOptions. return new MethodVisitor(Opcodes.ASM4, parentClass.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, delegateMethodName, nonstaticDesc, null, null)) { //Remember storage options for each argument StorageOption.Option[] options = new StorageOption.Option[args.length]; int targetIndex = -1; double sendRange = -1; StorageOption.Target.RangeOption range = StorageOption.Target.RangeOption.SINGLE; { for (int i = 0; i < options.length; ++i) { options[i] = StorageOption.Option.NULL; //set default value } options[0] = StorageOption.Option.INSTANCE; } @Override public AnnotationVisitor visitParameterAnnotation(int parameter_in_func, String desc, boolean visible) { final int parameter = parameter_in_func + 1; //skip this Type type = Type.getType(desc); if (type.equals(Type.getType(StorageOption.Data.class))) { options[parameter] = StorageOption.Option.DATA; } else if (type.equals(Type.getType(StorageOption.Instance.class))) { //INSTANCE as defualt options[parameter] = StorageOption.Option.INSTANCE; //Change to NULLABLE_INSTANCE if nullable set to true return new AnnotationVisitor(this.api, super.visitParameterAnnotation(parameter, desc, visible)) { @Override public void visit(String name, Object value) { if (name.equals("nullable")) { if ((Boolean) value == true) { options[parameter] = StorageOption.Option.NULLABLE_INSTANCE; } } super.visit(name, value); } }; } else if (type.equals(Type.getType(StorageOption.Update.class))) { options[parameter] = StorageOption.Option.UPDATE; } else if (type.equals(Type.getType(StorageOption.Null.class))) { options[parameter] = StorageOption.Option.NULL; } else if (type.equals(Type.getType(StorageOption.Target.class))) { if (!args[parameter].equals(Type.getType(EntityPlayer.class))) { throw new RuntimeException("Target annotation can only be used on EntityPlayer."); } if (targetIndex != -1) { throw new RuntimeException("You can not specify multiple targets."); } options[parameter] = StorageOption.Option.INSTANCE; targetIndex = parameter; return new AnnotationVisitor(this.api, super.visitParameterAnnotation(parameter, desc, visible)) { @Override public void visitEnum(String name, String desc, String value) { super.visitEnum(name, desc, value); range = StorageOption.Target.RangeOption.valueOf(value); } }; } else if (type.equals(Type.getType(StorageOption.RangedTarget.class))) { if (targetIndex != -1) { throw new RuntimeException("You can not specify multiple targets."); } targetIndex = parameter; range = null; return new AnnotationVisitor(this.api, super.visitParameterAnnotation(parameter, desc, visible)) { @Override public void visit(String name, Object value) { super.visit(name, value); sendRange = (double) value; } }; } return super.visitParameterAnnotation(parameter, desc, visible); } //TODO this option (from annotation) @Override public void visitEnd() { super.visitEnd(); //This is the last method in the delegate class. //Finish the class and do the registration. cw.visitEnd(); try { Class<?> clazz = classLoader.defineClass(delegateClassType.getClassName(), cw.toByteArray()); NetworkCallDelegate delegateObj = (NetworkCallDelegate) clazz.newInstance(); if (side == Side.CLIENT) { NetworkCallManager.registerClientDelegateClass(delegateName, delegateObj, options, targetIndex, range, sendRange); } else { NetworkCallManager.registerServerDelegateClass(delegateName, delegateObj, options); } } catch (Throwable e) { throw new RuntimeException("Can not create delegate for network call.", e); } } }; //public static void delegated(Type0 arg0, Type1, arg1, ...) { // //Code generated by caller. //} //} }