Example usage for org.objectweb.asm Opcodes CHECKCAST

List of usage examples for org.objectweb.asm Opcodes CHECKCAST

Introduction

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

Prototype

int CHECKCAST

To view the source code for org.objectweb.asm Opcodes CHECKCAST.

Click Source Link

Usage

From source file:io.syncframework.optimizer.OControllerClassVisitor.java

License:Apache License

/**
 * Generates code://  w w w.j  a va 2s. c o  m
 * 
 * public Class<?>[] _asActionInterceptors(String name) {
 *    return _asInterceptors.get(name);
 * }
 */
public void createActionInterceptorsMethod() {
    MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC, "_asActionInterceptors",
            "(Ljava/lang/String;)[Ljava/lang/Class;", null, null);

    Label l0 = new Label();
    Label l1 = new Label();
    mv.visitLabel(l0);
    mv.visitFieldInsn(Opcodes.GETSTATIC, reflector.getClazzInternalName(), "_asInterceptors",
            "Ljava/util/Map;");
    mv.visitVarInsn(Opcodes.ALOAD, 1);
    mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/Map", "get",
            "(Ljava/lang/Object;)Ljava/lang/Object;", true);
    mv.visitTypeInsn(Opcodes.CHECKCAST, "[Ljava/lang/Class;");
    mv.visitInsn(Opcodes.ARETURN);

    mv.visitLabel(l1);
    mv.visitLocalVariable("this", reflector.getClazzDescriptor(), null, l0, l1, 0);
    mv.visitLocalVariable("name", "Ljava/lang/String;", null, l0, l1, 1);
    mv.visitMaxs(2, 2);

    mv.visitEnd();
}

From source file:io.syncframework.optimizer.OControllerClassVisitor.java

License:Apache License

/**
 * Creates the code as://from   w  w w.j  a v a 2s. c om
 * 
 * public void _asParameter(String name, Object value) {
 *    if(name.equals("name") {
 *       setName((String)value);
 *       return;
 *    }
 *   if(name.equals("date") {
 *      setDate((Date)value);
 *      return;
 *   }
 *   ...
 *    return;
 * } 
 */
private void createParametersSetterMethod() {
    MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC, "_asParameter",
            "(Ljava/lang/String;Ljava/lang/Object;)V", null, null);

    Label start = new Label();
    Label next = new Label();
    Label variable = new Label();
    boolean first = true;

    for (String name : reflector.getParameters().keySet()) {
        Label l0 = null;
        Label l1 = new Label();
        Label l2 = new Label();

        if (first) {
            l0 = new Label();
            first = false;
        } else {
            l0 = next;
            next = new Label();
        }

        mv.visitLabel(l0);
        if (!first)
            mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
        mv.visitVarInsn(Opcodes.ALOAD, 1);
        mv.visitLdcInsn(name);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false);
        mv.visitJumpInsn(Opcodes.IFEQ, next);

        Class<?> parameterType = reflector.getParameters().get(name);

        String setterMethodName = reflector.getSetters().get(name).getName();
        String setterMethodDesc = "(" + Type.getDescriptor(parameterType) + ")V";

        mv.visitLabel(l1);
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitVarInsn(Opcodes.ALOAD, 2);
        mv.visitTypeInsn(Opcodes.CHECKCAST, Type.getInternalName(parameterType));
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, reflector.getClazzInternalName(), setterMethodName,
                setterMethodDesc, false);

        mv.visitLabel(l2);
        mv.visitInsn(Opcodes.RETURN);
    }

    mv.visitLabel(next);
    mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
    mv.visitInsn(Opcodes.RETURN);

    mv.visitLabel(variable);
    mv.visitLocalVariable("this", reflector.getClazzDescriptor(), null, start, next, 0);
    mv.visitLocalVariable("name", "Ljava/lang/String;", null, start, next, 1);
    mv.visitLocalVariable("value", "Ljava/lang/Object;", null, start, next, 2);
    mv.visitMaxs(2, 3);
    mv.visitEnd();
}

From source file:io.syncframework.optimizer.OControllerClassVisitor.java

License:Apache License

/**
 * public Class<?> _asParameterConverter(String name) {
 *    return _asConverters.get(name);/* www  .  j  ava  2 s  .com*/
 * }
 */
public void createParameterConverterMethod() {
    MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC, "_asParameterConverter",
            "(Ljava/lang/String;)Ljava/lang/Class;", null, null);
    Label l0 = new Label();
    mv.visitLabel(l0);
    mv.visitFieldInsn(Opcodes.GETSTATIC, reflector.getClazzInternalName(), "_asConverters", "Ljava/util/Map;");
    mv.visitVarInsn(Opcodes.ALOAD, 1);
    mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/Map", "get",
            "(Ljava/lang/Object;)Ljava/lang/Object;", true);
    mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Class");
    mv.visitInsn(Opcodes.ARETURN);

    Label l1 = new Label();
    mv.visitLocalVariable("this", reflector.getClazzDescriptor(), null, l0, l1, 0);
    mv.visitLocalVariable("name", "Ljava/lang/String;", null, l0, l1, 1);
    mv.visitMaxs(2, 2);
    mv.visitEnd();
}

From source file:io.syncframework.optimizer.OControllerStaticMethodVisitor.java

License:Apache License

public void visitInsn(int opcode) {
    if (opcode != Opcodes.RETURN) {
        mv.visitInsn(opcode);//from   www.j  a v a2  s .co  m
        return;
    }

    Label start = new Label();
    Label l1 = new Label();
    Label l2 = new Label();
    Label interceptorsLabel = new Label();

    mv.visitCode();
    mv.visitTryCatchBlock(start, l1, l2, "java/lang/Throwable");

    /*
     * _asActions = new HashMap<String,Boolean>();
     */
    {
        mv.visitLabel(start);
        mv.visitTypeInsn(Opcodes.NEW, "java/util/HashMap");
        mv.visitInsn(Opcodes.DUP);
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/util/HashMap", "<init>", "()V", false);
        mv.visitFieldInsn(Opcodes.PUTSTATIC, reflector.getClazzInternalName(), "_asActions", "Ljava/util/Map;");
    }
    /*
     * _asActions.put("main", true);
     * _asActions.put("action1", true);
     */
    for (String name : reflector.getActions().keySet()) {
        Label l = new Label();
        mv.visitLabel(l);
        mv.visitFieldInsn(Opcodes.GETSTATIC, reflector.getClazzInternalName(), "_asActions", "Ljava/util/Map;");
        mv.visitLdcInsn(name);
        mv.visitInsn(Opcodes.ICONST_1);
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;",
                false);
        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/Map", "put",
                "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", true);
        mv.visitInsn(Opcodes.POP);
    }

    /*
     * _asInterceptors = new HashMap<String,Class<?>[]>()
     */
    {
        Label l = new Label();
        mv.visitLabel(l);
        mv.visitTypeInsn(Opcodes.NEW, "java/util/HashMap");
        mv.visitInsn(Opcodes.DUP);
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/util/HashMap", "<init>", "()V", false);
        mv.visitFieldInsn(Opcodes.PUTSTATIC, reflector.getClazzInternalName(), "_asInterceptors",
                "Ljava/util/Map;");
    }

    /*
     * List<Class<?>> l = new ArrayList<Class<?>>();
     */
    mv.visitLabel(interceptorsLabel);
    mv.visitTypeInsn(Opcodes.NEW, "java/util/ArrayList");
    mv.visitInsn(Opcodes.DUP);
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/util/ArrayList", "<init>", "()V", false);
    mv.visitVarInsn(Opcodes.ASTORE, 0);

    for (String name : reflector.getActions().keySet()) {
        Class<?> interceptors[] = reflector.getInterceptors().get(name);
        if (interceptors == null || interceptors.length == 0)
            continue;

        /*
         * l.clear();
         */
        Label l01 = new Label();
        mv.visitLabel(l01);
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/List", "clear", "()V", true);

        for (Class<?> interceptor : interceptors) {
            /*
             * l.add(LoginInterceptor.class);
             */
            Label l02 = new Label();
            mv.visitLabel(l02);
            mv.visitVarInsn(Opcodes.ALOAD, 0);
            mv.visitLdcInsn(Type.getType(interceptor));
            mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/List", "add", "(Ljava/lang/Object;)Z", true);
        }

        /*
         * _asInterceptors.put("upload", l.toArray(new Class[0]));
         */
        Label l03 = new Label();
        mv.visitLabel(l03);
        mv.visitFieldInsn(Opcodes.GETSTATIC, reflector.getClazzInternalName(), "_asInterceptors",
                "Ljava/util/Map;");
        mv.visitLdcInsn(name);
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitInsn(Opcodes.ICONST_0);
        mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class");
        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/List", "toArray",
                "([Ljava/lang/Object;)[Ljava/lang/Object;", true);
        mv.visitTypeInsn(Opcodes.CHECKCAST, "[Ljava/lang/Class;");
        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/Map", "put",
                "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", true);
        mv.visitInsn(Opcodes.POP);
    }

    /* 
     * _asParameters = new HashMap<String,Class<?>>() 
     */
    {
        Label l = new Label();
        mv.visitLabel(l);
        mv.visitTypeInsn(Opcodes.NEW, "java/util/HashMap");
        mv.visitInsn(Opcodes.DUP);
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/util/HashMap", "<init>", "()V", false);
        mv.visitFieldInsn(Opcodes.PUTSTATIC, reflector.getClazzInternalName(), "_asParameters",
                "Ljava/util/Map;");
    }
    /*
     * _asParameters.put("name", Type.class);
     */
    for (String name : reflector.getParameters().keySet()) {
        Label l = new Label();
        mv.visitLabel(l);
        mv.visitFieldInsn(Opcodes.GETSTATIC, reflector.getClazzInternalName(), "_asParameters",
                "Ljava/util/Map;");
        mv.visitLdcInsn(name);
        mv.visitLdcInsn(Type.getType(reflector.getParameters().get(name)));
        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/Map", "put",
                "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", true);
        mv.visitInsn(Opcodes.POP);
    }

    /* 
     * _asConverters = new HashMap<String,Class<?>>() 
     */
    {
        Label l = new Label();
        mv.visitLabel(l);
        mv.visitTypeInsn(Opcodes.NEW, "java/util/HashMap");
        mv.visitInsn(Opcodes.DUP);
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/util/HashMap", "<init>", "()V", false);
        mv.visitFieldInsn(Opcodes.PUTSTATIC, reflector.getClazzInternalName(), "_asConverters",
                "Ljava/util/Map;");
    }
    /*
     * _asConverters.put("name", Type.class);
     */
    for (String name : reflector.getParameters().keySet()) {
        if (reflector.getConverters().get(name) != null) {
            Class<?> converter = reflector.getConverters().get(name);
            Label l = new Label();
            mv.visitLabel(l);
            mv.visitFieldInsn(Opcodes.GETSTATIC, reflector.getClazzInternalName(), "_asConverters",
                    "Ljava/util/Map;");
            mv.visitLdcInsn(name);
            mv.visitLdcInsn(Type.getType(converter));
            mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/Map", "put",
                    "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", true);
            mv.visitInsn(Opcodes.POP);
        }
    }

    /*
     * }
     * catch(Throwable t) {
     *    throw t;
     * }
     */
    Label throwableStart = new Label();
    Label throwableEnd = new Label();

    mv.visitLabel(l1);
    mv.visitJumpInsn(Opcodes.GOTO, throwableEnd);
    mv.visitLabel(l2);
    mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/Throwable" });
    mv.visitVarInsn(Opcodes.ASTORE, 0);
    mv.visitLabel(throwableStart);
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitInsn(Opcodes.ATHROW);

    mv.visitLabel(throwableEnd);
    mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
    mv.visitInsn(Opcodes.RETURN);
    mv.visitLocalVariable("l", "Ljava/util/List;", null, interceptorsLabel, l1, 0);
    mv.visitLocalVariable("t", "Ljava/lang/Throwable;", null, throwableStart, throwableEnd, 0);
}

From source file:javaone2015.con7442.indyprotector.MethodIndyProtector.java

License:Apache License

@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
    boolean isStatic = (opcode == Opcodes.INVOKESTATIC);
    String newSig = isStatic ? desc : desc.replace("(", "(Ljava/lang/Object;");
    Type origReturnType = Type.getReturnType(newSig);
    Type[] args = Type.getArgumentTypes(newSig);
    for (int i = 0; i < args.length; i++) {
        args[i] = genericType(args[i]);/*from   w  w w. j a  v  a  2 s.c o m*/
    }
    newSig = Type.getMethodDescriptor(origReturnType, args);
    switch (opcode) {
    case INVOKESTATIC: // invokestatic opcode
    case INVOKEVIRTUAL: // invokevirtual opcode
    case INVOKEINTERFACE: // invokeinterface opcode
        mv.visitInvokeDynamicInsn(String.valueOf(rnd.nextInt()), newSig, bootstrapMethodHandle, opcode,
                owner.replaceAll("/", "."), name, desc);
        if (origReturnType.getSort() == Type.ARRAY) {
            mv.visitTypeInsn(Opcodes.CHECKCAST, origReturnType.getInternalName());
        }
        break;
    default:
        mv.visitMethodInsn(opcode, owner, name, desc, itf);
    }
}

From source file:jpcsp.Allegrex.compiler.CompilerContext.java

License:Open Source License

/**
 * Generate the required Java code to load one parameter for
 * the syscall function from the CPU registers.
 *
 * The following code is generated based on the parameter type:
 * Processor: parameterValue = RuntimeContext.processor
 * int:       parameterValue = cpu.gpr[paramIndex++]
 * float:     parameterValue = cpu.fpr[paramFloatIndex++]
 * long:      parameterValue = (cpu.gpr[paramIndex++] & 0xFFFFFFFFL) + ((long) cpu.gpr[paramIndex++]) << 32)
 * boolean:   parameterValue = cpu.gpr[paramIndex++]
 * TPointer,/*  w  ww. j av a2 s  . co m*/
 * TPointer8,
 * TPointer16,
 * TPointer32,
 * TPointer64,
 * TErrorPointer32:
 *            if (checkMemoryAccess()) {
 *                if (canBeNullParam && address == 0) {
 *                    goto addressGood;
 *                }
 *                if (RuntimeContext.checkMemoryPointer(address)) {
 *                    goto addressGood;
 *                }
 *                cpu.gpr[_v0] = SceKernelErrors.ERROR_INVALID_POINTER;
 *                pop all the parameters already prepared on the stack;
 *                goto afterSyscall;
 *                addressGood:
 *            }
 *            <parameterType> pointer = new <parameterType>(address);
 *            if (parameterType == TErrorPointer32.class) {
 *                parameterReader.setHasErrorPointer(true);
 *                localVar[LOCAL_ERROR_POINTER] = pointer;
 *            }
 *            parameterValue = pointer
 * HLEUidClass defined in annotation:
 *            <parameterType> uidObject = HLEUidObjectMapping.getObject("<parameterType>", uid);
 *            if (uidObject == null) {
 *                cpu.gpr[_v0] = errorValueOnNotFound;
 *                pop all the parameters already prepared on the stack;
 *                goto afterSyscall;
 *            }
 *            parameterValue = uidObject
 *
 * And then common for all the types:
 *            try {
 *                parameterValue = <module>.<methodToCheck>(parameterValue);
 *            } catch (SceKernelErrorException e) {
 *                goto catchSceKernelErrorException;
 *            }
 *            push parameterValue on stack
 *
 * @param parameterReader               the current parameter state
 * @param func                          the syscall function
 * @param parameterType                 the type of the parameter
 * @param afterSyscallLabel             the Label pointing after the call to the syscall function
 * @param catchSceKernelErrorException  the Label pointing to the SceKernelErrorException catch handler
 */
private void loadParameter(CompilerParameterReader parameterReader, HLEModuleFunction func,
        Class<?> parameterType, Annotation[] parameterAnnotations, Label afterSyscallLabel,
        Label catchSceKernelErrorException) {
    if (parameterType == Processor.class) {
        loadProcessor();
        parameterReader.incrementCurrentStackSize();
    } else if (parameterType == CpuState.class) {
        loadCpu();
        parameterReader.incrementCurrentStackSize();
    } else if (parameterType == int.class) {
        parameterReader.loadNextInt();
        parameterReader.incrementCurrentStackSize();
    } else if (parameterType == float.class) {
        parameterReader.loadNextFloat();
        parameterReader.incrementCurrentStackSize();
    } else if (parameterType == long.class) {
        parameterReader.loadNextLong();
        parameterReader.incrementCurrentStackSize(2);
    } else if (parameterType == boolean.class) {
        parameterReader.loadNextInt();
        parameterReader.incrementCurrentStackSize();
    } else if (parameterType == String.class) {
        parameterReader.loadNextInt();

        int maxLength = 16 * 1024;
        for (Annotation parameterAnnotation : parameterAnnotations) {
            if (parameterAnnotation instanceof StringInfo) {
                StringInfo stringInfo = ((StringInfo) parameterAnnotation);
                maxLength = stringInfo.maxLength();
                break;
            }
        }
        loadImm(maxLength);
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, runtimeContextInternalName, "readStringNZ",
                "(II)" + Type.getDescriptor(String.class));
        parameterReader.incrementCurrentStackSize();
    } else if (parameterType == PspString.class) {
        parameterReader.loadNextInt();

        int maxLength = 16 * 1024;
        boolean canBeNull = false;
        for (Annotation parameterAnnotation : parameterAnnotations) {
            if (parameterAnnotation instanceof StringInfo) {
                StringInfo stringInfo = ((StringInfo) parameterAnnotation);
                maxLength = stringInfo.maxLength();
            }
            if (parameterAnnotation instanceof CanBeNull) {
                canBeNull = true;
            }
        }
        loadImm(maxLength);
        loadImm(canBeNull);
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, runtimeContextInternalName, "readPspStringNZ",
                "(IIZ)" + Type.getDescriptor(PspString.class));
        parameterReader.incrementCurrentStackSize();
    } else if (parameterType == TPointer.class || parameterType == TPointer8.class
            || parameterType == TPointer16.class || parameterType == TPointer32.class
            || parameterType == TPointer64.class || parameterType == TErrorPointer32.class) {
        // if (checkMemoryAccess()) {
        //     if (canBeNullParam && address == 0) {
        //         goto addressGood;
        //     }
        //     if (RuntimeContext.checkMemoryPointer(address)) {
        //         goto addressGood;
        //     }
        //     cpu.gpr[_v0] = SceKernelErrors.ERROR_INVALID_POINTER;
        //     pop all the parameters already prepared on the stack;
        //     goto afterSyscall;
        //     addressGood:
        // }
        // <parameterType> pointer = new <parameterType>(address);
        // if (parameterType == TErrorPointer32.class) {
        //     parameterReader.setHasErrorPointer(true);
        //     localVar[LOCAL_ERROR_POINTER] = pointer;
        // }
        mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(parameterType));
        mv.visitInsn(Opcodes.DUP);
        loadMemory();
        parameterReader.loadNextInt();

        boolean canBeNull = false;
        for (Annotation parameterAnnotation : parameterAnnotations) {
            if (parameterAnnotation instanceof CanBeNull) {
                canBeNull = true;
                break;
            }
        }

        if (checkMemoryAccess() && afterSyscallLabel != null) {
            Label addressGood = new Label();
            if (canBeNull) {
                mv.visitInsn(Opcodes.DUP);
                mv.visitJumpInsn(Opcodes.IFEQ, addressGood);
            }
            mv.visitInsn(Opcodes.DUP);
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, runtimeContextInternalName, "checkMemoryPointer", "(I)Z");
            mv.visitJumpInsn(Opcodes.IFNE, addressGood);
            storeRegister(_v0, SceKernelErrors.ERROR_INVALID_POINTER);
            parameterReader.popAllStack(4);
            mv.visitJumpInsn(Opcodes.GOTO, afterSyscallLabel);
            mv.visitLabel(addressGood);
        }
        if (parameterType == TPointer8.class || parameterType == TPointer16.class
                || parameterType == TPointer32.class || parameterType == TPointer64.class) {
            loadImm(canBeNull);
            mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(parameterType), "<init>",
                    "(" + memoryDescriptor + "IZ)V");
        } else {
            mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(parameterType), "<init>",
                    "(" + memoryDescriptor + "I)V");
        }
        if (parameterType == TErrorPointer32.class) {
            parameterReader.setHasErrorPointer(true);
            mv.visitInsn(Opcodes.DUP);
            mv.visitVarInsn(Opcodes.ASTORE, LOCAL_ERROR_POINTER);
        }
        parameterReader.incrementCurrentStackSize();
    } else if (pspAbstractMemoryMappedStructure.class.isAssignableFrom(parameterType)) {
        parameterReader.loadNextInt();

        boolean canBeNull = false;
        for (Annotation parameterAnnotation : parameterAnnotations) {
            if (parameterAnnotation instanceof CanBeNull) {
                canBeNull = true;
                break;
            }
        }

        if (checkMemoryAccess() && afterSyscallLabel != null) {
            Label addressGood = new Label();
            if (canBeNull) {
                mv.visitInsn(Opcodes.DUP);
                mv.visitJumpInsn(Opcodes.IFEQ, addressGood);
            }
            mv.visitInsn(Opcodes.DUP);
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, runtimeContextInternalName, "checkMemoryPointer", "(I)Z");
            mv.visitJumpInsn(Opcodes.IFNE, addressGood);
            storeRegister(_v0, SceKernelErrors.ERROR_INVALID_POINTER);
            parameterReader.popAllStack(1);
            mv.visitJumpInsn(Opcodes.GOTO, afterSyscallLabel);
            mv.visitLabel(addressGood);
        }

        mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(parameterType));
        mv.visitInsn(Opcodes.DUP);
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(parameterType), "<init>", "()V");
        mv.visitInsn(Opcodes.DUP_X1);
        mv.visitInsn(Opcodes.SWAP);
        loadMemory();
        mv.visitInsn(Opcodes.SWAP);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(parameterType), "read",
                "(" + memoryDescriptor + "I)V");
        parameterReader.incrementCurrentStackSize();
    } else {
        HLEUidClass hleUidClass = parameterType.getAnnotation(HLEUidClass.class);
        if (hleUidClass != null) {
            int errorValueOnNotFound = hleUidClass.errorValueOnNotFound();

            // <parameterType> uidObject = HLEUidObjectMapping.getObject("<parameterType>", uid);
            // if (uidObject == null) {
            //     cpu.gpr[_v0] = errorValueOnNotFound;
            //     pop all the parameters already prepared on the stack;
            //     goto afterSyscall;
            // }
            mv.visitLdcInsn(parameterType.getName());
            // Load the UID
            parameterReader.loadNextInt();

            // Load the UID Object
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(HLEUidObjectMapping.class),
                    "getObject",
                    "(" + Type.getDescriptor(String.class) + "I)" + Type.getDescriptor(Object.class));
            if (afterSyscallLabel != null) {
                Label foundUid = new Label();
                mv.visitInsn(Opcodes.DUP);
                mv.visitJumpInsn(Opcodes.IFNONNULL, foundUid);
                storeRegister(_v0, errorValueOnNotFound);
                parameterReader.popAllStack(1);
                mv.visitJumpInsn(Opcodes.GOTO, afterSyscallLabel);
                mv.visitLabel(foundUid);
            }
            mv.visitTypeInsn(Opcodes.CHECKCAST, Type.getInternalName(parameterType));
            parameterReader.incrementCurrentStackSize();
        } else {
            log.error(String.format("Unsupported sycall parameter type '%s'", parameterType.getName()));
            Emulator.PauseEmuWithStatus(Emulator.EMU_STATUS_UNIMPLEMENTED);
        }
    }

    Method methodToCheck = null;
    if (afterSyscallLabel != null) {
        for (Annotation parameterAnnotation : parameterAnnotations) {
            if (parameterAnnotation instanceof CheckArgument) {
                CheckArgument checkArgument = (CheckArgument) parameterAnnotation;
                try {
                    methodToCheck = func.getHLEModule().getClass().getMethod(checkArgument.value(),
                            parameterType);
                } catch (Exception e) {
                    log.error(String.format("CheckArgument method '%s' not found in %s", checkArgument.value(),
                            func.getModuleName()), e);
                }
                break;
            }
        }
    }

    if (methodToCheck != null) {
        // try {
        //     parameterValue = <module>.<methodToCheck>(parameterValue);
        // } catch (SceKernelErrorException e) {
        //     goto catchSceKernelErrorException;
        // }
        loadModule(func.getModuleName());
        mv.visitInsn(Opcodes.SWAP);

        Label tryStart = new Label();
        Label tryEnd = new Label();
        mv.visitTryCatchBlock(tryStart, tryEnd, catchSceKernelErrorException,
                Type.getInternalName(SceKernelErrorException.class));

        mv.visitLabel(tryStart);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(methodToCheck.getDeclaringClass()),
                methodToCheck.getName(),
                "(" + Type.getDescriptor(parameterType) + ")" + Type.getDescriptor(parameterType));
        mv.visitLabel(tryEnd);
    }

    parameterReader.incrementCurrentParameterIndex();
}

From source file:lapin.comp.asm.ASMByteCodeGenerator.java

License:Open Source License

private void generateCall(CallableInfo ci, Env env) {
    /*/*  w  w w .  j av  a 2s  .c om*/
     * local variables
     * <Callable#call>
     * 0: this
     * 1: args (list of arguments)
     * 2: env
     *
     * <Callable0#call0>
     * 0: this
     * 1: env
     *
     * <Callable1#call1>
     * 0: this
     * 1: arg0
     * 2: env
     *
     * <Callable2#call2>
     * 0: this
     * 1: arg0
     * 2: arg1
     * 3: env
     *
     * ...
     *
     */
    MethodVisitor mv = _cw.visitMethod(
            ci.mi.implCallable() ? Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL : Opcodes.ACC_FINAL, ci.mi.name(),
            Type.getMethodDescriptor(ci.retType, ci.paramTypes), null, null);

    // instruction list
    int len = ci.mi.instLen();
    // label
    Label label = null;

    // generate code
    for (int i = 0; i < len; i++) {
        Object inst = ci.mi.getInst(i);
        if (Logger.tracelevelp(env))
            Logger.trace("[asm:gen]" + i + ":\t~S", Lists.list(inst), env);

        // inst is symbol
        // -> convert tag (Symbol) to label (ASMe Label object)
        if (Data.isSymbol(inst)) {
            Symbol tag = Data.symbol(inst);
            Label l = (Label) ci.labelTable.get(tag);
            if (l == null) {
                throw new NotReachedException("label is null: ~S.", Lists.list(tag));
            } else if (l != label) {
                mv.visitLabel(l);
                label = l;
                if (Logger.tracelevelp(env))
                    Logger.trace("[asm:gen]" + i + ":\ttag ~S -> label ~S", Lists.list(tag, l), env);
            } else {
                if (Logger.tracelevelp(env))
                    Logger.trace("[asm:gen]" + i + ":\ttag ~S -> label ~S" + " (dup)", Lists.list(tag, l), env);
            }
            continue;
        }

        // inst must be the form of (id <arg1> <arg2> ....)
        Object id = Lists.car(inst);
        if (id == Insts.CONST) {
            /* push const on the stack. */
            Object obj = Lists.cadr(inst);
            String val = Data.string(constTable.get(obj));
            mv.visitVarInsn(Opcodes.ALOAD, 0);
            mv.visitFieldInsn(Opcodes.GETFIELD, toInternalName(super.classInfo.classname()), val,
                    TYPE_OBJECT.getDescriptor());
        } else if (id == Insts.VAR) {
            /* push var on the stack */
            Object var = Lists.cadr(inst);
            String val = Data.string(varTable.get(var));
            mv.visitVarInsn(Opcodes.ALOAD, 0);
            mv.visitFieldInsn(Opcodes.GETFIELD, toInternalName(super.classInfo.classname()), val,
                    TYPE_SYMBOL.getDescriptor());
        } else if (id == Insts.LAMBDA_LIST) {
            /* push lambdaList on the stack */
            Object var = Lists.cadr(inst);
            /* push _ll_<i> on the stack */
            String val = Data.string(llTable.get(var));
            mv.visitVarInsn(Opcodes.ALOAD, 0);
            mv.visitFieldInsn(Opcodes.GETFIELD, toInternalName(super.classInfo.classname()), val,
                    TYPE_LAMBDA_LIST.getDescriptor());
        } else if (id == Insts.ENV_GET) {
            /* env.get */
            Class type = Data.javaClass(Lists.cadr(inst));
            if (type.equals(int.class)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "getInt",
                        Type.getMethodDescriptor(Type.INT_TYPE, new Type[] { TYPE_SYMBOL }));
            } else if (type.equals(double.class)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "getDouble",
                        Type.getMethodDescriptor(Type.DOUBLE_TYPE, new Type[] { TYPE_SYMBOL }));
            } else if (type.equals(char.class)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "getChar",
                        Type.getMethodDescriptor(Type.CHAR_TYPE, new Type[] { TYPE_SYMBOL }));
            } else if (Object.class.isAssignableFrom(type)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "get",
                        Type.getMethodDescriptor(TYPE_OBJECT, new Type[] { TYPE_SYMBOL }));
            } else {
                throw new NotReachedException("unsupported type: ~S.", Lists.list(type));
            }
        } else if (id == Insts.ENV_SET) {
            /* env.set */
            Class type = Data.javaClass(Lists.cadr(inst));
            if (type.equals(int.class)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "set",
                        Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { TYPE_SYMBOL, Type.INT_TYPE }));
            } else if (type.equals(double.class)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "set",
                        Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { TYPE_SYMBOL, Type.DOUBLE_TYPE }));
            } else if (type.equals(char.class)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "set",
                        Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { TYPE_SYMBOL, Type.CHAR_TYPE }));
            } else if (Object.class.isAssignableFrom(type)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "set",
                        Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { TYPE_SYMBOL, TYPE_OBJECT }));
            } else {
                throw new NotReachedException("unsupported type: ~S.", Lists.list(type));
            }
        } else if (id == Insts.ENV_BIND) {
            /* env.bind */
            Class type = Data.javaClass(Lists.cadr(inst));
            if (type.equals(int.class)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "bind",
                        Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { TYPE_SYMBOL, Type.INT_TYPE }));
            } else if (type.equals(double.class)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "bind",
                        Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { TYPE_SYMBOL, Type.DOUBLE_TYPE }));
            } else if (type.equals(char.class)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "bind",
                        Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { TYPE_SYMBOL, Type.CHAR_TYPE }));
            } else if (Object.class.isAssignableFrom(type)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "bind",
                        Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { TYPE_SYMBOL, TYPE_OBJECT }));
            } else {
                throw new NotReachedException("unsupported type: ~S.", Lists.list(type));
            }
        } else if (id == Insts.ENV_UNBIND) {
            /* env.unbind */
            Class type = Data.javaClass(Lists.cadr(inst));
            if (type.equals(int.class)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "unbindInt",
                        Type.getMethodDescriptor(Type.INT_TYPE, new Type[] { TYPE_SYMBOL }));
            } else if (type.equals(double.class)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "unbindDouble",
                        Type.getMethodDescriptor(Type.DOUBLE_TYPE, new Type[] { TYPE_SYMBOL }));
            } else if (type.equals(char.class)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "unbindChar",
                        Type.getMethodDescriptor(Type.CHAR_TYPE, new Type[] { TYPE_SYMBOL }));
            } else if (Object.class.isAssignableFrom(type)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "unbind",
                        Type.getMethodDescriptor(TYPE_OBJECT, new Type[] { TYPE_SYMBOL }));
            } else {
                throw new NotReachedException("unsupported type: ~S.", Lists.list(type));
            }
        } else if (id == Insts.ENV_CHILD) {
            /* env.child */
            Object oldEnvVar = Lists.cadr(inst);
            Object newEnvVar = Lists.caddr(inst);
            Object oldSlot = Lists.cadr(oldEnvVar);
            Object newSlot = Lists.cadr(newEnvVar);
            int oldLocal = Data.fixnum(ci.localTable.get(oldSlot)).intValue();
            int newLocal = Data.fixnum(ci.localTable.get(newSlot)).intValue();
            if (Logger.tracelevelp(env))
                Logger.trace("[asm:gen]" + i + ":\tenv-child: local ~S -> ~S",
                        Lists.list(Data.toFixnum(oldLocal), Data.toFixnum(newLocal)), env);
            mv.visitVarInsn(Opcodes.ALOAD, oldLocal);
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "child",
                    Type.getMethodDescriptor(TYPE_ENV, TYPE_NO_ARGS));
            mv.visitVarInsn(Opcodes.ASTORE, newLocal);
        } else if (id == Insts.CALL) {
            /* funcall */
            int nargs = Data.fixnum(Lists.cadr(inst)).intValue();
            String className = "lapin.eval.Funcall";
            String methodName = nargs < 0 ? "funcall" : "funcall" + nargs;
            Class rType = Object.class;
            Class[] pTypes;
            if (nargs < 0) {
                pTypes = new Class[] { Function.class, Object.class, // list of args
                        Env.class };
            } else {
                pTypes = new Class[nargs + 2];
                pTypes[0] = Function.class;
                for (int j = 0; j < nargs; j++) {
                    pTypes[j + 1] = Object.class;
                }
                pTypes[nargs + 1] = Env.class;
            }

            Type retType = Type.getType(rType);
            Type[] paramTypes = new Type[pTypes.length];
            for (int j = 0; j < pTypes.length; j++)
                paramTypes[j] = Type.getType(pTypes[j]);

            mv.visitMethodInsn(Opcodes.INVOKESTATIC, toInternalName(className), methodName,
                    Type.getMethodDescriptor(retType, paramTypes));
        } else if (id == Insts.CALL_DIRECT) {
            /*
             * public class Foo
             *   extends CompiledExpr implements Callable2 {
             *  public Object call2(Object arg0, Object arg1, Env env) {
             *   ...
             *  }
             * }
             */
            MethodInfo mi = (MethodInfo) Lists.cadr(inst);
            String className = mi.classInfo().classname();
            int nargs = mi.nargs();
            boolean rest = mi.rest();
            String methodName = mi.name();
            Class rType = mi.retType();
            Class[] pTypes = mi.paramTypes();

            Type retType = Type.getType(rType);
            Type[] paramTypes = new Type[pTypes.length];
            for (int j = 0; j < pTypes.length; j++)
                paramTypes[j] = Type.getType(pTypes[j]);

            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, toInternalName(className), methodName,
                    Type.getMethodDescriptor(retType, paramTypes));
        } else if (id == Insts.COMPILED_EXPR) {
            /*
             * public class Foo extends CompiledExpr {
             *  static public Foo SELF;
             *  ...
             * }
             */
            String className = Data.string(Lists.cadr(inst));
            String fieldName = "SELF";
            String typeName = className;
            mv.visitFieldInsn(Opcodes.GETSTATIC, toInternalName(className), fieldName,
                    toTypeDescriptor(typeName));
        } else if (id == Insts.RETURN) {
            /* return */
            Class type = Data.javaClass(Lists.cadr(inst));
            if (type.equals(int.class) || type.equals(short.class) || type.equals(byte.class)
                    || type.equals(char.class)) {
                mv.visitInsn(Opcodes.IRETURN);
            } else if (type.equals(long.class)) {
                mv.visitInsn(Opcodes.LRETURN);
            } else if (type.equals(float.class)) {
                mv.visitInsn(Opcodes.FRETURN);
            } else if (type.equals(double.class)) {
                mv.visitInsn(Opcodes.DRETURN);
            } else if (type.equals(void.class)) {
                //mv.visitInsn(Opcodes.RETURN);
                throw new NotReachedException("unsupported returnType: ~S.", Lists.list(type));
            } else {
                mv.visitInsn(Opcodes.ARETURN);
            }
        } else if (id == Insts.IFEQ) {
            /* conditional jump */
            Symbol tag = Data.symbol(Lists.cadr(inst));
            Label l = (Label) ci.labelTable.get(tag);
            if (l == null) {
                throw new NotReachedException("label not found: ~S.", Lists.list(tag));
            }
            mv.visitJumpInsn(Opcodes.IFEQ, l);
        } else if (id == Insts.IFNE) {
            /* conditional jump */
            Symbol tag = Data.symbol(Lists.cadr(inst));
            Label l = (Label) ci.labelTable.get(tag);
            if (l == null) {
                throw new NotReachedException("label not found: ~S.", Lists.list(tag));
            }
            mv.visitJumpInsn(Opcodes.IFNE, l);
        } else if (id == Insts.GOTO) {
            /* jump */
            Symbol tag = Data.symbol(Lists.cadr(inst));
            Label l = (Label) ci.labelTable.get(tag);
            if (l == null) {
                throw new NotReachedException("label not found: ~S.", Lists.list(tag));
            }
            mv.visitJumpInsn(Opcodes.GOTO, l);
        } else if (id == Insts.LOAD) {
            /* local -> stack */
            Object localVar = Lists.cadr(inst);
            Object slot = Lists.cadr(localVar);
            Class type = Data.javaClass(Lists.caddr(localVar));
            int local = Data.fixnum(ci.localTable.get(slot)).intValue();
            int op = Type.getType(type).getOpcode(Opcodes.ILOAD);
            if (Logger.tracelevelp(env))
                Logger.trace("[asm:gen]" + i + ":\tload: local=~S type=~S",
                        Lists.list(Data.toFixnum(local), type), env);
            mv.visitVarInsn(op, local);
        } else if (id == Insts.STORE) {
            /* stack -> local */
            Object localVar = Lists.cadr(inst);
            Object slot = Lists.cadr(localVar);
            Class type = Data.javaClass(Lists.caddr(localVar));
            int local = Data.fixnum(ci.localTable.get(slot)).intValue();
            int op = Type.getType(type).getOpcode(Opcodes.ISTORE);
            if (Logger.tracelevelp(env))
                Logger.trace("[asm:gen]" + i + ":\tstore: local=~S type=~S",
                        Lists.list(Data.toFixnum(local), type), env);
            mv.visitVarInsn(op, local);
        } else if (id == Insts.POP) {
            /* pop a value and discard it */
            Class type = Data.javaClass(Lists.cadr(inst));
            int op;
            switch (Classes.sizeOf(type)) {
            case 1:
                op = Opcodes.POP;
                break;
            case 2:
                op = Opcodes.POP2;
                break;
            default:
                throw new NotReachedException("unsupported type: ~S.", Lists.list(type));
            }
            mv.visitInsn(op);
        } else if (id == Insts.DUP) {
            /* peek a value and duplicate it */
            Class type = Data.javaClass(Lists.cadr(inst));
            int op;
            switch (Classes.sizeOf(type)) {
            case 1:
                op = Opcodes.DUP;
                break;
            case 2:
                op = Opcodes.DUP2;
                break;
            default:
                throw new NotReachedException("unsupported type: ~S.", Lists.list(type));
            }
            mv.visitInsn(op);
        } else if (id == Insts.PUSH) {
            /* push a constant */
            Object val = Lists.cadr(inst);
            if (Data.isJavaBoolean(val)) {
                if (Data.javaBoolean(val).booleanValue())
                    mv.visitInsn(Opcodes.ICONST_1);
                else
                    mv.visitInsn(Opcodes.ICONST_0);
            } else if (val instanceof Byte || val instanceof Short || val instanceof Integer) {
                int n = Data.javaNumber(val).intValue();
                if (n == -1)
                    mv.visitInsn(Opcodes.ICONST_M1);
                else if (n == 0)
                    mv.visitInsn(Opcodes.ICONST_0);
                else if (n == 1)
                    mv.visitInsn(Opcodes.ICONST_1);
                else if (n == 2)
                    mv.visitInsn(Opcodes.ICONST_2);
                else if (n == 3)
                    mv.visitInsn(Opcodes.ICONST_3);
                else if (n == 4)
                    mv.visitInsn(Opcodes.ICONST_4);
                else if (n == 5)
                    mv.visitInsn(Opcodes.ICONST_5);
                else if (Byte.MIN_VALUE <= n && n <= Byte.MAX_VALUE)
                    mv.visitIntInsn(Opcodes.BIPUSH, n);
                else if (Short.MIN_VALUE <= n && n <= Short.MAX_VALUE)
                    mv.visitIntInsn(Opcodes.SIPUSH, n);
                else
                    mv.visitLdcInsn(Data.toFixnum(n));
            } else if (val instanceof Long) {
                long n = Data.javaNumber(val).longValue();
                if (n == 0L)
                    mv.visitInsn(Opcodes.LCONST_0);
                else if (n == 1L)
                    mv.visitInsn(Opcodes.LCONST_1);
                else
                    mv.visitLdcInsn(val);
            } else if (val instanceof Float) {
                float n = Data.javaNumber(val).floatValue();
                if (n == 0.0f)
                    mv.visitInsn(Opcodes.FCONST_0);
                else if (n == 1.0f)
                    mv.visitInsn(Opcodes.FCONST_1);
                else if (n == 2.0f)
                    mv.visitInsn(Opcodes.FCONST_2);
                else
                    mv.visitLdcInsn(val);
            } else if (val instanceof Double) {
                double n = Data.javaNumber(val).doubleValue();
                if (n == 0.0)
                    mv.visitInsn(Opcodes.DCONST_0);
                else if (n == 1.0)
                    mv.visitInsn(Opcodes.DCONST_1);
                else
                    mv.visitLdcInsn(val);
            } else if (Data.isCharacter(val)) {
                Character c = Data.character(val);
                int n = (int) c.charValue();
                if (Byte.MIN_VALUE <= n && n <= Byte.MAX_VALUE)
                    mv.visitIntInsn(Opcodes.BIPUSH, n);
                else if (Short.MIN_VALUE <= n && n <= Short.MAX_VALUE)
                    mv.visitIntInsn(Opcodes.SIPUSH, n);
                else
                    mv.visitLdcInsn(Data.toFixnum(n));
            } else if (Data.isString(val)) {
                mv.visitLdcInsn(val);
            } else {
                throw new NotReachedException("cannot push: ~S.", Lists.list(val));
            }
        } else if (id == Insts.GET) {
            Field f = Data.javaField(Lists.cadr(inst));
            String fieldName = f.getName();
            Class c = f.getDeclaringClass();
            String className = c.getName();
            Class t = f.getType();
            String typeName = t.getName();

            boolean isStatic = Classes.isStatic(f);
            int op = isStatic ? Opcodes.GETSTATIC : Opcodes.GETFIELD;

            mv.visitFieldInsn(op, toInternalName(className), fieldName, toTypeDescriptor(typeName));
        } else if (id == Insts.PUT) {
            Field f = Data.javaField(Lists.cadr(inst));
            String fieldName = f.getName();
            Class c = f.getDeclaringClass();
            String className = c.getName();
            Class t = f.getType();
            String typeName = t.getName();

            boolean isStatic = Classes.isStatic(f);
            int op = isStatic ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD;

            mv.visitFieldInsn(op, toInternalName(className), fieldName, toTypeDescriptor(typeName));
        } else if (id == Insts.INVOKE) {
            Method m = Data.javaMethod(Lists.cadr(inst));
            String methodName = m.getName();
            Class c = m.getDeclaringClass();
            String className = c.getName();
            Class rType = m.getReturnType();
            Class[] pTypes = m.getParameterTypes();
            if (rType.equals(void.class)) {
                throw new NotReachedException("unsupported returnType: ~S.", Lists.list(rType));
            }
            Type retType = Type.getType(rType);
            Type[] paramTypes = new Type[pTypes.length];
            for (int j = 0; j < pTypes.length; j++)
                paramTypes[j] = Type.getType(pTypes[j]);

            boolean isStatic = Classes.isStatic(m);
            boolean isInterface = c.isInterface();
            int op = isStatic ? Opcodes.INVOKESTATIC
                    : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL;

            mv.visitMethodInsn(op, toInternalName(className), methodName,
                    Type.getMethodDescriptor(retType, paramTypes));
        } else if (id == Insts.CHECKCAST) {
            Class c = Data.javaClass(Lists.cadr(inst));
            Type t = Type.getType(c);
            mv.visitTypeInsn(Opcodes.CHECKCAST, t.getInternalName());
        } else if (id == Insts.THROW) {
            mv.visitInsn(Opcodes.ATHROW);
        } else if (id == Insts.CATCH) {
            Symbol tagS = Data.symbol(Lists.cadr(inst));
            Symbol tagE = Data.symbol(Lists.caddr(inst));
            Symbol tagH = Data.symbol(Lists.cadddr(inst));
            String className;
            if (Lists.isEnd(Lists.cddddr(inst))) {
                className = null;
            } else {
                Class c = Data.javaClass(Lists.car(Lists.cddddr(inst)));
                className = toInternalName(c.getName());
            }
            Label labelS = (Label) ci.labelTable.get(tagS);
            if (labelS == null) {
                throw new NotReachedException("label not found: ~S.", Lists.list(tagS));
            }
            Label labelE = (Label) ci.labelTable.get(tagE);
            if (labelE == null) {
                throw new NotReachedException("label not found: ~S.", Lists.list(tagE));
            }
            Label labelH = (Label) ci.labelTable.get(tagH);
            if (labelH == null) {
                throw new NotReachedException("label not found: ~S.", Lists.list(tagH));
            }
            mv.visitTryCatchBlock(labelS, labelE, labelH, className);
        }
        //else if (id == Insts.CATCH_FROM ||
        //         id == Insts.CATCH_TO ||
        //         id == Insts.CATCH_HANDLER) {
        //    /* nothing emitted */
        //    continue;
        //}
        else {
            throw new NotReachedException("unknown inst: ~S.", Lists.list(inst));
        }
    }
    mv.visitMaxs(0, 0);
    mv.visitEnd();
}

From source file:net.sf.cglib.proxy.TestEnhancer.java

License:Apache License

public void testBridgeParameterCheckcast() throws Exception {

    // If the compiler used for Z omits the bridge method, and X is compiled with javac,
    // javac will generate an invokespecial bridge in X.

    // public interface I<A, B> {
    //   public A f(B b);
    // }/*from  w ww  .j  a v  a2s  . com*/
    // public abstract class Z<U extends Number> implements I<U, Long> {
    //   public U f(Long id) {
    //     return null;
    //   }
    // }
    // public class X extends Z<Integer> {}

    final Map<String, byte[]> classes = new HashMap<String, byte[]>();

    {
        ClassWriter cw = new ClassWriter(0);
        cw.visit(49, Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE, "I",
                "<A:Ljava/lang/Object;B:Ljava/lang/Object;>Ljava/lang/Object;", "java/lang/Object", null);
        {
            MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT, "f",
                    "(Ljava/lang/Object;)Ljava/lang/Object;", "(TB;)TA;", null);
            mv.visitEnd();
        }
        cw.visitEnd();
        classes.put("I.class", cw.toByteArray());
    }
    {
        ClassWriter cw = new ClassWriter(0);
        cw.visit(49, Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER | Opcodes.ACC_ABSTRACT, "Z",
                "<U:Ljava/lang/Number;>Ljava/lang/Object;LI<TU;Ljava/lang/String;>;", "java/lang/Object",
                new String[] { "I" });
        {
            MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
            mv.visitCode();
            mv.visitVarInsn(Opcodes.ALOAD, 0);
            mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
            mv.visitInsn(Opcodes.RETURN);
            mv.visitMaxs(1, 1);
            mv.visitEnd();
        }
        {
            MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "f", "(Ljava/lang/String;)Ljava/lang/Number;",
                    "(Ljava/lang/String;)TU;", null);
            mv.visitCode();
            mv.visitInsn(Opcodes.ACONST_NULL);
            mv.visitInsn(Opcodes.ARETURN);
            mv.visitMaxs(1, 2);
            mv.visitEnd();
        }
        cw.visitEnd();
        classes.put("Z.class", cw.toByteArray());
    }
    {
        ClassWriter cw = new ClassWriter(0);
        cw.visit(49, Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER, "X", "LZ<Ljava/lang/Integer;>;", "Z", null);
        {
            MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
            mv.visitCode();
            mv.visitVarInsn(Opcodes.ALOAD, 0);
            mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "Z", "<init>", "()V", false);
            mv.visitInsn(Opcodes.RETURN);
            mv.visitMaxs(1, 1);
            mv.visitEnd();
        }
        {
            MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_BRIDGE | Opcodes.ACC_SYNTHETIC,
                    "f", "(Ljava/lang/Object;)Ljava/lang/Object;", null, null);
            mv.visitCode();
            mv.visitVarInsn(Opcodes.ALOAD, 0);
            mv.visitVarInsn(Opcodes.ALOAD, 1);
            mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/String");
            mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "Z", "f", "(Ljava/lang/String;)Ljava/lang/Number;",
                    false);
            mv.visitInsn(Opcodes.ARETURN);
            mv.visitMaxs(2, 2);
            mv.visitEnd();
        }

        cw.visitEnd();

        classes.put("X.class", cw.toByteArray());
    }

    ClassLoader classLoader = new ClassLoader(getClass().getClassLoader()) {
        @Override
        public InputStream getResourceAsStream(String name) {
            InputStream is = super.getResourceAsStream(name);
            if (is != null) {
                return is;
            }
            if (classes.containsKey(name)) {
                return new ByteArrayInputStream(classes.get(name));
            }
            return null;
        }

        public Class findClass(String name) throws ClassNotFoundException {
            byte[] ba = classes.get(name.replace('.', '/') + ".class");
            if (ba != null) {
                return defineClass(name, ba, 0, ba.length);
            }
            throw new ClassNotFoundException(name);
        }
    };

    List<Class> retTypes = new ArrayList<Class>();
    List<Class> paramTypes = new ArrayList<Class>();
    Interceptor interceptor = new Interceptor(retTypes, paramTypes);

    Enhancer e = new Enhancer();
    e.setClassLoader(classLoader);
    e.setSuperclass(classLoader.loadClass("X"));
    e.setCallback(interceptor);

    Object c = e.create();

    for (Method m : c.getClass().getDeclaredMethods()) {
        if (m.getName().equals("f") && m.getReturnType().equals(Object.class)) {
            m.invoke(c, new Object[] { null });
        }
    }

    // f(Object)Object should bridge to f(Number)String
    assertEquals(Arrays.asList(Object.class, Number.class), retTypes);
    assertEquals(Arrays.asList(Object.class, String.class), paramTypes);
}

From source file:org.actorsguildframework.internal.codegenerator.ActorProxyCreator.java

License:Apache License

/**
 * Create or get a MessageCaller implementation for the given method.
 * @param ownerClass the class that owns the message
 * @param method the method to invoke/*from  w w w . j a va  2 s  .c o m*/
 * @return the message caller
 * @throws NoSuchMethodException 
 * @throws SecurityException 
 */
@SuppressWarnings("unchecked")
public static Class<MessageCaller<?>> createMessageCaller(Class<?> ownerClass, Method method)
        throws SecurityException, NoSuchMethodException {

    String className = String.format("%s_%s_%d__MESSAGECALLER", ownerClass.getName(), method.getName(),
            getMethodNumber(method));
    String classNameInternal = className.replace('.', '/');
    java.lang.reflect.Type fullReturnType = method.getGenericReturnType();
    if ((!(fullReturnType instanceof ParameterizedType))
            && AsyncResult.class.isAssignableFrom(((Class) ((ParameterizedType) fullReturnType).getRawType())))
        throw new RuntimeException("Something's wrong here: should not be called for such a method");
    String returnSignature = GenericTypeHelper
            .getSignature(((ParameterizedType) fullReturnType).getActualTypeArguments()[0]);

    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
    MethodVisitor mv;

    cw.visit(codeVersion, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_SUPER + Opcodes.ACC_SYNTHETIC,
            classNameInternal, "L" + classNameInternal + "<" + returnSignature + ">;",
            "org/actorsguildframework/internal/MessageCaller", null);
    cw.visitSource(null, null);

    {
        mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "org/actorsguildframework/internal/MessageCaller", "<init>",
                "()V");
        mv.visitInsn(Opcodes.RETURN);
        Label l1 = new Label();
        mv.visitLabel(l1);
        mv.visitLocalVariable("this", "L" + classNameInternal + ";", null, l0, l1, 0);
        mv.visitMaxs(1, 1);
        mv.visitEnd();
    }
    {
        mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "invoke",
                "(Lorg/actorsguildframework/Actor;[Ljava/lang/Object;)Lorg/actorsguildframework/AsyncResult;",
                "(Lorg/actorsguildframework/Actor;[Ljava/lang/Object;)Lorg/actorsguildframework/AsyncResult<"
                        + returnSignature + ">;",
                null);
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);

        mv.visitVarInsn(Opcodes.ALOAD, 1);
        mv.visitTypeInsn(Opcodes.CHECKCAST, Type.getInternalName(method.getDeclaringClass()) + "__ACTORPROXY");

        int idx = 0;
        for (Class<?> t : method.getParameterTypes()) {
            mv.visitVarInsn(Opcodes.ALOAD, 2);
            mv.visitIntInsn(Opcodes.BIPUSH, idx);
            mv.visitInsn(Opcodes.AALOAD);
            if (t.isPrimitive()) {
                String wrapperDescr = GenerationUtils.getWrapperInternalName(t);
                mv.visitTypeInsn(Opcodes.CHECKCAST, wrapperDescr);
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, wrapperDescr, t.getName() + "Value",
                        "()" + Type.getDescriptor(t));
            } else {
                if (isArgumentFreezingRequired(method, idx, t)) {
                    mv.visitTypeInsn(Opcodes.CHECKCAST, Type.getInternalName(SerializableFreezer.class));
                    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(SerializableFreezer.class),
                            "get", Type.getMethodDescriptor(SerializableFreezer.class.getMethod("get")));
                }
                if (!t.equals(Object.class))
                    mv.visitTypeInsn(Opcodes.CHECKCAST, Type.getInternalName(t));
            }
            idx++;
        }
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
                Type.getInternalName(method.getDeclaringClass()) + "__ACTORPROXY",
                String.format(SUPER_CALLER_NAME_FORMAT, method.getName()), Type.getMethodDescriptor(method));

        mv.visitInsn(Opcodes.ARETURN);

        Label l2 = new Label();
        mv.visitLabel(l2);
        mv.visitLocalVariable("this", "L" + classNameInternal + ";", null, l0, l2, 0);
        mv.visitLocalVariable("instance", "Lorg/actorsguildframework/Actor;", null, l0, l2, 1);
        mv.visitLocalVariable("arguments", "[Ljava/lang/Object;", null, l0, l2, 2);

        mv.visitMaxs(0, 0);
        mv.visitEnd();
    }
    {
        mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "getMessageName", "()Ljava/lang/String;", null, null);
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitLdcInsn(method.getName());
        mv.visitInsn(Opcodes.ARETURN);
        Label l1 = new Label();
        mv.visitLabel(l1);
        mv.visitLocalVariable("this", "L" + classNameInternal + ";", null, l0, l1, 0);
        mv.visitMaxs(0, 0);
        mv.visitEnd();
    }
    cw.visitEnd();

    return (Class<MessageCaller<?>>) GenerationUtils.loadClass(className, cw.toByteArray());
}

From source file:org.actorsguildframework.internal.codegenerator.BeanCreator.java

License:Apache License

/**
 * Writes the bean constructor to the given ClassWriter.
 * @param beanClass the original bean class to extend
 * @param bcd the descriptor of the bean
 * @param classNameInternal the internal name of the new class
 * @param cw the ClassWriter to write to
 * @param snippetWriter if not null, this will be invoked to add a snippet
 *                      after the invocation of the super constructor
 *//*from  w  ww  .jav  a2  s .  c o m*/
public static void writeConstructor(Class<?> beanClass, BeanClassDescriptor bcd, String classNameInternal,
        ClassWriter cw, SnippetWriter snippetWriter) {
    String classNameDescriptor = "L" + classNameInternal + ";";

    int localPropertySize = 0;
    ArrayList<PropertyDescriptor> localVarProperties = new ArrayList<PropertyDescriptor>();
    for (int i = 0; i < bcd.getPropertyCount(); i++) {
        PropertyDescriptor pd = bcd.getProperty(i);
        if (pd.getPropertySource().isGenerating() || (pd.getDefaultValue() != null)) {
            localVarProperties.add(pd);
            localPropertySize += Type.getType(pd.getPropertyClass()).getSize();
        }
    }

    final int locVarThis = 0;
    final int locVarController = 1;
    final int locVarProps = 2;
    final int locVarPropertiesOffset = 3;
    final int locVarP = 3 + localPropertySize;
    final int locVarK = 4 + localPropertySize;
    final int locVarV = 5 + localPropertySize;

    MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>",
            "(Lorg/actorsguildframework/internal/Controller;Lorg/actorsguildframework/Props;)V", null, null);
    mv.visitCode();
    Label lTry = new Label();
    Label lCatch = new Label();
    mv.visitTryCatchBlock(lTry, lCatch, lCatch, "java/lang/ClassCastException");

    Label lBegin = new Label();
    mv.visitLabel(lBegin);
    mv.visitVarInsn(Opcodes.ALOAD, locVarThis);
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(beanClass), "<init>", "()V");

    if (snippetWriter != null)
        snippetWriter.write(mv);

    Label lPropertyInit = new Label();
    mv.visitLabel(lPropertyInit);
    // load default values into the local variables for each property that must be set
    int varCount = 0;
    for (PropertyDescriptor pd : localVarProperties) {
        Type pt = Type.getType(pd.getPropertyClass());
        if (pd.getDefaultValue() != null)
            mv.visitFieldInsn(Opcodes.GETSTATIC, Type.getInternalName(pd.getDefaultValue().getDeclaringClass()),
                    pd.getDefaultValue().getName(), Type.getDescriptor(pd.getDefaultValue().getType()));
        else
            GenerationUtils.generateLoadDefault(mv, pd.getPropertyClass());
        mv.visitVarInsn(pt.getOpcode(Opcodes.ISTORE), locVarPropertiesOffset + varCount);
        varCount += pt.getSize();
    }

    // loop through the props argument's list
    mv.visitVarInsn(Opcodes.ALOAD, locVarProps);
    mv.visitVarInsn(Opcodes.ASTORE, locVarP);
    Label lWhile = new Label();
    Label lEndWhile = new Label();
    Label lWhileBody = new Label();
    mv.visitLabel(lWhile);
    mv.visitJumpInsn(Opcodes.GOTO, lEndWhile);
    mv.visitLabel(lWhileBody);

    mv.visitVarInsn(Opcodes.ALOAD, locVarP);
    mv.visitInsn(Opcodes.DUP);
    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "org/actorsguildframework/Props", "getKey",
            "()Ljava/lang/String;");
    mv.visitVarInsn(Opcodes.ASTORE, locVarK);
    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "org/actorsguildframework/Props", "getValue",
            "()Ljava/lang/Object;");
    mv.visitVarInsn(Opcodes.ASTORE, locVarV);

    mv.visitLabel(lTry);
    // write an if for each property
    Label lEndIf = new Label();
    varCount = 0;
    int ifCount = 0;
    for (int i = 0; i < bcd.getPropertyCount(); i++) {
        PropertyDescriptor pd = bcd.getProperty(i);
        boolean usesLocal = pd.getPropertySource().isGenerating() || (pd.getDefaultValue() != null);
        Class<?> propClass = pd.getPropertyClass();
        Type pt = Type.getType(propClass);
        mv.visitVarInsn(Opcodes.ALOAD, locVarK);
        mv.visitLdcInsn(pd.getName());
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z");
        Label lElse = new Label();
        mv.visitJumpInsn(Opcodes.IFEQ, lElse);

        if (!usesLocal)
            mv.visitVarInsn(Opcodes.ALOAD, locVarThis); // for setter invocation, load 'this'

        if (propClass.isPrimitive()) {
            mv.visitLdcInsn(pd.getName());
            mv.visitVarInsn(Opcodes.ALOAD, locVarV);
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(BeanHelper.class),
                    String.format("get%s%sFromPropValue",
                            propClass.getName().substring(0, 1).toUpperCase(Locale.US),
                            propClass.getName().substring(1)),
                    "(Ljava/lang/String;Ljava/lang/Object;)" + pt.getDescriptor());
        } else if (!propClass.equals(Object.class)) {
            mv.visitVarInsn(Opcodes.ALOAD, locVarV);
            mv.visitTypeInsn(Opcodes.CHECKCAST, pt.getInternalName());
        } else
            mv.visitVarInsn(Opcodes.ALOAD, locVarV);

        if (!usesLocal)
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, classNameInternal, pd.getSetter().getName(),
                    Type.getMethodDescriptor(pd.getSetter()));
        else
            mv.visitVarInsn(pt.getOpcode(Opcodes.ISTORE), varCount + locVarPropertiesOffset);

        mv.visitJumpInsn(Opcodes.GOTO, lEndIf);
        mv.visitLabel(lElse);

        ifCount++;
        if (usesLocal)
            varCount += pt.getSize();
    }

    // else (==> if not prop matched) throw IllegalArgumentException
    mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(IllegalArgumentException.class));
    mv.visitInsn(Opcodes.DUP);
    mv.visitLdcInsn("Unknown property \"%s\".");
    mv.visitInsn(Opcodes.ICONST_1);
    mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
    mv.visitInsn(Opcodes.DUP);
    mv.visitInsn(Opcodes.ICONST_0);
    mv.visitVarInsn(Opcodes.ALOAD, locVarK);
    mv.visitInsn(Opcodes.AASTORE);
    mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/String", "format",
            "(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;");
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(IllegalArgumentException.class), "<init>",
            "(Ljava/lang/String;)V");
    mv.visitInsn(Opcodes.ATHROW);

    mv.visitLabel(lCatch);
    mv.visitInsn(Opcodes.POP); // pop the exception object (not needed)
    mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(IllegalArgumentException.class));
    mv.visitInsn(Opcodes.DUP);
    mv.visitLdcInsn("Incompatible type for property \"%s\". Got %s.");
    mv.visitInsn(Opcodes.ICONST_2);
    mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
    mv.visitInsn(Opcodes.DUP);
    mv.visitInsn(Opcodes.ICONST_0);
    mv.visitVarInsn(Opcodes.ALOAD, locVarK);
    mv.visitInsn(Opcodes.AASTORE);
    mv.visitInsn(Opcodes.DUP);
    mv.visitInsn(Opcodes.ICONST_1);
    mv.visitVarInsn(Opcodes.ALOAD, locVarV);
    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;");
    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getName", "()Ljava/lang/String;");
    mv.visitInsn(Opcodes.AASTORE);
    mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/String", "format",
            "(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;");
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(IllegalArgumentException.class), "<init>",
            "(Ljava/lang/String;)V");
    mv.visitInsn(Opcodes.ATHROW);

    mv.visitLabel(lEndIf);
    mv.visitVarInsn(Opcodes.ALOAD, locVarP);
    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "org/actorsguildframework/Props", "tail",
            "()Lorg/actorsguildframework/Props;");
    mv.visitVarInsn(Opcodes.ASTORE, locVarP);

    mv.visitLabel(lEndWhile);
    mv.visitVarInsn(Opcodes.ALOAD, locVarP);
    mv.visitJumpInsn(Opcodes.IFNONNULL, lWhileBody);

    // write local variables back into properties 
    varCount = 0;
    for (PropertyDescriptor pd : localVarProperties) {
        Type pt = Type.getType(pd.getPropertyClass());
        mv.visitVarInsn(Opcodes.ALOAD, locVarThis);
        if (pd.getPropertySource() == PropertySource.ABSTRACT_METHOD) {
            mv.visitVarInsn(pt.getOpcode(Opcodes.ILOAD), locVarPropertiesOffset + varCount);
            mv.visitFieldInsn(Opcodes.PUTFIELD, classNameInternal,
                    String.format(PROP_FIELD_NAME_TEMPLATE, pd.getName()), pt.getDescriptor());
        } else if (pd.getPropertySource() == PropertySource.USER_WRITTEN) {
            mv.visitVarInsn(pt.getOpcode(Opcodes.ILOAD), locVarPropertiesOffset + varCount);
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, classNameInternal, pd.getSetter().getName(),
                    Type.getMethodDescriptor(pd.getSetter()));
        } else
            throw new RuntimeException("Internal error");
        varCount += pt.getSize();
    }

    // if bean is thread-safe, publish all writes now
    if (bcd.isThreadSafe()) {
        mv.visitVarInsn(Opcodes.ALOAD, locVarThis);
        mv.visitInsn(Opcodes.DUP);
        mv.visitInsn(Opcodes.MONITORENTER);
        mv.visitInsn(Opcodes.MONITOREXIT);
    }

    mv.visitInsn(Opcodes.RETURN);
    Label lEnd = new Label();
    mv.visitLabel(lEnd);

    mv.visitLocalVariable("this", classNameDescriptor, null, lBegin, lEnd, locVarThis);
    mv.visitLocalVariable("controller", "Lorg/actorsguildframework/internal/Controller;", null, lBegin, lEnd,
            locVarController);
    mv.visitLocalVariable("props", "Lorg/actorsguildframework/Props;", null, lBegin, lEnd, locVarProps);
    varCount = 0;
    for (PropertyDescriptor pd : localVarProperties) {
        Type pt = Type.getType(pd.getPropertyClass());
        mv.visitLocalVariable("__" + pd.getName(), pt.getDescriptor(),
                GenericTypeHelper.getSignature(pd.getPropertyType()), lPropertyInit, lEnd,
                locVarPropertiesOffset + varCount);
        varCount += pt.getSize();
    }
    mv.visitLocalVariable("p", "Lorg/actorsguildframework/Props;", null, lPropertyInit, lEnd, locVarP);
    mv.visitLocalVariable("k", "Ljava/lang/String;", null, lWhile, lEndWhile, locVarK);
    mv.visitLocalVariable("v", "Ljava/lang/Object;", null, lWhile, lEndWhile, locVarV);
    mv.visitMaxs(0, 0);
    mv.visitEnd();
}