List of usage examples for org.objectweb.asm.commons GeneratorAdapter invokeDynamic
public void invokeDynamic(final String name, final String descriptor, final Handle bootstrapMethodHandle, final Object... bootstrapMethodArguments)
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(); }