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)

_______________________________________________
mlvm-dev mailing list
mlvm-dev@openjdk.java.net
https://mail.openjdk.java.net/mailman/listinfo/mlvm-dev

Reply via email to