Example usage for org.objectweb.asm MethodVisitor MethodVisitor

List of usage examples for org.objectweb.asm MethodVisitor MethodVisitor

Introduction

In this page you can find the example usage for org.objectweb.asm MethodVisitor MethodVisitor.

Prototype

public MethodVisitor(final int api, final MethodVisitor methodVisitor) 

Source Link

Document

Constructs a new MethodVisitor .

Usage

From source file:com.foxelbox.spigotpatcher.patchers.OnPlayerJoinDisconnectPatcher.java

License:Open Source License

@Override
public MethodVisitor getVisitor(int api, MethodVisitor parent) {
    return new MethodVisitor(api, parent) {
        protected void checkMethodInsn(int opcode, String clazz, String name, String desc) {
            if (opcode == Opcodes.INVOKEVIRTUAL && clazz.endsWith("/CraftPlayer") && name.equals("canSee")) {
                visitInsn(Opcodes.POP);/* w ww .  java 2s. c  om*/
                visitInsn(Opcodes.ICONST_1);
                System.out.println("OnJoinPatcher: PATCHED (3 times = OK)");
            }
        }

        @Override
        public void visitMethodInsn(int opcode, String clazz, String name, String desc, boolean isInterface) {
            super.visitMethodInsn(opcode, clazz, name, desc, isInterface);
            checkMethodInsn(opcode, clazz, name, desc);
        }

        @Override
        public void visitMethodInsn(int opcode, String clazz, String name, String desc) {
            super.visitMethodInsn(opcode, clazz, name, desc);
            checkMethodInsn(opcode, clazz, name, desc);
        }
    };
}

From source file:com.gargoylesoftware.js.nashorn.internal.tools.nasgen.ScriptClassInfoCollector.java

License:Open Source License

@Override
public MethodVisitor visitMethod(final int methodAccess, final String methodName, final String methodDesc,
        final String signature, final String[] exceptions) {

    final MethodVisitor delegateMV = super.visitMethod(methodAccess, methodName, methodDesc, signature,
            exceptions);//  w  w  w .  ja va2  s  .co m

    return new MethodVisitor(Main.ASM_VERSION, delegateMV) {

        @Override
        public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
            final AnnotationVisitor delegateAV = super.visitAnnotation(descriptor, visible);
            final Kind annoKind = ScriptClassInfo.annotations.get(descriptor);

            if (annoKind != null) {
                if ((methodAccess & Opcodes.ACC_STATIC) == 0) {
                    error(methodName, methodDesc, "nasgen method annotations cannot be on instance methods");
                }

                final MemberInfo memInfo = new MemberInfo();

                // annoKind == GETTER or SPECIALIZED_FUNCTION
                memInfo.setKind(annoKind);
                memInfo.setJavaName(methodName);
                memInfo.setJavaDesc(methodDesc);
                memInfo.setJavaAccess(methodAccess);

                addScriptMember(memInfo);

                return new AnnotationVisitor(Main.ASM_VERSION, delegateAV) {
                    // These could be "null" if values are not supplied,
                    // in which case we have to use the default values.
                    private String name;
                    private Integer attributes;
                    private Integer arity;
                    private Where where;
                    private boolean isSpecializedConstructor;
                    private boolean isOptimistic;
                    private Type linkLogicClass = MethodGenerator.EMPTY_LINK_LOGIC_TYPE;

                    @Override
                    public void visit(final String annotationName, final Object annotationValue) {
                        switch (annotationName) {
                        case "name":
                            this.name = (String) annotationValue;
                            if (name.isEmpty()) {
                                name = null;
                            }
                            break;
                        case "attributes":
                            this.attributes = (Integer) annotationValue;
                            break;
                        case "arity":
                            this.arity = (Integer) annotationValue;
                            break;
                        case "isConstructor":
                            assert annoKind == Kind.SPECIALIZED_FUNCTION;
                            this.isSpecializedConstructor = (Boolean) annotationValue;
                            break;
                        case "isOptimistic":
                            assert annoKind == Kind.SPECIALIZED_FUNCTION;
                            this.isOptimistic = (Boolean) annotationValue;
                            break;
                        case "linkLogic":
                            this.linkLogicClass = (Type) annotationValue;
                            break;
                        default:
                            break;
                        }

                        super.visit(annotationName, annotationValue);
                    }

                    @Override
                    public void visitEnum(final String enumName, final String desc, final String enumValue) {
                        switch (enumName) {
                        case "where":
                            if (WHERE_ENUM_DESC.equals(desc)) {
                                this.where = Where.valueOf(enumValue);
                            }
                            break;
                        default:
                            break;
                        }
                        super.visitEnum(enumName, desc, enumValue);
                    }

                    @SuppressWarnings("fallthrough")
                    @Override
                    public void visitEnd() {
                        super.visitEnd();

                        if (memInfo.getKind() == Kind.CONSTRUCTOR) {
                            memInfo.setName(name == null ? scriptClassName : name);
                        } else {
                            memInfo.setName(name == null ? methodName : name);
                        }
                        memInfo.setAttributes(attributes == null ? MemberInfo.DEFAULT_ATTRIBUTES : attributes);

                        memInfo.setArity((arity == null) ? MemberInfo.DEFAULT_ARITY : arity);
                        if (where == null) {
                            // by default @Getter/@Setter belongs to INSTANCE
                            // @Function belong to PROTOTYPE.
                            switch (memInfo.getKind()) {
                            case GETTER:
                            case SETTER:
                                where = Where.INSTANCE;
                                break;
                            case CONSTRUCTOR:
                                where = Where.CONSTRUCTOR;
                                break;
                            case FUNCTION:
                                where = Where.PROTOTYPE;
                                break;
                            case SPECIALIZED_FUNCTION:
                                where = isSpecializedConstructor ? Where.CONSTRUCTOR : Where.PROTOTYPE;
                                //fallthru
                            default:
                                break;
                            }
                        }
                        memInfo.setWhere(where);
                        memInfo.setLinkLogicClass(linkLogicClass);
                        memInfo.setIsSpecializedConstructor(isSpecializedConstructor);
                        memInfo.setIsOptimistic(isOptimistic);
                    }
                };
            }

            return delegateAV;
        }
    };
}

From source file:com.gargoylesoftware.js.nashorn.internal.tools.nasgen.ScriptClassInstrumentor.java

License:Open Source License

@Override
public MethodVisitor visitMethod(final int methodAccess, final String methodName, final String methodDesc,
        final String signature, final String[] exceptions) {

    final boolean isConstructor = INIT.equals(methodName);
    final boolean isStaticInit = CLINIT.equals(methodName);

    if (isStaticInit) {
        staticInitFound = true;//from w  w  w .  j a  v  a 2s  .c  om
    }

    final MethodGenerator delegateMV = new MethodGenerator(
            super.visitMethod(methodAccess, methodName, methodDesc, signature, exceptions), methodAccess,
            methodName, methodDesc);

    return new MethodVisitor(Main.ASM_VERSION, delegateMV) {
        @Override
        public void visitInsn(final int opcode) {
            // call $clinit$ just before return from <clinit>
            if (isStaticInit && opcode == RETURN) {
                super.visitMethodInsn(INVOKESTATIC, scriptClassInfo.getJavaName(), $CLINIT$, DEFAULT_INIT_DESC,
                        false);
            }
            super.visitInsn(opcode);
        }

        @Override
        public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc,
                final boolean itf) {
            if (isConstructor && opcode == INVOKESPECIAL && INIT.equals(name)
                    && SCRIPTOBJECT_TYPE.equals(owner)) {
                super.visitMethodInsn(opcode, owner, name, desc, false);

                if (memberCount > 0) {
                    // initialize @Property fields if needed
                    for (final MemberInfo memInfo : scriptClassInfo.getMembers()) {
                        if (memInfo.isInstanceProperty() && !memInfo.getInitClass().isEmpty()) {
                            final String clazz = memInfo.getInitClass();
                            super.visitVarInsn(ALOAD, 0);
                            super.visitTypeInsn(NEW, clazz);
                            super.visitInsn(DUP);
                            super.visitMethodInsn(INVOKESPECIAL, clazz, INIT, DEFAULT_INIT_DESC, false);
                            super.visitFieldInsn(PUTFIELD, scriptClassInfo.getJavaName(), memInfo.getJavaName(),
                                    memInfo.getJavaDesc());
                        }

                        if (memInfo.isInstanceFunction()) {
                            super.visitVarInsn(ALOAD, 0);
                            ClassGenerator.newFunction(delegateMV, scriptClassInfo.getJavaName(), memInfo,
                                    scriptClassInfo.findSpecializations(memInfo.getJavaName()));
                            super.visitFieldInsn(PUTFIELD, scriptClassInfo.getJavaName(), memInfo.getJavaName(),
                                    OBJECT_DESC);
                        }
                    }
                }
            } else {
                super.visitMethodInsn(opcode, owner, name, desc, itf);
            }
        }

        @Override
        public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) {
            if (ScriptClassInfo.annotations.containsKey(desc)) {
                // ignore script method annotations
                return null;
            }
            return super.visitAnnotation(desc, visible);
        }
    };
}

From source file:com.gargoylesoftware.js.nashorn.internal.tools.nasgen.ScriptClassJavaInstrumentor.java

License:Open Source License

@Override
public MethodVisitor visitMethod(final int methodAccess, final String methodName, final String methodDesc,
        final String signature, final String[] exceptions) {

    final boolean isConstructor = INIT.equals(methodName);
    final boolean isStaticInit = CLINIT.equals(methodName);

    if (isStaticInit) {
        staticInitFound = true;//from w ww .  java  2s . c  o  m
    }

    final MethodGenerator delegateMV = new MethodGenerator(
            super.visitMethod(methodAccess, methodName, methodDesc, signature, exceptions), methodAccess,
            methodName, methodDesc);

    return new MethodVisitor(Main.ASM_VERSION, delegateMV) {
        @Override
        public void visitInsn(final int opcode) {
            // call $clinit$ just before return from <clinit>
            if (isStaticInit && opcode == RETURN) {
                super.visitMethodInsn(INVOKESTATIC, scriptClassInfo.getJavaName(), $CLINIT$, DEFAULT_INIT_DESC,
                        false);
            }
            super.visitInsn(opcode);
        }

        @Override
        public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc,
                final boolean itf) {
            if (isConstructor && opcode == INVOKESPECIAL && INIT.equals(name)
                    && SCRIPTOBJECT_TYPE.equals(owner)) {
                super.visitMethodInsn(opcode, owner, name, desc, false);

                if (memberCount > 0) {
                    // initialize @Property fields if needed
                    for (final MemberInfo memInfo : scriptClassInfo.getMembers()) {
                        if (memInfo.isInstanceProperty() && !memInfo.getInitClass().isEmpty()) {
                            final String clazz = memInfo.getInitClass();
                            super.visitVarInsn(ALOAD, 0);
                            super.visitTypeInsn(NEW, clazz);
                            super.visitInsn(DUP);
                            super.visitMethodInsn(INVOKESPECIAL, clazz, INIT, DEFAULT_INIT_DESC, false);
                            super.visitFieldInsn(PUTFIELD, scriptClassInfo.getJavaName(), memInfo.getJavaName(),
                                    memInfo.getJavaDesc());
                        }

                        if (memInfo.isInstanceFunction()) {
                            super.visitVarInsn(ALOAD, 0);
                            ClassJavaGenerator.newFunction(delegateMV, scriptClassInfo.getJavaName(), memInfo,
                                    scriptClassInfo.findSpecializations(memInfo.getJavaName()));
                            super.visitFieldInsn(PUTFIELD, scriptClassInfo.getJavaName(), memInfo.getJavaName(),
                                    OBJECT_DESC);
                        }
                    }
                }
            } else {
                super.visitMethodInsn(opcode, owner, name, desc, itf);
            }
        }

        @Override
        public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) {
            if (ScriptClassInfo.annotations.containsKey(desc)) {
                // ignore script method annotations
                return null;
            }
            return super.visitAnnotation(desc, visible);
        }
    };
}

From source file:com.github.antag99.retinazer.weaver.AccessProcessor.java

License:Open Source License

@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
    MethodVisitor visitor = super.visitMethod(access, name, desc, signature, exceptions);

    if ((access & ACC_ABSTRACT) != 0)
        return visitor;

    return new MethodVisitor(ASM5, visitor) {
        @Override//from ww  w. j a  v  a  2 s .  c  o m
        public void visitFieldInsn(int opcode, String owner, String name, String desc) {
            if (opcode == GETFIELD || opcode == PUTFIELD) {
                Type fieldOwner = Type.getObjectType(owner);
                if (fieldOwner.getSort() == Type.OBJECT) {
                    WeaverMetadata metadata = weaver.getMetadata(fieldOwner.getInternalName());
                    if (metadata.componentMetadata != null) { // Is it a component?
                        ComponentProperty property = metadata.componentMetadata.propertiesByName.get(name);
                        if (property != null) { // Ensure the field is not generated by the weaver
                            if (opcode == GETFIELD)
                                super.visitMethodInsn(INVOKEVIRTUAL, owner, property.getGetterName(),
                                        property.getGetterDesc(), false);
                            else
                                super.visitMethodInsn(INVOKEVIRTUAL, owner, property.getSetterName(),
                                        property.getSetterDesc(), false);
                            return; // Don't attempt to access the fields of packed components
                        }
                    }
                }
            }
            super.visitFieldInsn(opcode, owner, name, desc);
        }
    };
}

From source file:com.github.antag99.retinazer.weaver.ComponentProcessor.java

License:Open Source License

@Override
public void visit(final int version, final int access, final String name, final String signature,
        final String superName, String[] interfaces) {
    if (!"java/lang/Object".equals(superName))
        throw new WeaverException("Failed to weave " + metadata.internalName + "; cannot extend other classes");

    if ((access & ACC_FINAL) == 0)
        throw new WeaverException("Failed to weave " + metadata.internalName + "; must be final");

    if (Arrays.asList(interfaces).contains(WeaverConstants.PACKED_COMPONENT_NAME))
        throw new WeaverException("Failed to weave " + metadata.internalName + "; already packed");

    if (signature != null)
        throw new WeaverException(
                "Failed to weave " + metadata.internalName + "; cannot use generic type arguments");

    interfaces = Arrays.copyOf(interfaces, interfaces.length);
    for (int i = 0; i < interfaces.length; i++)
        if (interfaces[i].equals(WeaverConstants.COMPONENT_NAME))
            interfaces[i] = WeaverConstants.PACKED_COMPONENT_NAME;

    super.visit(version, access, name, signature, superName, interfaces);

    super.visitField(ACC_PUBLIC, WeaverConstants.INDEX_FIELD_NAME, WeaverConstants.INDEX_FIELD_DESC, null,
            null);/* w ww  .  ja v  a2s  . c  om*/

    new MethodVisitor(ASM5, super.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null)) {
        {
            visitCode();
            visitVarInsn(ALOAD, 0);
            visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
            visitInsn(RETURN);
            visitMaxs(-1, -1);
            visitEnd();
        }
    };
}

From source file:com.github.antag99.retinazer.weaver.ComponentProcessor.java

License:Open Source License

@Override
public FieldVisitor visitField(final int access, final String name, final String desc, final String signature,
        final Object value) {

    if ((access & ACC_STATIC) > 0)
        return super.visitField(access, name, desc, signature, value);

    final ComponentProperty property = metadata.propertiesByName.get(name);

    new MethodVisitor(ASM5,
            super.visitMethod(ACC_PUBLIC, property.getGetterName(), property.getGetterDesc(), null, null)) {
        {//from w w  w .  j a v a  2s .  c o  m
            visitCode();
            visitVarInsn(ALOAD, 0);
            visitFieldInsn(GETFIELD, metadata.internalName, property.getBagName(), property.getBagDesc());
            visitVarInsn(ALOAD, 0);
            visitFieldInsn(GETFIELD, metadata.internalName, WeaverConstants.INDEX_FIELD_NAME,
                    WeaverConstants.INDEX_FIELD_DESC);
            Type erasedType = property.type.getSort() == Type.OBJECT ? Type.getObjectType("java/lang/Object")
                    : property.type;
            visitMethodInsn(INVOKEVIRTUAL, WeaverConstants.getBagName(property.type), "get",
                    "(I)" + erasedType.getDescriptor(), false);
            visitInsn(property.type.getOpcode(IRETURN));
            visitMaxs(-1, -1);
            visitEnd();
        }
    };

    new MethodVisitor(ASM5,
            super.visitMethod(ACC_PUBLIC, property.getSetterName(), property.getSetterDesc(), null, null)) {
        {
            visitCode();
            visitVarInsn(ALOAD, 0);
            visitFieldInsn(GETFIELD, metadata.internalName, property.getBagName(), property.getBagDesc());
            visitVarInsn(ALOAD, 0);
            visitFieldInsn(GETFIELD, metadata.internalName, WeaverConstants.INDEX_FIELD_NAME,
                    WeaverConstants.INDEX_FIELD_DESC);
            visitVarInsn(property.type.getOpcode(ILOAD), 1);
            Type erasedType = property.type.getSort() == Type.OBJECT ? Type.getObjectType("java/lang/Object")
                    : property.type;
            visitMethodInsn(INVOKEVIRTUAL, WeaverConstants.getBagName(property.type), "set",
                    "(I" + erasedType.getDescriptor() + ")V", false);
            visitInsn(Opcodes.RETURN);
            visitMaxs(-1, -1);
            visitEnd();
        }
    };

    FieldVisitor storeField = super.visitField(ACC_PUBLIC, property.getBagName(), property.getBagDesc(), null,
            null);
    if (storeField != null)
        storeField.visitEnd();

    return null; // Remove backing field
}

From source file:com.github.antag99.retinazer.weaver.ComponentProcessor.java

License:Open Source License

@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
    if (!name.equals("<init>"))
        return super.visitMethod(access, name, desc, signature, exceptions);

    // Turn the no-arg/default constructor into a reset() method.
    if (!desc.equals("()V"))
        throw new WeaverException(
                "Failed to weave " + metadata.internalName + "; cannot have multi-arg constructor");

    if (exceptions != null && exceptions.length > 0)
        throw new WeaverException(
                "Failed to weave " + metadata.internalName + "; constructor cannot throw exceptions");

    return new MethodVisitor(ASM5, super.visitMethod(access, WeaverConstants.RESET_METHOD_NAME,
            WeaverConstants.RESET_METHOD_DESC, null, null)) {
        @Override//from   w w w .  j  a  v a 2  s  .c o  m
        public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
            // Replace the super constructor invocation with a call to the clear() method
            if (opcode == INVOKESPECIAL && owner.equals("java/lang/Object") && name.equals("<init>")
                    && desc.equals("()V") && !itf) {
                super.visitMethodInsn(INVOKEVIRTUAL, metadata.internalName, WeaverConstants.CLEAR_METHOD_NAME,
                        WeaverConstants.CLEAR_METHOD_DESC, false);
            } else {
                super.visitMethodInsn(opcode, owner, name, desc, itf);
            }
        }
    };
}

From source file:com.github.antag99.retinazer.weaver.ComponentProcessor.java

License:Open Source License

@Override
public void visitEnd() {
    // Generate clear() method
    new MethodVisitor(ASM5, super.visitMethod(ACC_PUBLIC, WeaverConstants.CLEAR_METHOD_NAME,
            WeaverConstants.CLEAR_METHOD_DESC, null, null)) {
        {/*from  w ww. ja  v a2s.co m*/
            visitCode();
            for (ComponentProperty property : metadata.properties) {
                visitVarInsn(ALOAD, 0);

                switch (property.type.getSort()) {
                case Type.BOOLEAN:
                case Type.BYTE:
                case Type.CHAR:
                case Type.SHORT:
                case Type.INT:
                    visitLdcInsn((int) 0);
                    break;
                case Type.FLOAT:
                    visitLdcInsn((float) 0);
                    break;
                case Type.DOUBLE:
                    visitLdcInsn((double) 0);
                    break;
                case Type.LONG:
                    visitLdcInsn((long) 0);
                    break;
                default:
                    visitInsn(ACONST_NULL);
                    break;
                }
                visitFieldInsn(PUTFIELD, metadata.internalName, property.name, property.type.getDescriptor());
            }
            visitInsn(RETURN);
            visitMaxs(-1, -1);
            visitEnd();
        }
    };

    super.visitEnd();
}

From source file:com.github.antag99.retinazer.weaver.MapperGenerator.java

License:Open Source License

@Override
public void accept(ClassVisitor visitor) {
    visitor.visit(V1_7, ACC_PUBLIC + ACC_FINAL + ACC_SYNTHETIC, metadata.getMapperName(),
            "Lcom/github/antag99/retinazer/PackedMapper<L" + metadata.getMapperName() + ";>;",
            "com/github/antag99/retinazer/PackedMapper", null);
    for (ComponentProperty property : metadata.properties) {
        FieldVisitor propertyField = visitor.visitField(ACC_PRIVATE + ACC_FINAL, property.getMetadataName(),
                property.getMetadataDesc(), null, null);
        if (propertyField != null)
            propertyField.visitEnd();/*from ww  w  .j  a  v a  2  s  .c o m*/
    }

    FieldVisitor flyweightField = visitor.visitField(ACC_PRIVATE + ACC_FINAL, "flyweight",
            "L" + metadata.internalName + ";", null, null);
    if (flyweightField != null)
        flyweightField.visitEnd();

    // @off: Formatter mangles the elegant method syntax

    new MethodVisitor(ASM5, visitor.visitMethod(ACC_PUBLIC, "<init>",
            "(Lcom/github/antag99/retinazer/Engine;I)V", null, null)) {
        {
            visitCode();
            visitVarInsn(ALOAD, 0);
            visitVarInsn(ALOAD, 1);
            visitLdcInsn(Type.getObjectType(metadata.internalName));
            visitVarInsn(ILOAD, 2);
            visitMethodInsn(Opcodes.INVOKESPECIAL, "com/github/antag99/retinazer/PackedMapper", "<init>",
                    "(Lcom/github/antag99/retinazer/Engine;Ljava/lang/Class;I)V", false);

            for (ComponentProperty property : metadata.properties) {
                visitVarInsn(ALOAD, 0);
                visitTypeInsn(NEW, WeaverConstants.getMetadataName(property.type));
                visitInsn(Opcodes.DUP);
                visitLdcInsn(property.name);
                if (property.type.getSort() == Type.OBJECT) {
                    visitLdcInsn(property.type);
                    visitMethodInsn(INVOKESPECIAL, WeaverConstants.getMetadataName(property.type), "<init>",
                            "(Ljava/lang/String;Ljava/lang/Class;)V", false);
                } else {
                    visitMethodInsn(INVOKESPECIAL, WeaverConstants.getMetadataName(property.type), "<init>",
                            "(Ljava/lang/String;)V", false);
                }
                visitFieldInsn(PUTFIELD, metadata.getMapperName(), property.getMetadataName(),
                        property.getMetadataDesc());
            }

            visitVarInsn(ALOAD, 0);
            visitInsn(DUP);
            visitMethodInsn(INVOKEVIRTUAL, metadata.getMapperName(), "createFlyweight",
                    "()L" + metadata.internalName + ";", false);
            visitFieldInsn(PUTFIELD, metadata.getMapperName(), "flyweight", "L" + metadata.internalName + ";");
            visitInsn(RETURN);
            visitMaxs(0, 0);
            visitEnd();
        }
    };

    new MethodVisitor(ASM5, visitor.visitMethod(ACC_PUBLIC, "createFlyweight",
            "()L" + metadata.internalName + ";", null, null)) {
        {
            visitCode();
            visitTypeInsn(NEW, metadata.internalName);
            visitInsn(DUP);
            visitMethodInsn(INVOKESPECIAL, metadata.internalName, "<init>", "()V", false);

            for (ComponentProperty property : metadata.properties) {
                visitInsn(DUP);
                visitVarInsn(ALOAD, 0);
                visitFieldInsn(GETFIELD, metadata.getMapperName(), property.getMetadataName(),
                        property.getMetadataDesc());
                visitMethodInsn(INVOKEVIRTUAL, WeaverConstants.getMetadataName(property.type), "getBag",
                        "()" + property.getBagDesc(), false);
                visitFieldInsn(PUTFIELD, metadata.internalName, property.getBagName(), property.getBagDesc());
            }

            visitInsn(ARETURN);

            visitMaxs(0, 0);
            visitEnd();
        }
    };

    new MethodVisitor(ASM5,
            visitor.visitMethod(ACC_PUBLIC, "create", "(I)L" + metadata.internalName + ";", null, null)) {
        {
            visitCode();
            visitVarInsn(ALOAD, 0);
            visitVarInsn(ILOAD, 1);
            visitMethodInsn(INVOKEVIRTUAL, "com/github/antag99/retinazer/Mapper", "checkCreate", "(I)V", false);
            visitVarInsn(ALOAD, 0);
            visitVarInsn(ILOAD, 1);
            visitMethodInsn(INVOKEVIRTUAL, metadata.getMapperName(), "get",
                    "(I)L" + metadata.internalName + ";", false);
            visitInsn(DUP);
            visitMethodInsn(INVOKEVIRTUAL, metadata.internalName, WeaverConstants.RESET_METHOD_NAME,
                    WeaverConstants.RESET_METHOD_DESC, false);
            visitInsn(ARETURN);
            visitMaxs(0, 0);
            visitEnd();
        }
    };

    new MethodVisitor(ASM5, visitor.visitMethod(ACC_PUBLIC + ACC_SYNTHETIC + ACC_BRIDGE, "create",
            "(I)Lcom/github/antag99/retinazer/Component;", null, null)) {
        {
            visitCode();
            visitVarInsn(ALOAD, 0);
            visitVarInsn(ILOAD, 1);
            visitMethodInsn(INVOKEVIRTUAL, metadata.getMapperName(), "create",
                    "(I)L" + metadata.internalName + ";", false);
            visitInsn(ARETURN);
            visitMaxs(0, 0);
            visitEnd();
        }
    };

    new MethodVisitor(ASM5,
            visitor.visitMethod(ACC_PUBLIC, "get", "(I)L" + metadata.internalName + ";", null, null)) {
        {
            visitCode();
            visitVarInsn(ALOAD, 0);
            visitFieldInsn(GETFIELD, metadata.getMapperName(), "flyweight", "L" + metadata.internalName + ";");
            visitInsn(DUP);
            visitVarInsn(ILOAD, 1);
            visitFieldInsn(PUTFIELD, metadata.internalName, WeaverConstants.INDEX_FIELD_NAME,
                    WeaverConstants.INDEX_FIELD_DESC);
            visitInsn(ARETURN);
            visitMaxs(0, 0);
            visitEnd();
        }
    };

    new MethodVisitor(ASM5, visitor.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "get",
            "(I)Lcom/github/antag99/retinazer/Component;", null, null)) {
        {
            visitCode();
            visitVarInsn(ALOAD, 0);
            visitVarInsn(ILOAD, 1);
            visitMethodInsn(INVOKEVIRTUAL, metadata.getMapperName(), "get",
                    "(I)L" + metadata.internalName + ";", false);
            visitInsn(ARETURN);
            visitMaxs(0, 0);
            visitEnd();
        }
    };

    new MethodVisitor(ASM5, visitor.visitMethod(ACC_PUBLIC, "getProperties",
            "()[Lcom/github/antag99/retinazer/util/Property;", null, null)) {
        {
            visitCode();
            visitLdcInsn(metadata.properties.size());
            visitTypeInsn(ANEWARRAY, "com/github/antag99/retinazer/util/Property");

            List<ComponentProperty> properties = metadata.properties;
            for (int i = 0, n = properties.size(); i < n; i++) {
                ComponentProperty property = properties.get(i);
                visitInsn(DUP);
                visitLdcInsn(i);
                visitVarInsn(ALOAD, 0);
                visitFieldInsn(GETFIELD, metadata.getMapperName(), property.getMetadataName(),
                        property.getMetadataDesc());
                visitInsn(AASTORE);
            }

            visitInsn(ARETURN);
            visitMaxs(0, 0);
            visitEnd();
        }
    };

    new MethodVisitor(ASM5, visitor.visitMethod(ACC_PUBLIC, "applyComponentChanges", "()V", null, null)) {
        {
            visitCode();
            visitVarInsn(ALOAD, 0);
            visitFieldInsn(GETFIELD, "com/github/antag99/retinazer/Mapper", "componentsMask",
                    "Lcom/github/antag99/retinazer/util/Mask;");
            visitVarInsn(ASTORE, 1);
            visitVarInsn(ALOAD, 0);
            visitFieldInsn(GETFIELD, "com/github/antag99/retinazer/Mapper", "removeMask",
                    "Lcom/github/antag99/retinazer/util/Mask;");
            visitVarInsn(ASTORE, 2);
            for (ComponentProperty property : metadata.properties) {
                visitVarInsn(ALOAD, 0);
                visitFieldInsn(GETFIELD, metadata.getMapperName(), property.getMetadataName(),
                        property.getMetadataDesc());
                visitMethodInsn(INVOKEVIRTUAL, WeaverConstants.getMetadataName(property.type), "getBag",
                        "()" + property.getBagDesc(), false);
                visitVarInsn(ALOAD, 2);
                visitMethodInsn(INVOKEVIRTUAL, WeaverConstants.getBagName(property.type), "clear",
                        "(Lcom/github/antag99/retinazer/util/Mask;)V", false);
            }
            visitVarInsn(ALOAD, 1);
            visitVarInsn(ALOAD, 2);
            visitMethodInsn(INVOKEVIRTUAL, "com/github/antag99/retinazer/util/Mask", "andNot",
                    "(Lcom/github/antag99/retinazer/util/Mask;)V", false);
            visitInsn(RETURN);
            visitMaxs(0, 0);
            visitEnd();
        }
    };

    visitor.visitEnd();
}