Example usage for org.objectweb.asm MethodVisitor visitLabel

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

Introduction

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

Prototype

public void visitLabel(final Label label) 

Source Link

Document

Visits a label.

Usage

From source file:org.eclipse.m2m.atl.emftvm.jit.CodeBlockJIT.java

License:Open Source License

/**
 * Generates an execute method for the {@link JITCodeBlock}.
 * @param execute the execute method visitor
 * @param cb the {@link CodeBlock} to JIT-compile
 * @param className the name of the generated class
 *///w  w w  . j  a va  2 s. c  o  m
protected void generateExecute(final MethodVisitor execute, final CodeBlock cb, final String className) {
    execute.visitCode();
    // Generate labels
    final LabelSwitch ls = new LabelSwitch();
    for (Instruction instr : cb.getCode()) {
        ls.doSwitch(instr);
    }
    // Default labels
    final Label start = new Label();
    final Label end = new Label();
    final Label tryStart = new Label();
    final Label vmExceptionHandler = new Label();
    final Label exceptionHandler = new Label();
    final Label catchEnd = new Label();
    // Create exception table
    execute.visitTryCatchBlock(tryStart, vmExceptionHandler, vmExceptionHandler,
            Type.getInternalName(VMException.class));
    execute.visitTryCatchBlock(tryStart, vmExceptionHandler, exceptionHandler,
            Type.getInternalName(Exception.class));
    // Generate bytecode
    execute.visitLabel(start);
    execute.visitVarInsn(ALOAD, 1); // frame
    execute.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(StackFrame.class), "getEnv",
            Type.getMethodDescriptor(Type.getType(ExecEnv.class), new Type[0]));
    execute.visitVarInsn(ASTORE, 2);
    execute.visitVarInsn(ALOAD, 2); // env
    execute.visitMethodInsn(INVOKEINTERFACE, Type.getInternalName(ExecEnv.class), "getMonitor",
            Type.getMethodDescriptor(Type.getType(VMMonitor.class), new Type[0]));
    execute.visitVarInsn(ASTORE, 3); // monitor
    execute.visitLabel(tryStart);
    final ByteCodeSwitch bs = new ByteCodeSwitch(this, execute, ls);
    final EList<Instruction> code = cb.getCode();
    final boolean hasMonitor = getEnv().getMonitor() != null;
    for (Instruction instr : code) {
        if (hasMonitor) {
            // do checkMonitor() before each instruction
            generateCheckMonitor(execute, code.indexOf(instr) + 1); // pc
        }
        // generate instruction-specific code
        bs.doSwitch(instr);
    }
    execute.visitJumpInsn(GOTO, catchEnd);
    // catch (VMException e)
    execute.visitLabel(vmExceptionHandler);
    execute.visitVarInsn(ASTORE, 4); // e
    execute.visitVarInsn(ALOAD, 4); // e
    execute.visitInsn(ATHROW); // throw e
    // catch (Exception e)
    execute.visitLabel(exceptionHandler);
    execute.visitVarInsn(ASTORE, 4); // e
    execute.visitTypeInsn(NEW, Type.getInternalName(VMException.class)); // new VMException(): [vme, ...]
    execute.visitInsn(DUP); // [vme, vme, e, ...]
    execute.visitVarInsn(ALOAD, 1); // frame: [frame, vme, vme, ...]
    execute.visitVarInsn(ALOAD, 4); // e: [e, frame, vme, vme, ...]
    execute.visitMethodInsn(INVOKESPECIAL, // new VMException(frame, e): [vme, ...]
            Type.getInternalName(VMException.class), "<init>", Type.getMethodDescriptor(Type.VOID_TYPE,
                    new Type[] { Type.getType(StackFrame.class), Type.getType(Throwable.class) }));
    execute.visitInsn(ATHROW); // throw vme
    // Regular method return
    execute.visitLabel(catchEnd);
    if (cb.getStackLevel() == 0) {
        execute.visitInsn(ACONST_NULL); // push null
    }
    execute.visitInsn(ARETURN); // return result
    execute.visitLabel(end);
    // Create local variable table
    execute.visitLocalVariable("this", "L" + className + ";", null, start, end, 0);
    execute.visitLocalVariable("frame", Type.getDescriptor(StackFrame.class), null, start, end, 1);
    execute.visitLocalVariable("env", Type.getDescriptor(ExecEnv.class), null, start, end, 2);
    execute.visitLocalVariable("monitor", Type.getDescriptor(VMMonitor.class), null, start, end, 3);
    execute.visitLocalVariable("e", Type.getDescriptor(VMException.class), null, vmExceptionHandler,
            exceptionHandler, 4);
    execute.visitLocalVariable("e", Type.getDescriptor(Exception.class), null, exceptionHandler, catchEnd, 4);
    // Finalise
    execute.visitMaxs(0, 0); // recalculate 
    execute.visitEnd();
}

From source file:org.eclipse.m2m.atl.emftvm.jit.CodeBlockJIT.java

License:Open Source License

/**
 * Generates bytecode for checking the VM monitor
 * @param mv the method visitor to generate code for
 * @param pc the current program counter
 *///from   w ww  .j  av a  2s .  c  om
protected static void generateCheckMonitor(final MethodVisitor mv, final int pc) {
    // Labels
    final Label notTerminated = new Label();
    // Generate bytecode
    mv.visitVarInsn(ALOAD, 3); // monitor: [..., monitor]
    mv.visitMethodInsn(INVOKEINTERFACE, // monitor.isTerminated(): [..., boolean]
            Type.getInternalName(VMMonitor.class), "isTerminated",
            Type.getMethodDescriptor(Type.BOOLEAN_TYPE, new Type[0]));
    mv.visitJumpInsn(IFEQ, notTerminated); // jump if isTerminated == false: [...]
    mv.visitTypeInsn(NEW, Type.getInternalName(VMException.class)); // new VMException: [..., vme]
    mv.visitInsn(DUP); // [..., vme, vme]
    mv.visitVarInsn(ALOAD, 1); // frame: [..., vme, vme, frame]
    mv.visitLdcInsn("Execution terminated."); // [..., vme, vme, frame, msg]
    mv.visitMethodInsn(INVOKESPECIAL, // vme.<init>(frame, msg): [..., vme]
            Type.getInternalName(VMException.class), "<init>", Type.getMethodDescriptor(Type.VOID_TYPE,
                    new Type[] { Type.getType(StackFrame.class), Type.getType(String.class) }));
    mv.visitInsn(ATHROW); // throw vme: [...]
    mv.visitLabel(notTerminated);
    mv.visitVarInsn(ALOAD, 1); // frame: [..., frame]
    generatePushInt(mv, pc); // [..., frame, pc]
    mv.visitMethodInsn(INVOKEVIRTUAL, // frame.setPc(pc): [...] 
            Type.getInternalName(StackFrame.class), "setPc",
            Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { Type.INT_TYPE }));
    mv.visitVarInsn(ALOAD, 3); // monitor: [..., monitor]
    mv.visitVarInsn(ALOAD, 1); // frame: [..., monitor, frame]
    mv.visitMethodInsn(INVOKEINTERFACE, // monitor.step(frame): [...]
            Type.getInternalName(VMMonitor.class), "step",
            Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { Type.getType(StackFrame.class) }));
}

From source file:org.eclipse.objectteams.otredyn.bytecode.asm.AddGlobalTeamActivationAdapter.java

License:Open Source License

@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
    synchronized (AddGlobalTeamActivationAdapter.class) {
        if (!done && isMainMethod(name, desc, access)) {
            done = true;//from  w  ww .j  a v  a  2  s  .  c om
            final MethodVisitor methodVisitor = cv.visitMethod(access, name, desc, null, null);
            return new AdviceAdapter(this.api, methodVisitor, access, name, desc) {
                @Override
                protected void onMethodEnter() {
                    List<String> teams = getTeamsFromConfigFile();
                    for (String aTeam : teams) {
                        Label start, end, typeHandler, ctorHandler, after;

                        String aTeamSlash = aTeam.replace('.', '/');

                        // new SomeTeam():
                        methodVisitor.visitLabel(start = new Label());
                        methodVisitor.visitTypeInsn(Opcodes.NEW, aTeamSlash);
                        //       .activate(Team.ALL_THREADS):
                        methodVisitor.visitInsn(Opcodes.DUP);
                        methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, aTeamSlash, "<init>", "()V",
                                false);
                        methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, ClassNames.TEAM_SLASH, "ALL_THREADS",
                                "Ljava/lang/Thread;");
                        methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, aTeamSlash, "activate",
                                "(Ljava/lang/Thread;)V", false);

                        methodVisitor.visitLabel(end = new Label());
                        methodVisitor.visitJumpInsn(Opcodes.GOTO, after = new Label());

                        // catch (ClassNotFoundException, NoClassDefFoundError):
                        //   System.err.println(...)
                        methodVisitor.visitLabel(typeHandler = new Label());
                        methodVisitor.visitInsn(Opcodes.POP); // discard the exception
                        methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "err",
                                "Ljava/io/PrintStream;");
                        methodVisitor.visitLdcInsn("Config error: Team class '" + aTeam + "' in config file '"
                                + TEAM_CONFIG_FILE + "' can not be found!");
                        methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println",
                                "(Ljava/lang/String;)V", false);
                        methodVisitor.visitJumpInsn(Opcodes.GOTO, after);
                        methodVisitor.visitTryCatchBlock(start, end, typeHandler,
                                "java/lang/ClassNotFoundException");
                        // dup to avoid stackmap errors (ASM bug at 1.8)
                        methodVisitor.visitLabel(typeHandler = new Label());
                        methodVisitor.visitInsn(Opcodes.POP); // discard the exception
                        methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "err",
                                "Ljava/io/PrintStream;");
                        methodVisitor.visitLdcInsn("Config error: Team class '" + aTeam + "' in config file '"
                                + TEAM_CONFIG_FILE + "' can not be found!");
                        methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println",
                                "(Ljava/lang/String;)V", false);
                        methodVisitor.visitJumpInsn(Opcodes.GOTO, after);
                        //
                        methodVisitor.visitTryCatchBlock(start, end, typeHandler,
                                "java/lang/NoClassDefFoundError");

                        // catch (NoSuchMethodError):
                        //   System.err.println(...)
                        methodVisitor.visitLabel(ctorHandler = new Label());
                        methodVisitor.visitInsn(Opcodes.POP); // discard the exception
                        methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "err",
                                "Ljava/io/PrintStream;");
                        methodVisitor.visitLdcInsn(
                                "Activation failed: Team class '" + aTeam + "' has no default constuctor!");
                        methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println",
                                "(Ljava/lang/String;)V", false);
                        methodVisitor.visitTryCatchBlock(start, end, ctorHandler,
                                "java/lang/NoSuchMethodError");

                        methodVisitor.visitLabel(after);
                    }
                }

                @Override
                public void visitMaxs(int maxStack, int maxLocals) {
                    super.visitMaxs(Math.max(maxStack, 3), maxLocals);
                }
            };
        }
        return null;
    }
}

From source file:org.eclipse.objectteams.otredyn.bytecode.asm.AddThreadNotificationAdapter.java

License:Open Source License

@Override
public MethodVisitor visitMethod(int access, String methodName, String desc, String signature,
        String[] exceptions) {/*from  w ww  . j a v  a2s  .  co  m*/
    if (INIT.equals(methodName)) {
        // into each constructor ...
        final MethodVisitor methodVisitor = cv.visitMethod(access, methodName, desc, null, null);
        return new AdviceAdapter(this.api, methodVisitor, access, methodName, desc) {
            @Override
            public void invokeConstructor(Type type, Method method) {
                super.invokeConstructor(type, method);
                // ... that contains a super(..) call (rather than this(..)):
                if (type.getInternalName().equals(clazz.getInternalSuperClassName())) {
                    // insert:
                    // this._OT$creationThread = Thread.currentThread();
                    methodVisitor.visitIntInsn(Opcodes.ALOAD, 0);
                    methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, ClassNames.THREAD_SLASH, CURRENT_THREAD,
                            CURRENT_THREAD_DESC, false);
                    methodVisitor.visitFieldInsn(Opcodes.PUTFIELD, clazz.getInternalName(), CREATION_THREAD,
                            THREAD_DESC);
                }
            }
        };
    } else if (RUN.equals(methodName) && RUN_DESC.equals(desc)) {
        final MethodVisitor methodVisitor = cv.visitMethod(access, methodName, desc, null, null);
        return new AdviceAdapter(this.api, methodVisitor, access, methodName, desc) {

            Label start = new Label(); // start of method (scope of new local)
            Label end = new Label(); // end of method
            int isThreadStartIdx; // new local: boolean _OT$isThreadStart

            @Override
            protected void onMethodEnter() {
                methodVisitor.visitLabel(start);
                isThreadStartIdx = newLocal(Type.BOOLEAN_TYPE);
                methodVisitor.visitLocalVariable("_OT$isThreadStart", "Z", null, start, end, isThreadStartIdx);
                // TeamThreadManager.newThreadStarted(false, this._OT$creationThread)
                methodVisitor.visitInsn(Opcodes.ICONST_0);
                methodVisitor.visitIntInsn(Opcodes.ALOAD, 0);
                methodVisitor.visitFieldInsn(Opcodes.GETFIELD, clazz.getInternalName(), CREATION_THREAD,
                        THREAD_DESC);
                methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, ClassNames.TEAM_THREAD_MANAGER_SLASH,
                        NEW_THREAD_STARTED, NEW_THREAD_STARTED_DESC, false);
                methodVisitor.visitIntInsn(Opcodes.ISTORE, isThreadStartIdx);
                // this._OT$creationThread = null; // avoid leak
                methodVisitor.visitIntInsn(Opcodes.ALOAD, 0);
                methodVisitor.visitInsn(Opcodes.ACONST_NULL);
                methodVisitor.visitFieldInsn(Opcodes.PUTFIELD, clazz.getInternalName(), CREATION_THREAD,
                        THREAD_DESC);
            }

            @Override
            protected void onMethodExit(int opcode) {
                insertThreadEndedNotification();
            }

            @Override
            public void endMethod() {
                methodVisitor.visitLabel(end);

                // insert another threadEnded notification as a handler for Throwable
                Label handler = new Label();
                methodVisitor.visitLabel(handler);
                insertThreadEndedNotification();
                methodVisitor.visitInsn(Opcodes.ATHROW); // rethrow caught exception

                methodVisitor.visitTryCatchBlock(start, end, handler, ClassNames.THROWABLE_SLASH);
                methodVisitor.visitMaxs(0, 0);
            }

            void insertThreadEndedNotification() {
                Label skip = new Label();
                // insert:
                // if (_OT$isThreadStart) TeamThreadManager.threadEnded();
                methodVisitor.visitIntInsn(Opcodes.ILOAD, isThreadStartIdx);
                methodVisitor.visitJumpInsn(Opcodes.IFEQ, skip);
                methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, ClassNames.TEAM_THREAD_MANAGER_SLASH,
                        THREAD_ENDED, THREAD_ENDED_DESC, false);
                methodVisitor.visitLabel(skip);
            }
        };
    }
    return null;
}

From source file:org.eclipse.sisu.peaberry.internal.ImportGlue.java

License:Open Source License

@SuppressWarnings("PMD.ExcessiveMethodLength")
private static void wrap(final ClassWriter cw, final String proxyName, final Method method) {

    final String methodName = method.getName();

    final String descriptor = getMethodDescriptor(method);
    final String[] exceptions = getInternalNames(method.getExceptionTypes());

    // simple delegating proxy, so don't need synchronization on wrapper method
    final int modifiers = method.getModifiers() & ~(ABSTRACT | NATIVE | SYNCHRONIZED);

    final MethodVisitor v = cw.visitMethod(modifiers, methodName, descriptor, null, exceptions);

    final Label start = new Label();
    final Label invoke = new Label();
    final Label end = new Label();

    final Label ungetR = new Label();
    final Label finalR = new Label();
    final Label catchX = new Label();
    final Label ungetX = new Label();
    final Label finalX = new Label();

    v.visitCode();//from   w  w w  . java 2  s  .  c o m

    // support try{ get(); } finally { unget(); } model
    v.visitTryCatchBlock(start, ungetR, catchX, null);
    v.visitTryCatchBlock(ungetR, finalR, finalR, EXCEPTION_NAME);
    v.visitTryCatchBlock(ungetX, finalX, finalX, EXCEPTION_NAME);

    // store handle as "this"
    v.visitVarInsn(ALOAD, 0);
    v.visitFieldInsn(GETFIELD, proxyName, PROXY_HANDLE, IMPORT_DESC);
    v.visitInsn(DUP);
    v.visitVarInsn(ASTORE, 0);

    v.visitLabel(start);

    // dereference handle to get actual service instance
    v.visitMethodInsn(INVOKEINTERFACE, IMPORT_NAME, "get", "()" + OBJECT_DESC);
    v.visitInsn(DUP);

    // null => ServiceUnavailableException
    v.visitJumpInsn(IFNONNULL, invoke);
    v.visitTypeInsn(NEW, UNAVAILABLE_NAME);
    v.visitInsn(DUP);
    v.visitMethodInsn(INVOKESPECIAL, UNAVAILABLE_NAME, "<init>", "()V");
    v.visitInsn(ATHROW);

    v.visitLabel(invoke);

    final Class<?> clazz = method.getDeclaringClass();
    final String subjectName = getInternalName(clazz);

    if (!clazz.isInterface()) {
        v.visitTypeInsn(CHECKCAST, subjectName);
    }

    int i = 1;
    for (final Type t : getArgumentTypes(method)) {
        v.visitVarInsn(t.getOpcode(ILOAD), i);
        i = i + t.getSize();
    }

    // delegate to real method
    if (clazz.isInterface()) {
        v.visitMethodInsn(INVOKEINTERFACE, subjectName, methodName, descriptor);
    } else {
        v.visitMethodInsn(INVOKEVIRTUAL, subjectName, methodName, descriptor);
    }

    final Type returnType = getReturnType(method);

    if (VOID != returnType.getSort()) {
        v.visitVarInsn(returnType.getOpcode(ISTORE), 1);
    }

    v.visitLabel(ungetR);

    // unget on return
    v.visitVarInsn(ALOAD, 0);
    v.visitMethodInsn(INVOKEINTERFACE, IMPORT_NAME, "unget", VOID_DESC);
    v.visitInsn(ACONST_NULL);

    v.visitLabel(finalR);

    if (VOID != returnType.getSort()) {
        v.visitVarInsn(returnType.getOpcode(ILOAD), 1);
    }

    v.visitInsn(returnType.getOpcode(IRETURN));

    // cache initial exception
    v.visitLabel(catchX);
    v.visitVarInsn(ASTORE, 1);

    v.visitLabel(ungetX);

    // unget on exception
    v.visitVarInsn(ALOAD, 0);
    v.visitMethodInsn(INVOKEINTERFACE, IMPORT_NAME, "unget", VOID_DESC);
    v.visitInsn(ACONST_NULL);

    v.visitLabel(finalX);

    // restore initial exception
    v.visitVarInsn(ALOAD, 1);
    v.visitInsn(ATHROW);

    v.visitLabel(end);
    v.visitMaxs(0, 0);
    v.visitEnd();
}

From source file:org.enerj.enhancer.ClassEnhancer.java

License:Open Source License

/**
 * Generate the getfield/putfield replacement methods (enerj_Get_* and enerj_Set_*)
 * for persistent fields.//from w  w  w  .  j a  v  a  2s.c  o m
 * Parameters to the generated methods conveniently match the stack frame of
 * getfield and putfield.
 *
 * @param aField a Field for which the methods will be generated.
 */
private void emitPersistentFieldMediationMethods(Field aField) {
    int fieldScope = aField.getAccessModifiers() & (ACC_PRIVATE | ACC_PUBLIC | ACC_PROTECTED);
    String fieldName = aField.getName();
    String methodNameSuffix = getFieldMethodNameSuffix(mClassName, fieldName);
    String fieldType = aField.getDescriptor();
    int opcodeOffset = getOpcodeOffsetForDescriptor(fieldType);
    // TODO do we need to worry about fields with parameterized types? 
    //String genericSignature = Type.getDescriptor( aField.getGenericType() );

    MethodVisitor mv = cv.visitMethod(fieldScope | ACC_STATIC, FIELD_ACCESSOR_PREFIX + methodNameSuffix,
            '(' + mThisClassDescr + ')' + fieldType, null, null);
    Label label0 = new Label();
    mv.visitLabel(label0);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, mThisClassNameSlashed, "enerj_mLoaded", "Z");
    Label label1 = new Label();
    mv.visitJumpInsn(IFNE, label1);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, mThisClassNameSlashed, "enerj_mNew", "Z");
    mv.visitJumpInsn(IFNE, label1);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitInsn(ICONST_0);
    mv.visitMethodInsn(INVOKESTATIC, sPersistableHelperClassSlashed, "checkLoaded",
            "(Lorg/enerj/core/Persistable;Z)V");
    mv.visitLabel(label1);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, mThisClassNameSlashed, fieldName, fieldType);
    mv.visitInsn(getReturnOpcodeForDescriptor(fieldType));
    Label label3 = new Label();
    mv.visitLabel(label3);
    mv.visitLocalVariable("anInstance", mThisClassDescr, null, label0, label3, 0);
    mv.visitMaxs(0, 0);

    ///--------------
    // Mutator (Setter). Because of the == comparison, the method is a little different
    // for primitives, Strings (final class that implements equals() properly), and regular objects.

    mv = cv.visitMethod(fieldScope | ACC_STATIC, FIELD_MUTATOR_PREFIX + methodNameSuffix,
            '(' + mThisClassDescr + fieldType + ")V", null, null);
    mv.visitCode();

    // Check if checkLoaded needs to be called. Call if (!enerj_mLoaded && !enerj_mNew)
    Label mutatorStartLabel = new Label();
    mv.visitLabel(mutatorStartLabel);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, mThisClassNameSlashed, "enerj_mLoaded", "Z");
    Label mutatorLabel1 = new Label();
    mv.visitJumpInsn(IFNE, mutatorLabel1);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, mThisClassNameSlashed, "enerj_mNew", "Z");
    mv.visitJumpInsn(IFNE, mutatorLabel1);

    // Call checkLoaded
    mv.visitVarInsn(ALOAD, 0);
    mv.visitInsn(ICONST_1);
    mv.visitMethodInsn(INVOKESTATIC, sPersistableHelperClassSlashed, "checkLoaded",
            "(Lorg/enerj/core/Persistable;Z)V");
    mv.visitLabel(mutatorLabel1);

    // Check if the field's value is actually changing. For primitives, we use ==;
    // for special classes declared final (e.g., String, Integer), we use equals(); 
    // and for other objects we use == (identity).

    Label notModifiedLabel = new Label();

    if (MetaData.isPrimitive(fieldType)) {
        // Push parameter 1 - the new value
        mv.visitVarInsn(ILOAD + opcodeOffset, 1);
        // This
        mv.visitVarInsn(ALOAD, 0);
        // Current value
        mv.visitFieldInsn(GETFIELD, mThisClassNameSlashed, fieldName, fieldType);

        char type = fieldType.charAt(0);
        switch (type) {
        case 'B':
        case 'Z':
        case 'C':
        case 'S':
        case 'I':
            mv.visitJumpInsn(IF_ICMPEQ, notModifiedLabel);
            break;

        case 'F':
            mv.visitInsn(FCMPL);
            mv.visitJumpInsn(IFEQ, notModifiedLabel);
            break;

        case 'J':
            mv.visitInsn(LCMP);
            mv.visitJumpInsn(IFEQ, notModifiedLabel);
            break;

        case 'D':
            mv.visitInsn(DCMPL);
            mv.visitJumpInsn(IFEQ, notModifiedLabel);
            break;

        default:
            throw new RuntimeException("Unknown primitive type: " + type);
        }
    } else if (fieldType.equals("Ljava/lang/String;") || fieldType.equals("Ljava/lang/Integer;")
            || fieldType.equals("Ljava/lang/Long;") || fieldType.equals("Ljava/lang/Byte;")
            || fieldType.equals("Ljava/lang/Boolean;") || fieldType.equals("Ljava/lang/Character;")
            || fieldType.equals("Ljava/lang/Short;") || fieldType.equals("Ljava/lang/Float;")
            || fieldType.equals("Ljava/lang/Double;")) {

        // One of the core final immutable types. Use equals() to compare values, like this:
        // "if ((aValue == null{1} && anInstance.mString != null{2}) || (aValue != null{3} && !aValue.equals(anInstance.mString){4})" ...

        // {1}: aValue == null
        mv.visitVarInsn(ALOAD, 1);
        Label imEqualsLabel = new Label();
        mv.visitJumpInsn(IFNONNULL, imEqualsLabel);

        // {2}: anInstance.mString != null
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, mThisClassNameSlashed, fieldName, fieldType);
        Label imStoreLabel = new Label();
        mv.visitJumpInsn(IFNONNULL, imStoreLabel);

        // {3}: aValue != null
        mv.visitLabel(imEqualsLabel);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitJumpInsn(IFNULL, notModifiedLabel);

        // {4}: equals()...
        // Push parameter 1 - the new value
        mv.visitVarInsn(ALOAD, 1);
        // Current Value
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, mThisClassNameSlashed, fieldName, fieldType);
        // Compare !equals()
        mv.visitMethodInsn(INVOKEVIRTUAL, aField.getInternalName(), "equals", "(Ljava/lang/Object;)Z");
        mv.visitJumpInsn(IFNE, notModifiedLabel);

        mv.visitLabel(imStoreLabel);
    } else {
        // Some other Object -- use identity ==
        // Push parameter 1 - the new value
        mv.visitVarInsn(ALOAD, 1);
        // This
        mv.visitVarInsn(ALOAD, 0);
        // Current value
        mv.visitFieldInsn(GETFIELD, mThisClassNameSlashed, fieldName, fieldType);
        mv.visitJumpInsn(IF_ACMPEQ, notModifiedLabel);
    }

    // Store the value
    // Mark owner object as modified - short circuit if already marked modified
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, mThisClassNameSlashed, "enerj_mModified", "Z");
    Label mutatorLabel2 = new Label();
    mv.visitJumpInsn(IFNE, mutatorLabel2);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitMethodInsn(INVOKESTATIC, sPersistableHelperClassSlashed, "addModified", sPersistableVoidSignature);
    mv.visitLabel(mutatorLabel2);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitVarInsn(ILOAD + opcodeOffset, 1);
    mv.visitFieldInsn(PUTFIELD, mThisClassNameSlashed, fieldName, fieldType);
    mv.visitLabel(notModifiedLabel);
    mv.visitInsn(RETURN);

    Label mutatorEndlabel = new Label();
    mv.visitLabel(mutatorEndlabel);
    mv.visitLocalVariable("anInstance", mThisClassDescr, null, mutatorStartLabel, mutatorEndlabel, 0);
    mv.visitLocalVariable("aValue", fieldType, null, mutatorStartLabel, mutatorEndlabel, 1);
    mv.visitMaxs(0, 0);
    mv.visitEnd();
}

From source file:org.enerj.enhancer.ClassEnhancer.java

License:Open Source License

/**
 * Generate the getfield/putfield replacement methods (enerj_Get_* and enerj_Set_*)
 * for non-static transient fields./* w  w w  .ja v  a2 s  .c om*/
 * Parameters to the generated methods conveniently match the stack frame of
 * getfield and putfield.
 *
 * @param aField a Field for which the methods will be generated.
 */
private void emitTransientFieldMediationMethods(Field aField) {
    int fieldScope = aField.getAccessModifiers() & (ACC_PRIVATE | ACC_PUBLIC | ACC_PROTECTED);
    String fieldName = aField.getName();
    String methodNameSuffix = getFieldMethodNameSuffix(mClassName, fieldName);
    String fieldType = aField.getDescriptor();

    // Accessor (Getter).
    MethodVisitor mv = cv.visitMethod(fieldScope | ACC_STATIC, FIELD_ACCESSOR_PREFIX + methodNameSuffix,
            '(' + mThisClassDescr + ')' + fieldType, null, null);
    mv.visitCode();
    Label startLabel = new Label();
    mv.visitLabel(startLabel);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, mThisClassNameSlashed, fieldName, fieldType);
    mv.visitInsn(getReturnOpcodeForDescriptor(fieldType));
    Label endLabel = new Label();
    mv.visitLabel(endLabel);
    mv.visitLocalVariable("anInstance", mThisClassDescr, null, startLabel, endLabel, 0);
    mv.visitMaxs(0, 0);
    mv.visitEnd();

    // Mutator (Setter).
    mv = cv.visitMethod(fieldScope | ACC_STATIC, FIELD_MUTATOR_PREFIX + methodNameSuffix,
            '(' + mThisClassDescr + fieldType + ")V", null, null);
    mv.visitCode();
    startLabel = new Label();
    mv.visitLabel(startLabel);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitVarInsn(getLoadOpcodeForDescriptor(fieldType), 1);
    mv.visitFieldInsn(PUTFIELD, mThisClassNameSlashed, fieldName, fieldType);
    mv.visitInsn(RETURN);
    endLabel = new Label();
    mv.visitLabel(endLabel);
    mv.visitLocalVariable("anInstance", mThisClassDescr, null, startLabel, endLabel, 0);
    mv.visitLocalVariable("aValue", fieldType, null, startLabel, endLabel, 1);
    mv.visitMaxs(0, 0);
    mv.visitEnd();
}

From source file:org.enerj.enhancer.ClassEnhancer.java

License:Open Source License

/**
 * Generate the getstatic/putstatic replacement methods (enerj_Get_* and enerj_Set_*)
 * for static transient fields. //from   w  w w  .  j  a v  a  2  s .c  o  m
 * Parameters to the generated methods conveniently match the stack frame of
 * getstatic and putstatic.
 *
 * @param aField a Field for which the methods will be generated.
 */
private void emitStaticFieldMediationMethods(Field aField) {
    int fieldScope = aField.getAccessModifiers() & (ACC_PRIVATE | ACC_PUBLIC | ACC_PROTECTED);
    String fieldName = aField.getName();
    String methodNameSuffix = getFieldMethodNameSuffix(mClassName, fieldName);
    String fieldType = aField.getDescriptor();

    // Accessor (Getter).
    MethodVisitor mv = cv.visitMethod(fieldScope | ACC_STATIC, FIELD_ACCESSOR_PREFIX + methodNameSuffix,
            "()" + fieldType, null, null);
    mv.visitCode();
    mv.visitFieldInsn(GETSTATIC, mThisClassNameSlashed, fieldName, fieldType);
    mv.visitInsn(getReturnOpcodeForDescriptor(fieldType));
    mv.visitMaxs(0, 0);
    mv.visitEnd();

    // Mutator (Setter).
    mv = cv.visitMethod(fieldScope | ACC_STATIC, FIELD_MUTATOR_PREFIX + methodNameSuffix,
            '(' + fieldType + ")V", null, null);
    mv.visitCode();
    Label startLabel = new Label();
    mv.visitLabel(startLabel);
    mv.visitVarInsn(getLoadOpcodeForDescriptor(fieldType), 0);
    mv.visitFieldInsn(PUTSTATIC, mThisClassNameSlashed, fieldName, fieldType);
    mv.visitInsn(RETURN);
    Label endLabel = new Label();
    mv.visitLabel(endLabel);
    mv.visitLocalVariable("aValue", fieldType, null, startLabel, endLabel, 0);
    mv.visitMaxs(0, 0);
    mv.visitEnd();
}

From source file:org.enerj.enhancer.ClassEnhancer.java

License:Open Source License

/**
 * Emit the special clone() method on a top-level persistable. This is
 * generated when a top-level Persistable doesn't have a clone method.
 * It ensures initPersistableClone is called if a sub-class implements clone().
 *//*from   w  ww .  ja v  a  2 s.  c om*/
private void emitClone() {
    // TODO Only add this exception if superclass throws it. Object does, while java.util.Date does not.
    // TODO Either that or never throw it and wrap the super.clone() in a try/catch.
    // TODO catch part should never happen. If it does, return null.
    String[] exceptions = new String[] { "java/lang/CloneNotSupportedException" };
    MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "clone", "()Ljava/lang/Object;", null, exceptions);

    mv.visitCode();
    Label startLabel = new Label();
    mv.visitLabel(startLabel);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitMethodInsn(INVOKESPECIAL, mSuperClassNameSlashed, "clone", "()Ljava/lang/Object;");
    mv.visitInsn(DUP);
    mv.visitTypeInsn(CHECKCAST, sPersistableClassSlashed);
    mv.visitMethodInsn(INVOKESTATIC, sPersistableHelperClassSlashed, "initPersistableClone",
            sPersistableVoidSignature);
    mv.visitInsn(ARETURN);
    Label endLabel = new Label();
    mv.visitLabel(endLabel);

    mv.visitLocalVariable("this", mThisClassDescr, null, startLabel, endLabel, 0);
    mv.visitMaxs(0, 0);
    mv.visitEnd();
}