couple questions on method handle combinators

Paul Sandoz paul.sandoz at oracle.com
Tue Jun 13 00:00:53 UTC 2017


Below is a simple test class. Unfortunately running this crashes the VM.

Paul.

#  Internal Error (/Users/sandoz/Projects/jdk10/valhalla/hotspot/src/share/vm/utilities/growableArray.hpp:233), pid=35547, tid=29443
#  assert(0 <= i && i < _len) failed: illegal index
...
Stack: [0x0000000122332000,0x0000000122432000],  sp=0x000000012242f1f0,  free space=1012k
Native frames: (J=compiled Java code, A=aot compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.dylib+0xc99cb4]  VMError::report_and_die(int, char const*, char const*, __va_list_tag*, Thread*, unsigned char*, void*, void*, char const*, int, unsigned long)+0x4d4
V  [libjvm.dylib+0xc9a476]  VMError::report_and_die(Thread*, char const*, int, char const*, char const*, __va_list_tag*)+0x4a
V  [libjvm.dylib+0x4cb281]  report_vm_error(char const*, int, char const*, char const*, ...)+0xcd
V  [libjvm.dylib+0x6a3ba6]  GrowableArray<int>::at(int) const+0x4e
V  [libjvm.dylib+0xa16335]  TypeStackSlotEntries::post_initialize(Symbol*, bool, bool)+0xa9
V  [libjvm.dylib+0xa164f5]  CallTypeData::post_initialize(BytecodeStream*, MethodData*)+0x14d
V  [libjvm.dylib+0xa1895f]  MethodData::post_initialize(BytecodeStream*)+0x81
V  [libjvm.dylib+0xa18cf0]  MethodData::initialize()+0x2d6
V  [libjvm.dylib+0xa17a95]  MethodData::allocate(ClassLoaderData*, methodHandle const&, Thread*)+0xa9
V  [libjvm.dylib+0xa0c994]  Method::build_interpreter_method_data(methodHandle const&, Thread*)+0x76
V  [libjvm.dylib+0x6beaf0]  InterpreterRuntime::profile_method(JavaThread*)+0x1ba
j  java.lang.invoke.LambdaForm$DMH.invokeStatic(Ljava/lang/Object;Qjava/lang/__Value;)Ljava/lang/Object;+0 java.base at 10-internal
j  java.lang.invoke.LambdaForm$MH.invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;I)Ljava/lang/Object;+169 java.base at 10-internal
j  java.lang.invoke.LambdaForm$MH.invoke_MT(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Ljava/lang/Object;+24 java.base at 10-internal
j  GWTTest.run_Q()I+20



> On 12 Jun 2017, at 13:13, Maurizio Cimadamore <maurizio.cimadamore at oracle.com> wrote:
> 
> 
> 
> On 12/06/17 20:27, Paul Sandoz wrote:
>> To investigate further i think we need to write a separate smaller GWT test for both values and refs. I can write such a test if that helps? and may want be useful for MH analysis.
> +1
> 
> Thanks Paul, seems a solid plan
> 
> Maurizio

/*
 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 * @test
 * @run testng/othervm
 *                     -Xverify:none
 *                     -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
 *                     -XX:-TieredCompilation
 *                     -XX:+EnableMVT
 *                     -Dvalhalla.enablePoolPatches=true
 *                     GWTTest
 */

/*
 *                     -Dvalhalla.dumpProxyClasses=.
 *                     -XX:+ValueTypePassFieldsAsArgs
 *                     -XX:+ValueTypeReturnedAsFields
 *                     -XX:+VerifyAdapterSharing
 *                     -XX:+EnableValhalla
 *                     -XX:+ValueArrayFlatten
 *                     -XX:ValueArrayElemMaxFlatSize=-1
 *                     -XX:ValueArrayElemMaxFlatOops=-1
 *                     -XX:+FullGCALotWithValueTypes

 */
import jdk.experimental.value.ValueType;
import org.testng.annotations.Test;
import valhalla.shady.MinimalValueTypes_1_0;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.Objects;

public class GWTTest {

    @jvm.internal.value.DeriveValueType
    static final class V {
        final int x;
        final int y;

        public V(int x, int y) {
            this.x = x;
            this.y = y;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            V v = (V) o;
            return x == v.x &&
                   y == v.y;
        }

        @Override
        public int hashCode() {
            return Objects.hash(x, y);
        }

        @Override
        public String toString() {
            final StringBuffer sb = new StringBuffer(this.getClass().getSimpleName());
            sb.append("{");
            sb.append("x=").append(x);
            sb.append(", y=").append(y);
            sb.append('}');
            return sb.toString();
        }
    }


    static final ValueType<?> VT = ValueType.forClass(V.class);

    static final Class<?> DVT;

    static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();


    static final Object Q_V1_ARRAY;

    static final Object Q_V2_ARRAY;

    static final MethodHandle Q_MH_GWT;

    static final Object L_V1_ARRAY;

    static final Object L_V2_ARRAY;

    static final MethodHandle L_MH_GWT;

    static boolean test() {
        return false;
    }

    static {
        try {
            DVT = MinimalValueTypes_1_0.getValueTypeClass(V.class);
        }
        catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }

        try {
            Q_V1_ARRAY = MethodHandles.arrayConstructor(VT.arrayValueClass()).invoke(1);
            Q_V2_ARRAY = MethodHandles.arrayConstructor(VT.arrayValueClass()).invoke(1);
            MethodHandles.arrayElementSetter(VT.arrayValueClass()).invoke(Q_V1_ARRAY, 0, new V(1, 1));
            MethodHandles.arrayElementSetter(VT.arrayValueClass()).invoke(Q_V2_ARRAY, 0, new V(2, 2));


            Q_MH_GWT = MethodHandles.guardWithTest(
                    MethodHandles.lookup().findStatic(GWTTest.class, "test", MethodType.methodType(boolean.class)),
                    MethodHandles.dropArguments(MethodHandles.arrayElementGetter(VT.arrayValueClass()), 1, VT.arrayValueClass()),
                    MethodHandles.dropArguments(MethodHandles.arrayElementGetter(VT.arrayValueClass()), 0, VT.arrayValueClass())
            );


            L_V1_ARRAY = new V[] { new V(1, 1) };
            L_V2_ARRAY = new V[] { new V(2, 2) };
            L_MH_GWT = MethodHandles.guardWithTest(
                    MethodHandles.lookup().findStatic(GWTTest.class, "test", MethodType.methodType(boolean.class)),
                    MethodHandles.dropArguments(MethodHandles.arrayElementGetter(V[].class), 1, V[].class),
                    MethodHandles.dropArguments(MethodHandles.arrayElementGetter(V[].class), 0, V[].class)
            );

        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }


    static int run_Q() throws Throwable {
        int sum = 0;
        for (int i = 0; i < 100_000; i++) {
            V v = (V) Q_MH_GWT.invoke(Q_V1_ARRAY, Q_V2_ARRAY, 0);
            sum += v.x;
        }
        return sum;
    }

    @Test
    public void testGWT_Q() throws Throwable {
        int r = run_Q();
        System.out.println(r);
    }

    static int run_L() throws Throwable {
        int sum = 0;
        for (int i = 0; i < 100_000; i++) {
            V v = (V) L_MH_GWT.invoke(L_V1_ARRAY, L_V2_ARRAY, 0);
            sum += v.x;
        }
        return sum;
    }

    @Test
    public void testGWT_L() throws Throwable {
        int r = run_L();
        System.out.println(r);
    }

    public static void main(String[] args) throws Throwable {
        GWTTest t = new GWTTest();
        t.testGWT_L();
        t.testGWT_Q();
    }
}



More information about the valhalla-dev mailing list