[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openjdk-mlvm-dev
Subject:    Specialize method with dynamic argument type?
From:       Dain Sundstrom <dain () iq80 ! com>
Date:       2019-08-08 20:01:05
Message-ID: EFDC7E3D-EF62-403E-B9D1-927B7E73EDD1 () iq80 ! com
[Download RAW message or body]

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


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic