Specialize method with dynamic argument type?

Dain Sundstrom dain at iq80.com
Thu Aug 8 20:01:05 UTC 2019


Hi all,

I've been playing with the LW2 code, and using method handles to create specialized code (without byte code generation).  I am able to do most of the transformation easily, but have run into a case I'd like to run by this group, because it applies today to specializing code for primitives.

The method handle specialization, I'm using works well for functions that process arrays internally.  For example, I can write a generic function that performs a user supplied equality between two positions in an array as follows:

public class InternalOnly
{
    public static void main(String[] args)
            throws Throwable
    {
        Lookup lookup = MethodHandles.lookup();
        MethodHandle doubleArrayPositionsEqual = lookup.findStatic(
                InternalOnly.class,
                "doubleArrayPositionsEqual",
                methodType(boolean.class, double[].class, int.class, int.class))
                .asType(methodType(boolean.class, Object.class, int.class, int.class));

        MethodHandle comparePositions = lookup.findStatic(
                InternalOnly.class,
                "comparePositions",
                methodType(boolean.class, MethodHandle.class, Object.class, int.class, int.class))
                .bindTo(doubleArrayPositionsEqual);

        Object array = new double[] {1, 2};
        System.out.println((boolean) comparePositions.invokeExact(array, 0, 0));
        System.out.println((boolean) comparePositions.invokeExact(array, 0, 1));
    }

    public static boolean comparePositions(MethodHandle comparePositions, Object array, int leftPosition, int rightPosition)
            throws Throwable
    {
        return (boolean) comparePositions.invokeExact(array, leftPosition, rightPosition);
    }

    public static boolean doubleArrayPositionsEqual(double[] array, int left, int right)
    {
        return array[left] == array[right];
    }
}

The problem comes if I want to create a function that takes a generic argument type (including primitives).  For example, a function that compares an array position with a user supplied argument.  The hack I came up with is to have my generic function take a no-arg MethodHandle for the arguments I want to pass in, and then I use MethodHandles.filterArguments to bind in MethodHandles.constant to which effectively the MethodHandle argument into the primitive type argument I want.  Here is an example:

public class DynamicArgument
{
    public static void main(String[] args)
            throws Throwable
    {
        Lookup lookup = MethodHandles.lookup();
        MethodHandle doubleArrayPositionsEqual = lookup.findStatic(
                DynamicArgument.class,
                "doubleArrayPositionsEqual",
                methodType(boolean.class, double[].class, int.class, double.class))
                .asType(methodType(boolean.class, Object.class, int.class, double.class));

        MethodHandle doubleArgument = lookup.findStatic(MethodHandles.class, "constant", methodType(MethodHandle.class, Class.class, Object.class))
                .bindTo(double.class)
                .asType(methodType(MethodHandle.class, double.class));

        MethodHandle comparePositions = lookup.findStatic(
                DynamicArgument.class,
                "comparePositions",
                methodType(boolean.class, MethodHandle.class, Object.class, int.class, MethodHandle.class))
                .bindTo(doubleArrayPositionsEqual);
        comparePositions = filterArguments(comparePositions, 2, doubleArgument);

        Object array = new double[] {1, 2};
        System.out.println((boolean) comparePositions.invokeExact(array, 0, 1.0));
        System.out.println((boolean) comparePositions.invokeExact(array, 0, 42.2));
    }

    public static boolean comparePositions(MethodHandle comparePositions, Object array, int leftPosition, MethodHandle rightValue)
            throws Throwable
    {
        return (boolean) comparePositions.invoke(array, leftPosition, rightValue.invoke());
    }

    public static boolean doubleArrayPositionsEqual(double[] array, int left, double rightValue)
    {
        return array[left] == rightValue;
    }
}

This works, but I'm not sure if this is a design that was intended by the APIs.  What do you all think?  Is there a better way to accomplish something like this?

Thanks for any feedback,

-dain


----
Dain Sundstrom
Co-founder @ Presto Software Foundation, Co-creator of Presto (https://prestosql.io)



More information about the mlvm-dev mailing list