private static byte[] generate(String name, Class<?> type, Class<?> parameter) { name = name.replace('.', '/'); String typeName = Type.getInternalName(type); String typeDesc = Type.getDescriptor(type); String parameterName = Type.getInternalName(parameter); String parameterDesc = Type.getDescriptor(parameter); String constructSignature = '(' + parameterDesc + ')' + typeDesc; ClassWriter cw = new ClassWriter(0); MethodVisitor mv; cw.visit(V1_6, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, name, null, BASE_CLASS, null); { mv = cw.visitMethod(ACC_PUBLIC, "<init>", "(Ljava/lang/Class;)V", null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn(INVOKESPECIAL, BASE_CLASS, "<init>", "(Ljava/lang/Class;)V", false); mv.visitInsn(RETURN); mv.visitMaxs(2, 2); mv.visitEnd(); } { mv = cw.visitMethod(ACC_PUBLIC, "construct", constructSignature, null, null); mv.visitCode(); mv.visitTypeInsn(NEW, typeName); mv.visitInsn(DUP); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn(INVOKESPECIAL, typeName, "<init>", '(' + parameterDesc + ")V", false); mv.visitInsn(ARETURN); mv.visitMaxs(3, 2); mv.visitEnd(); } { mv = cw.visitMethod( ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "construct", "(Ljava/lang/Object;)Ljava/lang/Object;", null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitTypeInsn(CHECKCAST, parameterName); mv.visitMethodInsn(INVOKEVIRTUAL, name, "construct", constructSignature, false); mv.visitInsn(ARETURN); mv.visitMaxs(2, 2); mv.visitEnd(); } cw.visitEnd(); return cw.toByteArray(); }
public Class<?> createWrapper(Method callback) { ClassWriter cw = new ClassWriter(0); MethodVisitor mv; String name = getUniqueName(callback); String desc = name.replace('.', '/'); String instType = Type.getInternalName(callback.getDeclaringClass()); String eventType = Type.getInternalName(callback.getParameterTypes()[0]); /* System.out.println("Name: " + name); System.out.println("Desc: " + desc); System.out.println("InstType: " + instType); System.out.println("Callback: " + callback.getName() + Type.getMethodDescriptor(callback)); System.out.println("Event: " + eventType); */ cw.visit( V1_6, ACC_PUBLIC | ACC_SUPER, desc, null, "java/lang/Object", new String[] {HANDLER_DESC}); cw.visitSource(".dynamic", null); { cw.visitField(ACC_PUBLIC, "instance", "Ljava/lang/Object;", null, null).visitEnd(); } { mv = cw.visitMethod(ACC_PUBLIC, "<init>", "(Ljava/lang/Object;)V", null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V"); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitFieldInsn(PUTFIELD, desc, "instance", "Ljava/lang/Object;"); mv.visitInsn(RETURN); mv.visitMaxs(2, 2); mv.visitEnd(); } { mv = cw.visitMethod(ACC_PUBLIC, "invoke", HANDLER_FUNC_DESC, null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, desc, "instance", "Ljava/lang/Object;"); mv.visitTypeInsn(CHECKCAST, instType); mv.visitVarInsn(ALOAD, 1); mv.visitTypeInsn(CHECKCAST, eventType); mv.visitMethodInsn( INVOKEVIRTUAL, instType, callback.getName(), Type.getMethodDescriptor(callback)); mv.visitInsn(RETURN); mv.visitMaxs(2, 2); mv.visitEnd(); } cw.visitEnd(); return LOADER.define(name, cw.toByteArray()); }
private void declareClass( ClassVisitor visitor, Collection<String> interfaceInternalNames, Type generatedType, Type superclassType) { visitor.visit( V1_6, ACC_PUBLIC, generatedType.getInternalName(), null, superclassType.getInternalName(), Iterables.toArray(interfaceInternalNames, String.class)); }
// the overload of type Object for Groovy coercions: public void setFoo(Object foo) private void createTypeConvertingSetter( ClassVisitor visitor, Type generatedType, ModelProperty<?> property) { if (!property.isWritable() || !(property.getSchema() instanceof ScalarValueSchema)) { return; } Class<?> propertyClass = property.getType().getConcreteClass(); Type propertyType = Type.getType(propertyClass); Class<?> boxedClass = propertyClass.isPrimitive() ? BOXED_TYPES.get(propertyClass) : propertyClass; Type boxedType = Type.getType(boxedClass); Method setter = property.getSetter().getMethod(); MethodVisitor methodVisitor = declareMethod( visitor, setter.getName(), SET_OBJECT_PROPERTY_DESCRIPTOR, SET_OBJECT_PROPERTY_DESCRIPTOR); putThisOnStack(methodVisitor); putTypeConverterFieldValueOnStack(methodVisitor, generatedType); // Object converted = $typeConverter.convert(foo, Float.class, false); methodVisitor.visitVarInsn(ALOAD, 1); // put var #1 ('foo') on the stack methodVisitor.visitLdcInsn(boxedType); // push the constant Class onto the stack methodVisitor.visitInsn( propertyClass.isPrimitive() ? ICONST_1 : ICONST_0); // push int 1 or 0 (interpreted as true or false) onto the stack methodVisitor.visitMethodInsn( INVOKEINTERFACE, TYPE_CONVERTER_TYPE.getInternalName(), "convert", COERCE_TO_SCALAR_DESCRIPTOR, true); methodVisitor.visitTypeInsn(CHECKCAST, boxedType.getInternalName()); if (propertyClass.isPrimitive()) { unboxType(methodVisitor, propertyClass); } // invoke the typed setter, popping 'this' and 'converted' from the stack methodVisitor.visitMethodInsn( INVOKEVIRTUAL, generatedType.getInternalName(), setter.getName(), Type.getMethodDescriptor(Type.VOID_TYPE, propertyType), false); finishVisitingMethod(methodVisitor); }
@Override public Type emit_const(MethodVisitor fa) { Type type = ELIST_TYPE; fa.visitTypeInsn(Opcodes.NEW, type.getInternalName()); fa.visitInsn(Opcodes.DUP); ((EObject) head).emit_const(fa); ((EObject) tail).emit_const(fa); fa.visitMethodInsn(Opcodes.INVOKESPECIAL, type.getInternalName(), "<init>", CONSTRUCTOR_DESC); return type; }
@Override protected void insertTransform( MethodVisitor mv, Parameter param, Class<?> targetType, int local) { mv.visitVarInsn(ALOAD, local); Label failure = new Label(); Label success = new Label(); mv.visitMethodInsn(INVOKEVIRTUAL, "java/util/Optional", "isPresent", "()Z", false); mv.visitJumpInsn(IFEQ, failure); // Unwrap the optional mv.visitVarInsn(ALOAD, local); mv.visitMethodInsn(INVOKEVIRTUAL, "java/util/Optional", "get", "()Ljava/lang/Object;", false); mv.visitVarInsn(ASTORE, local); mv.visitVarInsn(ALOAD, local); mv.visitTypeInsn(INSTANCEOF, Type.getInternalName(targetType)); if (this.anno.typeFilter().length != 0) { mv.visitJumpInsn(IFEQ, failure); mv.visitVarInsn(ALOAD, local); // For each type we do an instance check and jump to either failure or success if matched for (int i = 0; i < this.anno.typeFilter().length; i++) { Class<?> filter = this.anno.typeFilter()[i]; if (i < this.anno.typeFilter().length - 1) { mv.visitInsn(DUP); } mv.visitTypeInsn(INSTANCEOF, Type.getInternalName(filter)); if (this.anno.inverse()) { mv.visitJumpInsn(IFNE, failure); } else { mv.visitJumpInsn(IFNE, success); } } if (this.anno.inverse()) { mv.visitJumpInsn(GOTO, success); } // If the annotation was not reversed then we fall into failure as no types were matched } else { mv.visitJumpInsn(IFNE, success); } mv.visitLabel(failure); mv.visitInsn(ACONST_NULL); mv.visitInsn(ARETURN); mv.visitLabel(success); }
private boolean classIsDefinitelyMutable(ClassNode klass) { if (superClassIsDefinitelyMutable(klass.superName)) { log.add("Mutable parent: " + klass.name + " < " + klass.superName); return true; } for (FieldNode field : klass.fields) { if ((field.access & Opcodes.ACC_STATIC) != 0) { continue; } if ((field.access & Opcodes.ACC_FINAL) == 0) { log.add("Non-final field: " + klass.name + "#" + field.name + ":" + field.desc); return true; } if (field.name.contains("$")) { // Generated fields are assumed to be effectively immutable. // This could, in principle, miss an issue like a static reference to a // seemingly-immutable inner class object that maintains a hidden reference // to its mutable outer object, but that seems unlikely. continue; } Type type = Type.getType(field.desc); if (IMMUTABLE_TYPE_SORTS.contains(type.getSort())) { continue; } if (type.getSort() != Type.OBJECT) { log.add("Odd sort: " + klass.name + "#" + field.name + ":" + field.desc); return true; } if (allClasses.keySet().contains(type.getInternalName())) { if (classesWithMutableDescendents.contains(type.getInternalName())) { log.add("Internal mutable field: " + klass.name + "#" + field.name + ":" + field.desc); return true; } } else { if (!EXTERNAL_IMMUTABLE_CLASSES.contains(type.getInternalName())) { log.add("External mutable field: " + klass.name + "#" + field.name + ":" + field.desc); return true; } } } return false; }
public static Class<?> getClassForType(Type type) { checkArgNotNull(type, "type"); switch (type.getSort()) { case Type.BOOLEAN: return boolean.class; case Type.BYTE: return byte.class; case Type.CHAR: return char.class; case Type.DOUBLE: return double.class; case Type.FLOAT: return float.class; case Type.INT: return int.class; case Type.LONG: return long.class; case Type.SHORT: return short.class; case Type.VOID: return void.class; case Type.OBJECT: case Type.ARRAY: return getClassForInternalName(type.getInternalName()); } throw new IllegalStateException(); // should be unreachable }
private void generateAccessor( ClassWriter cw, Class<?> parentType, String internalName, Property<Class<?>, Method> property) { Method accessor = property.getAccessor(); MethodVisitor mv = cw.visitMethod( ACC_PUBLIC, accessor.getName(), Type.getMethodDescriptor(accessor), null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn( GETFIELD, internalName, property.getName(), Type.getDescriptor(property.getLeastSpecificType())); if (!property.isLeastSpecificType()) { mv.visitTypeInsn(CHECKCAST, Type.getInternalName(property.getType())); } mv.visitInsn(Type.getType(property.getType()).getOpcode(IRETURN)); mv.visitMaxs(0, 0); mv.visitEnd(); }
/** * Insert the necessary methods to unbox a primitive type (if the given type is a primitive). * * @param mv The method visitor * @param type The type to unbox */ public static void visitUnboxingMethod(MethodVisitor mv, Type type) { if (type.getSort() == Type.BOOLEAN) { mv.visitTypeInsn(CHECKCAST, "java/lang/Boolean"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false); } else if (type.getSort() == Type.INT) { mv.visitTypeInsn(CHECKCAST, "java/lang/Integer"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false); } else if (type.getSort() == Type.BYTE) { mv.visitTypeInsn(CHECKCAST, "java/lang/Byte"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false); } else if (type.getSort() == Type.SHORT) { mv.visitTypeInsn(CHECKCAST, "java/lang/Short"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false); } else if (type.getSort() == Type.LONG) { mv.visitTypeInsn(CHECKCAST, "java/lang/Long"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false); } else if (type.getSort() == Type.FLOAT) { mv.visitTypeInsn(CHECKCAST, "java/lang/Float"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false); } else if (type.getSort() == Type.DOUBLE) { mv.visitTypeInsn(CHECKCAST, "java/lang/Double"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false); } else if (type.getSort() == Type.CHAR) { mv.visitTypeInsn(CHECKCAST, "java/lang/Character"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C", false); } else { mv.visitTypeInsn(CHECKCAST, type.getInternalName()); } }
private void castFirstStackElement(MethodVisitor methodVisitor, Class<?> returnType) { if (returnType.isPrimitive()) { unboxType(methodVisitor, returnType); } else { methodVisitor.visitTypeInsn(CHECKCAST, Type.getInternalName(returnType)); } }
@Override public DataType visitPrint_stmt(@NotNull PythonParser.Print_stmtContext ctx) { mv.visitFieldInsn( GETSTATIC, Type.getInternalName(System.class), "out", Type.getDescriptor(PrintStream.class)); DataType type = visitTest(ctx.test()); mv.visitMethodInsn( INVOKEVIRTUAL, Type.getInternalName(PrintStream.class), "println", Type.getMethodDescriptor(Type.VOID_TYPE, type.getType()), false); return null; }
public void addSetMethod(MetaBeanProperty property) throws Exception { MetaMethod setter = property.getSetter(); Type paramType = Type.getType(setter.getParameterTypes()[0].getTheClass()); Type returnType = Type.getType(setter.getReturnType()); String setterDescriptor = Type.getMethodDescriptor(returnType, new Type[] {paramType}); // GENERATE public void <propName>(<type> v) { <setter>(v) } String setMethodDescriptor = Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {paramType}); MethodVisitor methodVisitor = visitor.visitMethod( Opcodes.ACC_PUBLIC, property.getName(), setMethodDescriptor, null, new String[0]); methodVisitor.visitCode(); // GENERATE <setter>(v) methodVisitor.visitVarInsn(Opcodes.ALOAD, 0); methodVisitor.visitVarInsn(paramType.getOpcode(Opcodes.ILOAD), 1); methodVisitor.visitMethodInsn( Opcodes.INVOKEVIRTUAL, generatedType.getInternalName(), setter.getName(), setterDescriptor); // END methodVisitor.visitInsn(Opcodes.RETURN); methodVisitor.visitMaxs(0, 0); methodVisitor.visitEnd(); }
private int firePeacefulRegenEventAndStoreEventBefore( MethodNode method, AbstractInsnNode injectPoint, LabelNode endLabel) { // create variable LabelNode peacefulRegenEventStart = new LabelNode(); LocalVariableNode peacefulRegenEvent = new LocalVariableNode( "peacefulRegenEvent", Type.getDescriptor(HealthRegenEvent.PeacefulRegen.class), null, peacefulRegenEventStart, endLabel, method.maxLocals); method.maxLocals += 1; method.localVariables.add(peacefulRegenEvent); InsnList toInject = new InsnList(); // HealthRegenEvent.PeacefulRegen peacefulRegenEvent = Hooks.firePeacefulRegenEvent(this); toInject.add(new VarInsnNode(ALOAD, 0)); toInject.add( new MethodInsnNode( INVOKESTATIC, Type.getInternalName(Hooks.class), "firePeacefulRegenEvent", "(Lnet/minecraft/entity/player/EntityPlayer;)Lsqueek/applecore/api/hunger/HealthRegenEvent$PeacefulRegen;", false)); toInject.add(new VarInsnNode(ASTORE, peacefulRegenEvent.index)); toInject.add(peacefulRegenEventStart); method.instructions.insertBefore(injectPoint, toInject); return peacefulRegenEvent.index; }
/** * Creates a new local variable of the given type. * * @param type the type of the local variable to be created. * @return the identifier of the newly created local variable. */ public int newLocal(final Type type) { Object t; switch (type.getSort()) { case Type.BOOLEAN: case Type.CHAR: case Type.BYTE: case Type.SHORT: case Type.INT: t = Opcodes.INTEGER; break; case Type.FLOAT: t = Opcodes.FLOAT; break; case Type.LONG: t = Opcodes.LONG; break; case Type.DOUBLE: t = Opcodes.DOUBLE; break; case Type.ARRAY: t = type.getDescriptor(); break; // case Type.OBJECT: default: t = type.getInternalName(); break; } int local = newLocalMapping(type); setLocalType(local, type); setFrameLocal(local, t); return local; }
private Type getMirrorType(final Type type) { int numDimensions = 0; final Type basicType; if (type.getSort() == Type.ARRAY) { numDimensions = type.getDimensions(); basicType = type.getElementType(); } else { basicType = type; } if (basicType.getSort() != Type.OBJECT) { return type; } final Mirror mirror = getMirror(basicType.getInternalName()); if (mirror.isClassMirror()) { final StringBuilder name = new StringBuilder(); for (int i = 0; i < numDimensions; ++i) { name.append('['); } name.append('L').append(mirror.getTranslatedName()).append(';'); return Type.getType(name.toString()); } return type; }
private static byte[] generateEventExecutor(Method m, String name) { final boolean staticMethod = Modifier.isStatic(m.getModifiers()); ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); writer.visit( V1_8, ACC_PUBLIC, name, null, "java/lang/Object", new String[] {Type.getInternalName(EventExecutor.class)}); // Generate constructor MethodVisitor methodGenerator = writer.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); methodGenerator.visitVarInsn(ALOAD, 0); methodGenerator.visitMethodInsn( INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false); // Invoke the super class (Object) constructor methodGenerator.visitInsn(RETURN); methodGenerator.visitMaxs(1, 1); methodGenerator.visitEnd(); // Generate the execute method methodGenerator = writer.visitMethod( ACC_PUBLIC, "fire", "(Ljava/lang/Object;Ljava/lang/Object;)V", null, null); if (!staticMethod) { methodGenerator.visitVarInsn(ALOAD, 1); methodGenerator.visitTypeInsn(CHECKCAST, Type.getInternalName(m.getDeclaringClass())); } methodGenerator.visitVarInsn(ALOAD, 2); methodGenerator.visitTypeInsn(CHECKCAST, Type.getInternalName(m.getParameterTypes()[0])); methodGenerator.visitMethodInsn( staticMethod ? INVOKESTATIC : INVOKEVIRTUAL, Type.getInternalName(m.getDeclaringClass()), m.getName(), Type.getMethodDescriptor(m), m.getDeclaringClass().isInterface()); if (m.getReturnType() != void.class) { methodGenerator.visitInsn(POP); } methodGenerator.visitInsn(RETURN); methodGenerator.visitMaxs(staticMethod ? 1 : 2, 3); methodGenerator.visitEnd(); writer.visitEnd(); return writer.toByteArray(); }
private void invokeSuperConstructor(MethodVisitor constructorVisitor, Type superclassType) { putThisOnStack(constructorVisitor); constructorVisitor.visitMethodInsn( INVOKESPECIAL, superclassType.getInternalName(), CONSTRUCTOR_NAME, Type.getMethodDescriptor(Type.VOID_TYPE), false); }
@Override public void visitLdcInsn(Object cst) { if (cst instanceof Type) { Type type = (Type) cst; AsmClass usedClass = asmClassProvider.getClass(type.getInternalName(), DETAIL_LEVEL.NOTHING); method.addEdge(new AsmEdge(method, usedClass, SourceCodeEdgeUsage.USES, lineNumber)); } emptyMethod = false; }
private void boxType(MethodVisitor methodVisitor, Class<?> primitiveType) { Class<?> boxedType = BOXED_TYPES.get(primitiveType); methodVisitor.visitMethodInsn( INVOKESTATIC, Type.getInternalName(boxedType), "valueOf", "(" + Type.getDescriptor(primitiveType) + ")" + Type.getDescriptor(boxedType), false); }
private void assignStateField(MethodVisitor constructorVisitor, Type generatedType) { putThisOnStack(constructorVisitor); putFirstMethodArgumentOnStack(constructorVisitor); constructorVisitor.visitFieldInsn( PUTFIELD, generatedType.getInternalName(), STATE_FIELD_NAME, MODEL_ELEMENT_STATE_TYPE.getDescriptor()); }
private void assignTypeConverterField(MethodVisitor constructorVisitor, Type generatedType) { putThisOnStack(constructorVisitor); putSecondMethodArgumentOnStack(constructorVisitor); constructorVisitor.visitFieldInsn( PUTFIELD, generatedType.getInternalName(), TYPE_CONVERTER_FIELD_NAME, TYPE_CONVERTER_TYPE.getDescriptor()); }
private void invokeSuperMethod(MethodVisitor methodVisitor, Class<?> superClass, Method method) { putThisOnStack(methodVisitor); methodVisitor.visitMethodInsn( INVOKESPECIAL, Type.getInternalName(superClass), method.getName(), Type.getMethodDescriptor(method), false); }
@Override protected void insertCauseCall(MethodVisitor mv, Parameter param, Class<?> targetType) { mv.visitLdcInsn(Type.getType(this.anno.value())); mv.visitMethodInsn( INVOKEVIRTUAL, Type.getInternalName(Cause.class), "after", "(Ljava/lang/Class;)Ljava/util/Optional;", false); }
private void assignDelegateField( MethodVisitor constructorVisitor, Type generatedType, Type delegateType) { putThisOnStack(constructorVisitor); putThirdMethodArgumentOnStack(constructorVisitor); constructorVisitor.visitFieldInsn( PUTFIELD, generatedType.getInternalName(), DELEGATE_FIELD_NAME, delegateType.getDescriptor()); }
public void addSetter(MetaBeanProperty property) throws Exception { MetaMethod setter = property.getSetter(); // GENERATE public <return-type> <setter>(<type> v) { <return-type> v = super.<setter>(v); // <prop>Set = true; return v; } Type paramType = Type.getType(setter.getParameterTypes()[0].getTheClass()); Type returnType = Type.getType(setter.getReturnType()); String setterDescriptor = Type.getMethodDescriptor(returnType, new Type[] {paramType}); MethodVisitor methodVisitor = visitor.visitMethod( Opcodes.ACC_PUBLIC, setter.getName(), setterDescriptor, null, new String[0]); methodVisitor.visitCode(); // GENERATE super.<setter>(v) methodVisitor.visitVarInsn(Opcodes.ALOAD, 0); methodVisitor.visitVarInsn(paramType.getOpcode(Opcodes.ILOAD), 1); methodVisitor.visitMethodInsn( Opcodes.INVOKESPECIAL, superclassType.getInternalName(), setter.getName(), setterDescriptor); // END // GENERATE <prop>Set = true methodVisitor.visitVarInsn(Opcodes.ALOAD, 0); methodVisitor.visitLdcInsn(true); methodVisitor.visitFieldInsn( Opcodes.PUTFIELD, generatedType.getInternalName(), String.format("%sSet", property.getName()), Type.BOOLEAN_TYPE.getDescriptor()); // END methodVisitor.visitInsn(returnType.getOpcode(Opcodes.IRETURN)); methodVisitor.visitMaxs(0, 0); methodVisitor.visitEnd(); }
private void setCanCallSettersField( MethodVisitor methodVisitor, Type generatedType, boolean canCallSetters) { putThisOnStack(methodVisitor); methodVisitor.visitLdcInsn(canCallSetters); methodVisitor.visitFieldInsn( PUTFIELD, generatedType.getInternalName(), CAN_CALL_SETTERS_FIELD_NAME, Type.BOOLEAN_TYPE.getDescriptor()); }
private void addType(Type t) { switch (t.getSort()) { case Type.ARRAY: addType(t.getElementType()); break; case Type.OBJECT: addName(t.getInternalName()); break; } }
/** * Create the event class. * * @param type The type * @param name The canonical of the generated class * @param parentType The parent type * @return The class' contents, to be loaded via a {@link ClassLoader} */ public byte[] createClass( final Class<?> type, final String name, final Class<?> parentType, List<? extends EventFactoryPlugin> plugins) { checkNotNull(type, "type"); checkNotNull(name, "name"); checkNotNull(parentType, "parentType"); final ImmutableSet<? extends Property<Class<?>, Method>> properties = this.propertySearch.findProperties(new ReflectionClassWrapper(type)); final String internalName = getInternalName(name); final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); cw.visit( V1_6, ACC_PUBLIC + ACC_SUPER, internalName, null, Type.getInternalName(parentType), new String[] {Type.getInternalName(type)}); MethodVisitor toStringMv = this.initializeToString(cw, type); this.generateWithPlugins(cw, type, parentType, internalName, properties, toStringMv, plugins); // Create the fields // this.contributeFields(cw, parentType, properties, plugins); // Create the constructor this.generateConstructor(cw, internalName, parentType, properties); // The return value of toString takes the form of // "ClassName{param1=value1, param2=value2, ...}" // Create the accessors and mutators, and fill out the toString method this.finalizeToString(toStringMv); cw.visitEnd(); return cw.toByteArray(); }
public void addPeacefulRegenHook(ClassNode classNode, MethodNode method) { AbstractInsnNode relevantConditional = ASMHelper.find(method.instructions, new LdcInsnNode("naturalRegeneration")); JumpInsnNode ifNode = (JumpInsnNode) ASMHelper.find(relevantConditional, new JumpInsnNode(IFEQ, new LabelNode())); LabelNode ifBlockEndLabel = ifNode.label; AbstractInsnNode targetNode = ASMHelper.find(ifNode, new InsnNode(FCONST_1)).getPrevious(); int peacefulRegenEventIndex = firePeacefulRegenEventAndStoreEventBefore(method, targetNode, ifBlockEndLabel); InsnList healAmountNeedle = new InsnList(); healAmountNeedle.add(new InsnNode(FCONST_1)); InsnList healAmountReplacement = new InsnList(); healAmountReplacement.add(new VarInsnNode(ALOAD, peacefulRegenEventIndex)); healAmountReplacement.add( new FieldInsnNode( GETFIELD, Type.getInternalName(HealthRegenEvent.PeacefulRegen.class), "deltaHealth", "F")); ASMHelper.findAndReplace( method.instructions, healAmountNeedle, healAmountReplacement, targetNode); InsnList ifNotCanceledBlock = new InsnList(); LabelNode ifNotCanceled = new LabelNode(); ifNotCanceledBlock.add(new VarInsnNode(ALOAD, peacefulRegenEventIndex)); ifNotCanceledBlock.add( new MethodInsnNode( INVOKEVIRTUAL, Type.getInternalName(HealthRegenEvent.PeacefulRegen.class), "isCanceled", "()Z", false)); ifNotCanceledBlock.add(new JumpInsnNode(IFNE, ifNotCanceled)); method.instructions.insertBefore(targetNode, ifNotCanceledBlock); method.instructions.insertBefore(ifBlockEndLabel, ifNotCanceled); }