Example usage for org.objectweb.asm MethodVisitor visitVarInsn

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

Introduction

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

Prototype

public void visitVarInsn(final int opcode, final int var) 

Source Link

Document

Visits a local variable instruction.

Usage

From source file:com.google.code.jconts.instrument.gen.ComputationClassGenerator.java

License:Apache License

private void generateConstructor(ClassVisitor cv) {
    final String name = info.computationClassName;
    final Type outerType = Type.getObjectType(info.owner);

    // Constructor have form either <init>(OuterClass this$0, State state)
    // or <init>(State state)
    String ctorDesc;/*from w  w w  .  j  a  v a  2 s .  co m*/
    if (info.isStatic()) {
        ctorDesc = Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { info.stateType });
    } else {
        cv.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL, "this$0", 'L' + info.owner + ';', null, null);

        ctorDesc = Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { outerType, info.stateType });
    }

    // Generate constructor
    MethodVisitor mv = cv.visitMethod(0, CTOR_NAME, ctorDesc, null, null);
    mv.visitCode();
    Label start = new Label();
    Label end = new Label();
    mv.visitLabel(start);

    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, OBJECT_NAME, CTOR_NAME, DEFAULT_CTOR_DESC);

    // Save state field
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitVarInsn(Opcodes.ALOAD, 1 + info.thisOffset);
    mv.visitFieldInsn(Opcodes.PUTFIELD, name, "state", stateDesc);

    // Save outer this
    if (!info.isStatic()) {
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitVarInsn(Opcodes.ALOAD, 1);
        mv.visitFieldInsn(Opcodes.PUTFIELD, name, "this$0", outerType.getDescriptor());
    }
    mv.visitInsn(Opcodes.RETURN);
    mv.visitLabel(end);

    mv.visitLocalVariable("this", 'L' + name + ';', signature, start, end, 0);
    if (!info.isStatic()) {
        mv.visitLocalVariable("this$0", outerType.getDescriptor(), null, start, end, 1);
    }
    mv.visitLocalVariable("state", stateDesc, null, start, end, 1 + info.thisOffset);

    mv.visitMaxs(2, 2 + info.thisOffset);
    mv.visitEnd();
}

From source file:com.google.code.jconts.instrument.gen.ComputationClassGenerator.java

License:Apache License

private void generateExecute(ClassVisitor cv) {
    final String name = info.computationClassName;
    final Type outerType = Type.getObjectType(info.owner);

    // Generate execute(Continuation<T> cont);
    MethodVisitor mv = cv.visitMethod(Opcodes.ACC_FINAL | Opcodes.ACC_PUBLIC, COMPUTATION_EXECUTE_NAME,
            COMPUTATION_EXECUTE_DESC, executeSignature(), null);
    mv.visitCode();/*from w ww . j  av  a  2  s .  com*/
    Label start = new Label();
    Label end = new Label();
    mv.visitLabel(start);

    // Load outer this
    if (!info.isStatic()) {
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitFieldInsn(Opcodes.GETFIELD, name, "this$0", outerType.getDescriptor());
    }

    // Load state field
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitFieldInsn(Opcodes.GETFIELD, name, "state", stateDesc);

    // state.continuation = continuation
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitFieldInsn(Opcodes.GETFIELD, name, "state", stateDesc);
    mv.visitVarInsn(Opcodes.ALOAD, 1);
    mv.visitFieldInsn(Opcodes.PUTFIELD, info.stateClassName, CONTINUATION_FIELD, CONTINUATION_DESC);

    // Initial state (0)
    mv.visitIntInsn(Opcodes.BIPUSH, 0);
    mv.visitMethodInsn(info.isStatic() ? Opcodes.INVOKESTATIC : Opcodes.INVOKEVIRTUAL, info.owner,
            info.name + "$async",
            Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { info.stateType, Type.INT_TYPE }));

    mv.visitInsn(Opcodes.RETURN);
    mv.visitLabel(end);

    mv.visitLocalVariable("this", 'L' + name + ';', signature, start, end, 0);
    if (!info.isStatic()) {
        mv.visitLocalVariable("this$0", outerType.getDescriptor(), null, start, end, 1);
    }

    SignatureWriter sign = new SignatureWriter();
    contSignature(sign);
    mv.visitLocalVariable("continuation", CONTINUATION_DESC, sign.toString(), start, end, 1 + info.thisOffset);

    mv.visitMaxs(3 + info.thisOffset, 2 + info.thisOffset);
    mv.visitEnd();
}

From source file:com.google.code.jconts.instrument.gen.ContinuationClassGenerator.java

License:Apache License

private void generateConstructor(ClassVisitor cv) {
    final String name = info.continuationClassName;
    final Type outerType = Type.getObjectType(info.owner);

    // Constructor have form either <init>(OuterClass this$0, State state,
    // int index)
    // or <init>(State state, int index)
    String ctorDesc;/*from  w w  w  .  ja  v  a2 s .c o m*/
    if (info.isStatic()) {
        ctorDesc = Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { info.stateType, Type.INT_TYPE });
    } else {
        cv.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL, "this$0", 'L' + info.owner + ';', null, null);

        ctorDesc = Type.getMethodDescriptor(Type.VOID_TYPE,
                new Type[] { outerType, info.stateType, Type.INT_TYPE });
    }

    // Generate constructor
    MethodVisitor mv = cv.visitMethod(0, CTOR_NAME, ctorDesc, null, null);
    mv.visitCode();
    Label start = new Label();
    Label end = new Label();
    mv.visitLabel(start);

    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, OBJECT_NAME, CTOR_NAME, DEFAULT_CTOR_DESC);

    // Save state field
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitVarInsn(Opcodes.ALOAD, 1 + info.thisOffset);
    mv.visitFieldInsn(Opcodes.PUTFIELD, name, "state", stateDesc);

    // Save index field
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitVarInsn(Opcodes.ILOAD, 2 + info.thisOffset);
    mv.visitFieldInsn(Opcodes.PUTFIELD, name, "index", "I");

    // Save outer this
    if (!info.isStatic()) {
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitVarInsn(Opcodes.ALOAD, 1);
        mv.visitFieldInsn(Opcodes.PUTFIELD, name, "this$0", outerType.getDescriptor());
    }
    mv.visitInsn(Opcodes.RETURN);
    mv.visitLabel(end);

    mv.visitLocalVariable("this", 'L' + name + ';', signature, start, end, 0);
    if (!info.isStatic()) {
        mv.visitLocalVariable("this$0", outerType.getDescriptor(), null, start, end, 1);
    }
    mv.visitLocalVariable("state", stateDesc, null, start, end, 1 + info.thisOffset);
    mv.visitLocalVariable("index", "I", null, start, end, 2 + info.thisOffset);

    mv.visitMaxs(2, 3 + info.thisOffset);
    mv.visitEnd();
}

From source file:com.google.code.jconts.instrument.gen.ContinuationClassGenerator.java

License:Apache License

private void generateExecute(ClassVisitor cv, boolean execute) {
    final String name = info.continuationClassName;
    final Type outerType = Type.getObjectType(info.owner);

    // Generate invoke(T result);
    String signature = null;//from   w ww. ja  va  2 s.  com
    if (execute) {
        SignatureWriter sign = new SignatureWriter();
        sign.visitParameterType().visitTypeVariable("T");
        sign.visitReturnType().visitBaseType('V'); // void
        signature = sign.toString();
    }
    MethodVisitor mv = cv.visitMethod(Opcodes.ACC_FINAL | Opcodes.ACC_PUBLIC,
            execute ? CONTINUATION_INVOKE_NAME : CONTINUATION_SET_EXCEPTION_NAME,
            execute ? CONTINUATION_INVOKE_DESC : CONTINUATION_SET_EXCEPTION_DESC, signature, null);
    mv.visitCode();
    Label start = new Label();
    Label end = new Label();
    mv.visitLabel(start);

    // Load outer this
    if (!info.isStatic()) {
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitFieldInsn(Opcodes.GETFIELD, name, "this$0", outerType.getDescriptor());
    }

    // state.result = result or state.exception = throwable
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitFieldInsn(Opcodes.GETFIELD, name, "state", stateDesc);
    mv.visitVarInsn(Opcodes.ALOAD, 1);
    mv.visitFieldInsn(Opcodes.PUTFIELD, info.stateClassName, execute ? "result" : "exception",
            execute ? OBJECT_DESC : THROWABLE_DESC);

    // Load state field
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitFieldInsn(Opcodes.GETFIELD, name, "state", stateDesc);

    // Continue from this index or index+1 (for exception)
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitFieldInsn(Opcodes.GETFIELD, name, "index", "I");
    if (!execute) {
        mv.visitInsn(Opcodes.ICONST_1);
        mv.visitInsn(Opcodes.IADD);
    }

    mv.visitMethodInsn(info.isStatic() ? Opcodes.INVOKESTATIC : Opcodes.INVOKEVIRTUAL, info.owner,
            info.name + "$async",
            Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { info.stateType, Type.INT_TYPE }));

    mv.visitInsn(Opcodes.RETURN);
    mv.visitLabel(end);

    mv.visitLocalVariable("this", 'L' + name + ';', signature, start, end, 0);
    if (!info.isStatic()) {
        mv.visitLocalVariable("this$0", outerType.getDescriptor(), null, start, end, 1);
    }
    mv.visitLocalVariable("result", OBJECT_DESC, "TT;", start, end, 1 + info.thisOffset);

    mv.visitMaxs(3 + info.thisOffset + (execute ? 0 : 1), 2 + info.thisOffset);
    mv.visitEnd();
}

From source file:com.google.code.jconts.instrument.gen.StateClassGenerator.java

License:Apache License

public void accept(TransformationContext context) {
    ClassVisitor cv = context.writer();/*from ww w .ja  v a2  s  .c o m*/

    final String name = info.stateClassName;

    cv.visit(Opcodes.V1_6, Opcodes.ACC_FINAL /*| Opcodes.ACC_SYNTHETIC*/, name, null, OBJECT_NAME, null);

    cv.visitSource(info.ownerSource, null);
    cv.visitOuterClass(info.owner, null, null);

    cv.visitField(0/*Opcodes.ACC_SYNTHETIC*/, CONTINUATION_FIELD, CONTINUATION_DESC,
            'L' + CONTINUATION_NAME + '<' + info.valueSignature + ">;", null);

    // Local variables state
    List<String> names = info.tracker.getFieldNames();
    List<Type> types = info.tracker.getFieldTypes();
    for (int i = 0; i < names.size(); ++i) {
        cv.visitField(0/*Opcodes.ACC_SYNTHETIC*/, names.get(i), types.get(i).getDescriptor(), null, null);
    }

    // Return value variable
    cv.visitField(0/*Opcodes.ACC_SYNTHETIC*/, "result", OBJECT_DESC, null, null);
    cv.visitField(0/*Opcodes.ACC_SYNTHETIC*/, "exception", THROWABLE_DESC, null, null);

    // Generate constructor
    MethodVisitor mv = cv.visitMethod(0, CTOR_NAME, DEFAULT_CTOR_DESC, null, null);
    mv.visitCode();
    Label start = new Label();
    Label end = new Label();
    mv.visitLabel(start);
    mv.visitLineNumber(0, start);

    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, OBJECT_NAME, CTOR_NAME, DEFAULT_CTOR_DESC);
    mv.visitInsn(Opcodes.RETURN);
    mv.visitLabel(end);

    mv.visitLocalVariable("this", 'L' + name + ';', null, start, end, 0);

    mv.visitMaxs(1, 1);
    mv.visitEnd();

    cv.visitEnd();
}

From source file:com.google.code.jconts.instrument.gen.TramplineMethodGenerator.java

License:Apache License

public void accept(ClassVisitor cv) {
    MethodVisitor mv = cv.visitMethod(info.access, info.name, info.desc, info.signature, info.exceptions);
    mv.visitCode();/* w ww .j  a va 2 s . co  m*/
    mv.visitTypeInsn(Opcodes.NEW, info.computationClassName);
    mv.visitInsn(Opcodes.DUP);

    // "this' for new Computation(this, state)
    if (!info.isStatic()) {
        mv.visitVarInsn(Opcodes.ALOAD, 0);
    }

    // new State()
    mv.visitTypeInsn(Opcodes.NEW, info.stateClassName);
    mv.visitInsn(Opcodes.DUP);
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, info.stateClassName, CTOR_NAME, DEFAULT_CTOR_DESC);

    // state.varX = argX
    String[] names = info.entryLocalsVars;
    for (int i = 0; i < info.entryLocals.length; ++i) {
        mv.visitInsn(Opcodes.DUP);
        mv.visitVarInsn(info.entryLocals[i].getOpcode(Opcodes.ILOAD), i + info.thisOffset);
        mv.visitFieldInsn(Opcodes.PUTFIELD, info.stateClassName, names[i], info.entryLocals[i].getDescriptor());
    }

    // new Computation(this, state);
    String ctorDesc;
    if (info.isStatic()) {
        ctorDesc = Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { info.stateType });
    } else {
        ctorDesc = Type.getMethodDescriptor(Type.VOID_TYPE,
                new Type[] { Type.getObjectType(info.owner), info.stateType });
    }
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, info.computationClassName, CTOR_NAME, ctorDesc);

    mv.visitInsn(Opcodes.ARETURN);
    mv.visitMaxs(info.isStatic() ? 5 : 6,
            info.isStatic() ? info.entryLocals.length : info.entryLocals.length + 1);
    mv.visitEnd();
}

From source file:com.google.devtools.build.android.desugar.Bug62060793TestDataGenerator.java

License:Open Source License

private static byte[] createClass() {
    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    MethodVisitor mv;
    cw.visit(V1_8, ACC_PUBLIC | ACC_SUPER, CLASS_NAME, null, "java/lang/Object", null);

    cw.visitInnerClass(INTERFACE_TYPE_NAME, CLASS_NAME, "Interface",
            ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE);

    cw.visitInnerClass("java/lang/invoke/MethodHandles$Lookup", "java/lang/invoke/MethodHandles", "Lookup",
            ACC_PUBLIC | ACC_FINAL | ACC_STATIC);

    {/*from www  .  j  ava  2 s . c  om*/
        mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
        mv.visitCode();
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
        mv.visitInsn(RETURN);
        mv.visitEnd();
    }
    {
        mv = cw.visitMethod(ACC_PRIVATE | ACC_STATIC, "method", "(Ljava/lang/String;)Ljava/lang/String;", null,
                null);
        mv.visitParameter("str", 0);
        mv.visitCode();
        mv.visitVarInsn(ALOAD, 0);
        mv.visitInsn(ARETURN);
        mv.visitEnd();
    }
    {
        mv = cw.visitMethod(ACC_PRIVATE | ACC_STATIC, "method",
                "(ZCBFDJISLjava/lang/Object;[Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/String;", null,
                null);
        mv.visitParameter("bool", 0);
        mv.visitParameter("c", 0);
        mv.visitParameter("b", 0);
        mv.visitParameter("f", 0);
        mv.visitParameter("d", 0);
        mv.visitParameter("l", 0);
        mv.visitParameter("i", 0);
        mv.visitParameter("s", 0);
        mv.visitParameter("o", 0);
        mv.visitParameter("array", 0);
        mv.visitParameter("str", 0);
        mv.visitCode();
        mv.visitVarInsn(ALOAD, 10);
        mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf",
                "(Ljava/lang/Object;)Ljava/lang/String;", false);
        mv.visitVarInsn(ASTORE, 13);
        mv.visitVarInsn(ALOAD, 11);
        Label l0 = new Label();
        mv.visitJumpInsn(IFNONNULL, l0);
        mv.visitInsn(ICONST_1);
        Label l1 = new Label();
        mv.visitJumpInsn(GOTO, l1);
        mv.visitLabel(l0);
        mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] { "java/lang/String" }, 0, null);
        mv.visitInsn(ICONST_0);
        mv.visitLabel(l1);
        mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { Opcodes.INTEGER });
        mv.visitVarInsn(ISTORE, 14);
        mv.visitIntInsn(BIPUSH, 91);
        mv.visitVarInsn(ALOAD, 12);
        mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf",
                "(Ljava/lang/Object;)Ljava/lang/String;", false);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "length", "()I", false);
        mv.visitInsn(IADD);
        mv.visitVarInsn(ALOAD, 13);
        mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf",
                "(Ljava/lang/Object;)Ljava/lang/String;", false);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "length", "()I", false);
        mv.visitInsn(IADD);
        mv.visitTypeInsn(NEW, "java/lang/StringBuilder");
        mv.visitInsn(DUP_X1);
        mv.visitInsn(SWAP);
        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "(I)V", false);
        mv.visitVarInsn(ALOAD, 12);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
                "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false);
        mv.visitVarInsn(ILOAD, 0);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Z)Ljava/lang/StringBuilder;",
                false);
        mv.visitVarInsn(ILOAD, 1);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(C)Ljava/lang/StringBuilder;",
                false);
        mv.visitVarInsn(ILOAD, 2);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(I)Ljava/lang/StringBuilder;",
                false);
        mv.visitVarInsn(FLOAD, 3);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(F)Ljava/lang/StringBuilder;",
                false);
        mv.visitVarInsn(DLOAD, 4);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(D)Ljava/lang/StringBuilder;",
                false);
        mv.visitVarInsn(LLOAD, 6);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(J)Ljava/lang/StringBuilder;",
                false);
        mv.visitVarInsn(ILOAD, 8);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(I)Ljava/lang/StringBuilder;",
                false);
        mv.visitVarInsn(ILOAD, 9);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(I)Ljava/lang/StringBuilder;",
                false);
        mv.visitVarInsn(ALOAD, 13);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
                "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false);
        mv.visitVarInsn(ILOAD, 14);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Z)Ljava/lang/StringBuilder;",
                false);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false);
        mv.visitInsn(ARETURN);
        mv.visitEnd();
    }
    {
        mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "lambdaWithConstantArguments",
                "()L" + INTERFACE_TYPE_NAME + ";", null, null);
        mv.visitCode();
        mv.visitInsn(ICONST_0);
        mv.visitInsn(ICONST_1);
        mv.visitInsn(ICONST_2);
        mv.visitInsn(FCONST_0);
        mv.visitInsn(DCONST_0);
        mv.visitInsn(LCONST_0);
        mv.visitInsn(ICONST_4);
        mv.visitIntInsn(SIPUSH, 9);
        mv.visitInsn(ACONST_NULL);
        mv.visitInsn(ACONST_NULL);
        mv.visitInvokeDynamicInsn("call",
                "(ZCBFDJISLjava/lang/Object;[Ljava/lang/Object;)L" + INTERFACE_TYPE_NAME + ";",
                new Handle(Opcodes.H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", "metafactory",
                        "(Ljava/lang/invoke/MethodHandles$Lookup;"
                                + "Ljava/lang/String;Ljava/lang/invoke/MethodType;"
                                + "Ljava/lang/invoke/MethodType;" + "Ljava/lang/invoke/MethodHandle;"
                                + "Ljava/lang/invoke/MethodType;" + ")Ljava/lang/invoke/CallSite;",
                        false),
                new Object[] { Type.getType("(Ljava/lang/String;)Ljava/lang/String;"),
                        new Handle(Opcodes.H_INVOKESTATIC, CLASS_NAME, "method",
                                "(ZCBFDJISLjava/lang/Object;[Ljava/lang/Object;Ljava/lang/String;"
                                        + ")Ljava/lang/String;",
                                false),
                        Type.getType("(Ljava/lang/String;)Ljava/lang/String;") });
        mv.visitInsn(ARETURN);
        mv.visitEnd();
    }

    cw.visitEnd();

    return cw.toByteArray();
}

From source file:com.google.devtools.build.android.desugar.CoreLibrarySupport.java

License:Open Source License

private void makeDispatchHelperMethod(ClassVisitor helper, EmulatedMethod method,
        ImmutableList<Class<?>> typechecks) {
    checkArgument(method.owner().isInterface());
    String owner = method.owner().getName().replace('.', '/');
    Type methodType = Type.getMethodType(method.descriptor());
    String companionDesc = InterfaceDesugaring.companionDefaultMethodDescriptor(owner, method.descriptor());
    MethodVisitor dispatchMethod = helper.visitMethod(method.access() | Opcodes.ACC_STATIC, method.name(),
            companionDesc, /*signature=*/ null, // signature is invalid due to extra "receiver" argument
            method.exceptions().toArray(EMPTY_LIST));

    dispatchMethod.visitCode();//from ww w.  j  a  v  a2 s  .  c o  m
    {
        // See if the receiver might come with its own implementation of the method, and call it.
        // We do this by testing for the interface type created by EmulatedInterfaceRewriter
        Label fallthrough = new Label();
        String emulationInterface = renameCoreLibrary(owner);
        dispatchMethod.visitVarInsn(Opcodes.ALOAD, 0); // load "receiver"
        dispatchMethod.visitTypeInsn(Opcodes.INSTANCEOF, emulationInterface);
        dispatchMethod.visitJumpInsn(Opcodes.IFEQ, fallthrough);
        dispatchMethod.visitVarInsn(Opcodes.ALOAD, 0); // load "receiver"
        dispatchMethod.visitTypeInsn(Opcodes.CHECKCAST, emulationInterface);

        visitLoadArgs(dispatchMethod, methodType, 1 /* receiver already loaded above */);
        dispatchMethod.visitMethodInsn(Opcodes.INVOKEINTERFACE, emulationInterface, method.name(),
                method.descriptor(), /*itf=*/ true);
        dispatchMethod.visitInsn(methodType.getReturnType().getOpcode(Opcodes.IRETURN));

        dispatchMethod.visitLabel(fallthrough);
        // Trivial frame for the branch target: same empty stack as before
        dispatchMethod.visitFrame(Opcodes.F_SAME, 0, EMPTY_FRAME, 0, EMPTY_FRAME);
    }

    // Next, check for subtypes with specialized implementations and call them
    for (Class<?> tested : typechecks) {
        Label fallthrough = new Label();
        String testedName = tested.getName().replace('.', '/');
        // In case of a class this must be a member move; for interfaces use the companion.
        String target = tested.isInterface() ? InterfaceDesugaring.getCompanionClassName(testedName)
                : checkNotNull(memberMoves.get(rewriter.unprefix(testedName) + '#' + method.name()));
        dispatchMethod.visitVarInsn(Opcodes.ALOAD, 0); // load "receiver"
        dispatchMethod.visitTypeInsn(Opcodes.INSTANCEOF, testedName);
        dispatchMethod.visitJumpInsn(Opcodes.IFEQ, fallthrough);
        dispatchMethod.visitVarInsn(Opcodes.ALOAD, 0); // load "receiver"
        dispatchMethod.visitTypeInsn(Opcodes.CHECKCAST, testedName); // make verifier happy

        visitLoadArgs(dispatchMethod, methodType, 1 /* receiver already loaded above */);
        dispatchMethod.visitMethodInsn(Opcodes.INVOKESTATIC, target, method.name(),
                InterfaceDesugaring.companionDefaultMethodDescriptor(testedName, method.descriptor()),
                /*itf=*/ false);
        dispatchMethod.visitInsn(methodType.getReturnType().getOpcode(Opcodes.IRETURN));

        dispatchMethod.visitLabel(fallthrough);
        // Trivial frame for the branch target: same empty stack as before
        dispatchMethod.visitFrame(Opcodes.F_SAME, 0, EMPTY_FRAME, 0, EMPTY_FRAME);
    }

    // Call static type's default implementation in companion class
    dispatchMethod.visitVarInsn(Opcodes.ALOAD, 0); // load "receiver"
    visitLoadArgs(dispatchMethod, methodType, 1 /* receiver already loaded above */);
    dispatchMethod.visitMethodInsn(Opcodes.INVOKESTATIC, InterfaceDesugaring.getCompanionClassName(owner),
            method.name(), companionDesc, /*itf=*/ false);
    dispatchMethod.visitInsn(methodType.getReturnType().getOpcode(Opcodes.IRETURN));

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

From source file:com.google.devtools.build.android.desugar.CoreLibrarySupport.java

License:Open Source License

/**
 * Emits instructions to load a method's parameters as arguments of a method call assumed to have
 * compatible descriptor, starting at the given local variable slot.
 *//* w  ww. j av a 2 s  . c  o m*/
private static void visitLoadArgs(MethodVisitor dispatchMethod, Type neededType, int slot) {
    for (Type arg : neededType.getArgumentTypes()) {
        dispatchMethod.visitVarInsn(arg.getOpcode(Opcodes.ILOAD), slot);
        slot += arg.getSize();
    }
}

From source file:com.google.devtools.build.android.desugar.LambdaDesugaring.java

License:Open Source License

@Override
public void visitEnd() {
    for (Map.Entry<Handle, MethodReferenceBridgeInfo> bridge : bridgeMethods.entrySet()) {
        Handle original = bridge.getKey();
        Handle neededMethod = bridge.getValue().bridgeMethod();
        checkState(//from  w ww . j a  v a  2s  .c  o  m
                neededMethod.getTag() == Opcodes.H_INVOKESTATIC
                        || neededMethod.getTag() == Opcodes.H_INVOKEVIRTUAL,
                "Cannot generate bridge method %s to reach %s", neededMethod, original);
        checkState(bridge.getValue().referenced() != null, "Need referenced method %s to generate bridge %s",
                original, neededMethod);

        int access = Opcodes.ACC_BRIDGE | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_FINAL;
        if (neededMethod.getTag() == Opcodes.H_INVOKESTATIC) {
            access |= Opcodes.ACC_STATIC;
        }
        MethodVisitor bridgeMethod = super.visitMethod(access, neededMethod.getName(), neededMethod.getDesc(),
                (String) null, toInternalNames(bridge.getValue().referenced().getExceptionTypes()));

        // Bridge is a factory method calling a constructor
        if (original.getTag() == Opcodes.H_NEWINVOKESPECIAL) {
            bridgeMethod.visitTypeInsn(Opcodes.NEW, original.getOwner());
            bridgeMethod.visitInsn(Opcodes.DUP);
        }

        int slot = 0;
        if (neededMethod.getTag() != Opcodes.H_INVOKESTATIC) {
            bridgeMethod.visitVarInsn(Opcodes.ALOAD, slot++);
        }
        Type neededType = Type.getMethodType(neededMethod.getDesc());
        for (Type arg : neededType.getArgumentTypes()) {
            bridgeMethod.visitVarInsn(arg.getOpcode(Opcodes.ILOAD), slot);
            slot += arg.getSize();
        }
        bridgeMethod.visitMethodInsn(invokeOpcode(original), original.getOwner(), original.getName(),
                original.getDesc(), original.isInterface());
        bridgeMethod.visitInsn(neededType.getReturnType().getOpcode(Opcodes.IRETURN));

        bridgeMethod.visitMaxs(0, 0); // rely on class writer to compute these
        bridgeMethod.visitEnd();
    }
    super.visitEnd();
}