Search in sources :

Example 6 with Handle

use of org.objectweb.asm.Handle in project es6draft by anba.

the class SimpleTypeTextifier method visitInvokeDynamicInsn.

@Override
public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) {
    buf.setLength(0);
    buf.append(tab2).append("INVOKEDYNAMIC").append(' ').append(name);
    appendDescriptor(METHOD_DESCRIPTOR, desc);
    if (bsmArgs.length != 0) {
        buf.append(" [");
        for (int i = 0; i < bsmArgs.length; ++i) {
            Object arg = bsmArgs[i];
            if (arg instanceof String) {
                appendString(buf, (String) arg);
            } else if (arg instanceof Type) {
                Type type = (Type) arg;
                if (type.getSort() == Type.METHOD) {
                    appendDescriptor(METHOD_DESCRIPTOR, type.getDescriptor());
                } else {
                    appendDescriptor(INTERNAL_NAME, type.getDescriptor());
                }
            } else if (arg instanceof Handle) {
                Handle handle = (Handle) arg;
                appendDescriptor(HANDLE_DESCRIPTOR, getMethodDescriptor(handle.getDesc()));
            } else {
                buf.append(arg);
            }
            if (i + 1 < bsmArgs.length) {
                buf.append(", ");
            }
        }
        buf.append("]");
    }
    buf.append("\n");
    text.add(buf.toString());
}
Also used : Type(org.objectweb.asm.Type) Handle(org.objectweb.asm.Handle)

Example 7 with Handle

use of org.objectweb.asm.Handle in project bazel by bazelbuild.

the class LambdaDesugaring method queueUpBridgeMethodIfNeeded.

/**
   * Makes {@link #visitEnd} generate a bridge method for the given method handle if the
   * referenced method will be invisible to the generated lambda class.
   *
   * @return struct containing either {@code invokedMethod} or {@code invokedMethod} and a handle
   *     representing the bridge method that will be generated for {@code invokedMethod}.
   */
private MethodReferenceBridgeInfo queueUpBridgeMethodIfNeeded(Handle invokedMethod) throws ClassNotFoundException {
    if (invokedMethod.getName().startsWith("lambda$")) {
        // We adjust lambda bodies to be visible
        return MethodReferenceBridgeInfo.noBridge(invokedMethod);
    }
    // invokedMethod is a method reference if we get here
    Executable invoked = findTargetMethod(invokedMethod);
    if (isVisibleToLambdaClass(invoked, invokedMethod.getOwner())) {
        // Referenced method is visible to the generated class, so nothing to do
        return MethodReferenceBridgeInfo.noBridge(invokedMethod);
    }
    // We need a bridge method if we get here
    checkState(!isInterface, "%s is an interface and shouldn't need bridge to %s", internalName, invokedMethod);
    checkState(!invokedMethod.isInterface(), "%s's lambda classes can't see interface method: %s", internalName, invokedMethod);
    MethodReferenceBridgeInfo result = bridgeMethods.get(invokedMethod);
    if (result != null) {
        // we're already queued up a bridge method for this method reference
        return result;
    }
    String name = uniqueInPackage(internalName, "bridge$lambda$" + bridgeMethods.size());
    Handle bridgeMethod;
    switch(invokedMethod.getTag()) {
        case Opcodes.H_INVOKESTATIC:
            bridgeMethod = new Handle(invokedMethod.getTag(), internalName, name, invokedMethod.getDesc(), /*itf*/
            false);
            break;
        case Opcodes.H_INVOKEVIRTUAL:
        case // we end up calling these using invokevirtual
        Opcodes.H_INVOKESPECIAL:
            bridgeMethod = new Handle(Opcodes.H_INVOKEVIRTUAL, internalName, name, invokedMethod.getDesc(), /*itf*/
            false);
            break;
        case Opcodes.H_NEWINVOKESPECIAL:
            {
                // Call invisible constructor through generated bridge "factory" method, so we need to
                // compute the descriptor for the bridge method from the constructor's descriptor
                String desc = Type.getMethodDescriptor(Type.getObjectType(invokedMethod.getOwner()), Type.getArgumentTypes(invokedMethod.getDesc()));
                bridgeMethod = new Handle(Opcodes.H_INVOKESTATIC, internalName, name, desc, /*itf*/
                false);
                break;
            }
        case Opcodes.H_INVOKEINTERFACE:
        // Shouldn't get here
        default:
            throw new UnsupportedOperationException("Cannot bridge " + invokedMethod);
    }
    result = MethodReferenceBridgeInfo.bridge(invokedMethod, invoked, bridgeMethod);
    MethodReferenceBridgeInfo old = bridgeMethods.put(invokedMethod, result);
    checkState(old == null, "Already had bridge %s so we don't also want %s", old, result);
    return result;
}
Also used : Executable(java.lang.reflect.Executable) MethodHandle(java.lang.invoke.MethodHandle) Handle(org.objectweb.asm.Handle)

Example 8 with Handle

use of org.objectweb.asm.Handle in project bazel by bazelbuild.

the class LambdaDesugaring method visitEnd.

@Override
public void visitEnd() {
    for (Map.Entry<Handle, MethodReferenceBridgeInfo> bridge : bridgeMethods.entrySet()) {
        Handle original = bridge.getKey();
        Handle neededMethod = bridge.getValue().bridgeMethod();
        checkState(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));
        // rely on class writer to compute these
        bridgeMethod.visitMaxs(0, 0);
        bridgeMethod.visitEnd();
    }
    super.visitEnd();
}
Also used : Type(org.objectweb.asm.Type) MethodType(java.lang.invoke.MethodType) HashMap(java.util.HashMap) Map(java.util.Map) MethodHandle(java.lang.invoke.MethodHandle) Handle(org.objectweb.asm.Handle) MethodVisitor(org.objectweb.asm.MethodVisitor)

Example 9 with Handle

use of org.objectweb.asm.Handle in project elasticsearch by elastic.

the class SFunction method initializeConstant.

private void initializeConstant(MethodWriter writer) {
    final Handle handle = new Handle(Opcodes.H_INVOKESTATIC, CLASS_TYPE.getInternalName(), name, method.method.getDescriptor(), false);
    writer.push(handle);
}
Also used : Handle(org.objectweb.asm.Handle)

Example 10 with Handle

use of org.objectweb.asm.Handle in project lombok by rzwitserloot.

the class SneakyThrowsRemover method applyTransformations.

@Override
public byte[] applyTransformations(byte[] original, String fileName, final DiagnosticsReceiver diagnostics) {
    if (!new ClassFileMetaData(original).usesMethod("lombok/Lombok", "sneakyThrow"))
        return null;
    byte[] fixedByteCode = fixJSRInlining(original);
    ClassReader reader = new ClassReader(fixedByteCode);
    ClassWriter writer = new ClassWriter(reader, 0);
    final AtomicBoolean changesMade = new AtomicBoolean();
    class SneakyThrowsRemoverVisitor extends MethodVisitor {

        SneakyThrowsRemoverVisitor(MethodVisitor mv) {
            super(Opcodes.ASM5, mv);
        }

        private boolean methodInsnQueued = false;

        @Override
        public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
            if (opcode == Opcodes.INVOKESTATIC && "sneakyThrow".equals(name) && "lombok/Lombok".equals(owner) && "(Ljava/lang/Throwable;)Ljava/lang/RuntimeException;".equals(desc)) {
                if (System.getProperty("lombok.debugAsmOnly", null) != null) {
                    // DEBUG for issue 470!
                    super.visitMethodInsn(opcode, owner, name, desc, itf);
                } else {
                    methodInsnQueued = true;
                }
            } else {
                super.visitMethodInsn(opcode, owner, name, desc, itf);
            }
        }

        private void handleQueue() {
            if (!methodInsnQueued)
                return;
            super.visitMethodInsn(Opcodes.INVOKESTATIC, "lombok/Lombok", "sneakyThrow", "(Ljava/lang/Throwable;)Ljava/lang/RuntimeException;", false);
            methodInsnQueued = false;
            diagnostics.addWarning("Proper usage is: throw lombok.Lombok.sneakyThrow(someException);. You did not 'throw' it. Because of this, the call to sneakyThrow " + "remains in your classfile and you will need lombok.jar on the classpath at runtime.");
        }

        @Override
        public void visitInsn(int arg0) {
            if (methodInsnQueued && arg0 == Opcodes.ATHROW) {
                changesMade.set(true);
                // As expected, the required ATHROW. We can now safely 'eat' the previous call.
                methodInsnQueued = false;
            }
            handleQueue();
            super.visitInsn(arg0);
        }

        @Override
        public void visitFrame(int arg0, int arg1, Object[] arg2, int arg3, Object[] arg4) {
            handleQueue();
            super.visitFrame(arg0, arg1, arg2, arg3, arg4);
        }

        @Override
        public void visitIincInsn(int arg0, int arg1) {
            handleQueue();
            super.visitIincInsn(arg0, arg1);
        }

        @Override
        public void visitFieldInsn(int arg0, String arg1, String arg2, String arg3) {
            handleQueue();
            super.visitFieldInsn(arg0, arg1, arg2, arg3);
        }

        @Override
        public void visitIntInsn(int arg0, int arg1) {
            handleQueue();
            super.visitIntInsn(arg0, arg1);
        }

        @Override
        public void visitEnd() {
            handleQueue();
            super.visitEnd();
        }

        @Override
        public void visitInvokeDynamicInsn(String arg0, String arg1, Handle arg2, Object... arg3) {
            handleQueue();
            super.visitInvokeDynamicInsn(arg0, arg1, arg2, arg3);
        }

        @Override
        public void visitLabel(Label arg0) {
            handleQueue();
            super.visitLabel(arg0);
        }

        @Override
        public void visitJumpInsn(int arg0, Label arg1) {
            handleQueue();
            super.visitJumpInsn(arg0, arg1);
        }

        @Override
        public void visitLdcInsn(Object arg0) {
            handleQueue();
            super.visitLdcInsn(arg0);
        }

        @Override
        public void visitLocalVariable(String arg0, String arg1, String arg2, Label arg3, Label arg4, int arg5) {
            handleQueue();
            super.visitLocalVariable(arg0, arg1, arg2, arg3, arg4, arg5);
        }

        @Override
        public void visitMaxs(int arg0, int arg1) {
            handleQueue();
            super.visitMaxs(arg0, arg1);
        }

        @Override
        public void visitLookupSwitchInsn(Label arg0, int[] arg1, Label[] arg2) {
            handleQueue();
            super.visitLookupSwitchInsn(arg0, arg1, arg2);
        }

        @Override
        public void visitMultiANewArrayInsn(String arg0, int arg1) {
            handleQueue();
            super.visitMultiANewArrayInsn(arg0, arg1);
        }

        @Override
        public void visitVarInsn(int arg0, int arg1) {
            handleQueue();
            super.visitVarInsn(arg0, arg1);
        }

        @Override
        public void visitTryCatchBlock(Label arg0, Label arg1, Label arg2, String arg3) {
            handleQueue();
            super.visitTryCatchBlock(arg0, arg1, arg2, arg3);
        }

        @Override
        public void visitTableSwitchInsn(int arg0, int arg1, Label arg2, Label... arg3) {
            handleQueue();
            super.visitTableSwitchInsn(arg0, arg1, arg2, arg3);
        }

        @Override
        public void visitTypeInsn(int arg0, String arg1) {
            handleQueue();
            super.visitTypeInsn(arg0, arg1);
        }
    }
    reader.accept(new ClassVisitor(Opcodes.ASM5, writer) {

        @Override
        public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
            return new SneakyThrowsRemoverVisitor(super.visitMethod(access, name, desc, signature, exceptions));
        }
    }, 0);
    return changesMade.get() ? writer.toByteArray() : null;
}
Also used : Label(org.objectweb.asm.Label) ClassVisitor(org.objectweb.asm.ClassVisitor) ClassWriter(org.objectweb.asm.ClassWriter) MethodVisitor(org.objectweb.asm.MethodVisitor) Handle(org.objectweb.asm.Handle) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ClassReader(org.objectweb.asm.ClassReader)

Aggregations

Handle (org.objectweb.asm.Handle)14 MethodHandle (java.lang.invoke.MethodHandle)6 Type (org.objectweb.asm.Type)4 Label (org.objectweb.asm.Label)3 MethodType (java.lang.invoke.MethodType)2 StackManipulation (net.bytebuddy.implementation.bytecode.StackManipulation)2 Test (org.junit.Test)2 ClassReader (org.objectweb.asm.ClassReader)2 ClassWriter (org.objectweb.asm.ClassWriter)2 MethodVisitor (org.objectweb.asm.MethodVisitor)2 Local (com.googlecode.dex2jar.ir.expr.Local)1 MethodHandles (java.lang.invoke.MethodHandles)1 Executable (java.lang.reflect.Executable)1 Method (java.lang.reflect.Method)1 HashMap (java.util.HashMap)1 Map (java.util.Map)1 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)1 ClassVisitor (org.objectweb.asm.ClassVisitor)1 ClassNode (org.objectweb.asm.tree.ClassNode)1 FieldNode (org.objectweb.asm.tree.FieldNode)1