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