Example usage for org.objectweb.asm.commons GeneratorAdapter invokeDynamic

List of usage examples for org.objectweb.asm.commons GeneratorAdapter invokeDynamic

Introduction

In this page you can find the example usage for org.objectweb.asm.commons GeneratorAdapter invokeDynamic.

Prototype

public void invokeDynamic(final String name, final String descriptor, final Handle bootstrapMethodHandle,
        final Object... bootstrapMethodArguments) 

Source Link

Document

Generates an invokedynamic instruction.

Usage

From source file:org.elasticsearch.painless.LambdaBootstrap.java

License:Apache License

/**
 * Generates the interface method that will delegate (call) to the delegate method
 * with {@code INVOKEDYNAMIC} using the {@link #delegateBootstrap} type converter.
 */// w  w w  . ja v  a 2s. c  om
private static void generateInterfaceMethod(ClassWriter cw, MethodType factoryMethodType, Type lambdaClassType,
        String interfaceMethodName, MethodType interfaceMethodType, Type delegateClassType,
        int delegateInvokeType, String delegateMethodName, MethodType delegateMethodType, Capture[] captures)
        throws LambdaConversionException {

    String lamDesc = interfaceMethodType.toMethodDescriptorString();
    Method lamMeth = new Method(lambdaClassType.getInternalName(), lamDesc);
    int modifiers = ACC_PUBLIC;

    GeneratorAdapter iface = new GeneratorAdapter(modifiers, lamMeth,
            cw.visitMethod(modifiers, interfaceMethodName, lamDesc, null, null));
    iface.visitCode();

    // Loads any captured variables onto the stack.
    for (int captureCount = 0; captureCount < captures.length; ++captureCount) {
        iface.loadThis();
        iface.getField(lambdaClassType, captures[captureCount].name, captures[captureCount].type);
    }

    // Loads any passed in arguments onto the stack.
    iface.loadArgs();

    // Handles the case for a lambda function or a static reference method.
    // interfaceMethodType and delegateMethodType both have the captured types
    // inserted into their type signatures.  This later allows the delegate
    // method to be invoked dynamically and have the interface method types
    // appropriately converted to the delegate method types.
    // Example: Integer::parseInt
    // Example: something.each(x -> x + 1)
    if (delegateInvokeType == H_INVOKESTATIC) {
        interfaceMethodType = interfaceMethodType.insertParameterTypes(0, factoryMethodType.parameterArray());
        delegateMethodType = delegateMethodType.insertParameterTypes(0, factoryMethodType.parameterArray());
    } else if (delegateInvokeType == H_INVOKEVIRTUAL || delegateInvokeType == H_INVOKEINTERFACE) {
        // Handles the case for a virtual or interface reference method with no captures.
        // delegateMethodType drops the 'this' parameter because it will be re-inserted
        // when the method handle for the dynamically invoked delegate method is created.
        // Example: Object::toString
        if (captures.length == 0) {
            Class<?> clazz = delegateMethodType.parameterType(0);
            delegateClassType = Type.getType(clazz);
            delegateMethodType = delegateMethodType.dropParameterTypes(0, 1);
            // Handles the case for a virtual or interface reference method with 'this'
            // captured. interfaceMethodType inserts the 'this' type into its
            // method signature. This later allows the delegate
            // method to be invoked dynamically and have the interface method types
            // appropriately converted to the delegate method types.
            // Example: something::toString
        } else if (captures.length == 1) {
            Class<?> clazz = factoryMethodType.parameterType(0);
            delegateClassType = Type.getType(clazz);
            interfaceMethodType = interfaceMethodType.insertParameterTypes(0, clazz);
        } else {
            throw new LambdaConversionException("unexpected number of captures [ " + captures.length + "]");
        }
    } else {
        throw new IllegalStateException("unexpected invocation type [" + delegateInvokeType + "]");
    }

    Handle delegateHandle = new Handle(delegateInvokeType, delegateClassType.getInternalName(),
            delegateMethodName, delegateMethodType.toMethodDescriptorString(),
            delegateInvokeType == H_INVOKEINTERFACE);
    iface.invokeDynamic(delegateMethodName,
            Type.getMethodType(interfaceMethodType.toMethodDescriptorString()).getDescriptor(),
            DELEGATE_BOOTSTRAP_HANDLE, delegateHandle);

    iface.returnValue();
    iface.endMethod();
}