couple questions on method handle combinators

Paul Sandoz paul.sandoz at oracle.com
Tue Jun 13 23:36:10 UTC 2017


In an attempt to simplify the test and to try and obtain invokeExact semantics for inlining i created a new test.

This one crashes the VM :-)

Paul.

#  Internal Error (/Users/sandoz/Projects/jdk10/valhalla/hotspot/src/share/vm/opto/type.cpp:2084), pid=59955, tid=26883
#  assert(type != ciEnv::current()->___Value_klass()) failed: unsupported
...
Current CompileTask:
C2:   4213  353 %           GWTTest::run_Q @ 4 (29 bytes)

Stack: [0x000000011bbbd000,0x000000011bcbd000],  sp=0x000000011bcb9d60,  free space=1011k
Native frames: (J=compiled Java code, A=aot compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.dylib+0xc9ac54]  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+0xc9b416]  VMError::report_and_die(Thread*, char const*, int, char const*, char const*, __va_list_tag*)+0x4a
V  [libjvm.dylib+0x4cc1e1]  report_vm_error(char const*, int, char const*, char const*, ...)+0xcd
V  [libjvm.dylib+0xc3fe07]  TypeTuple::make_domain(ciInstanceKlass*, ciSignature*, bool)+0x307
V  [libjvm.dylib+0xc48c5a]  TypeFunc::make(ciMethod*)+0x52
V  [libjvm.dylib+0x6520bd]  GraphKit::round_double_arguments(ciMethod*)+0x1d
V  [libjvm.dylib+0x551a4c]  Parse::do_call()+0x568
V  [libjvm.dylib+0xac7f82]  Parse::do_one_bytecode()+0xf4
V  [libjvm.dylib+0xabb98f]  Parse::do_one_block()+0x35f
V  [libjvm.dylib+0xaba470]  Parse::do_all_blocks()+0x428
V  [libjvm.dylib+0xab704c]  Parse::Parse(JVMState*, ciMethod*, float)+0xa1e
V  [libjvm.dylib+0x350cfc]  ParseGenerator::generate(JVMState*)+0xb6
V  [libjvm.dylib+0x551bac]  Parse::do_call()+0x6c8
V  [libjvm.dylib+0xac7f82]  Parse::do_one_bytecode()+0xf4
V  [libjvm.dylib+0xabb98f]  Parse::do_one_block()+0x35f
V  [libjvm.dylib+0xaba470]  Parse::do_all_blocks()+0x428
V  [libjvm.dylib+0xab704c]  Parse::Parse(JVMState*, ciMethod*, float)+0xa1e
V  [libjvm.dylib+0x350cfc]  ParseGenerator::generate(JVMState*)+0xb6
V  [libjvm.dylib+0x551bac]  Parse::do_call()+0x6c8
V  [libjvm.dylib+0xac7f82]  Parse::do_one_bytecode()+0xf4
V  [libjvm.dylib+0xabb98f]  Parse::do_one_block()+0x35f
V  [libjvm.dylib+0xaba470]  Parse::do_all_blocks()+0x428
V  [libjvm.dylib+0xab704c]  Parse::Parse(JVMState*, ciMethod*, float)+0xa1e
V  [libjvm.dylib+0x350cfc]  ParseGenerator::generate(JVMState*)+0xb6
V  [libjvm.dylib+0x46554e]  Compile::Compile(ciEnv*, C2Compiler*, ciMethod*, int, bool, bool, bool, DirectiveSet*)+0x8c8
V  [libjvm.dylib+0x46857b]  Compile::Compile(ciEnv*, C2Compiler*, ciMethod*, int, bool, bool, bool, DirectiveSet*)+0x31
V  [libjvm.dylib+0x34f680]  C2Compiler::compile_method(ciEnv*, ciMethod*, int, DirectiveSet*)+0x130



/*
 * 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
 *                     -Djava.lang.invoke.MethodHandle.DUMP_CLASS_FILES=true
 *                     -Dvalhalla.enablePoolPatches=true
 *                     -Xverify:none
 *                     -XX:-TieredCompilation
 *                     -XX:+EnableMVT
 *                     -XX:+ValueArrayFlatten
 *                     -XX:+ValueTypePassFieldsAsArgs
 *                     -XX:+ValueTypeReturnedAsFields
 *                     -XX:+VerifyAdapterSharing
 *                     -XX:+EnableValhalla
 *                     -XX:ValueArrayElemMaxFlatSize=-1
 *                     -XX:ValueArrayElemMaxFlatOops=-1
 *                     -XX:+FullGCALotWithValueTypes
 *                     GWTTest
 */

/*
 *                     -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
 *                     -XX:-TieredCompilation
 *                     -XX:+EnableMVT
 *                     -XX:+ValueArrayFlatten
 *                     -XX:+ValueTypePassFieldsAsArgs
 *                     -XX:+ValueTypeReturnedAsFields
 *                     -XX:+VerifyAdapterSharing
 *                     -XX:+EnableValhalla
 *                     -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 V V1 = new V(1, 1);

    static final V V2 = new V(2, 2);

    static final MethodHandle Q_MH_GWT;

    static final MethodHandle L_MH_GWT;

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

        try {
            MethodHandle v1 = LOOKUP.findStatic(GWTTest.class, "v1", MethodType.methodType(V.class));
            MethodHandle v2 = LOOKUP.findStatic(GWTTest.class, "v2", MethodType.methodType(V.class));
            MethodHandle test = LOOKUP.findStatic(GWTTest.class, "test", MethodType.methodType(boolean.class));

            MethodHandle v_unbox = VT.unbox();

            MethodHandle q_gwt = MethodHandles.guardWithTest(
                    test,
                    MethodHandles.filterReturnValue(v1, v_unbox),
                    MethodHandles.filterReturnValue(v2, v_unbox)
            );
            Q_MH_GWT = MethodHandles.filterReturnValue(
                    q_gwt,
                    VT.findGetter(LOOKUP, "x", int.class));


            MethodHandle l_gwt = MethodHandles.guardWithTest(
                    test,
                    v1,
                    v2
            );
            L_MH_GWT = MethodHandles.filterReturnValue(
                    l_gwt,
                    LOOKUP.findGetter(V.class, "x", int.class));
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }

    static boolean test() {
        return false;
    }

    static V v1() {
        return V1;
    }

    static V v2() {
        return V2;
    }

    static int run_Q() throws Throwable {
        int sum = 0;
        for (int i = 0; i < 100_000; i++) {
            int v = (int) Q_MH_GWT.invokeExact();
            sum += v;
        }
        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++) {
            int v = (int) L_MH_GWT.invokeExact();
            sum += v;
        }
        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