Skip to content

Commit 94ce8fd

Browse files
author
Michael Haas
committed
Utilize the fixed binding feature of JVMCI in Graal.
1 parent dc35644 commit 94ce8fd

File tree

18 files changed

+611
-284
lines changed

18 files changed

+611
-284
lines changed
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package jdk.graal.compiler.hotspot.test;
2+
3+
import org.junit.Before;
4+
import org.junit.Test;
5+
6+
import jdk.graal.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl;
7+
import jdk.graal.compiler.hotspot.nodes.InvokeStaticJavaMethodNode;
8+
import jdk.graal.compiler.nodes.ValueNode;
9+
import jdk.graal.compiler.nodes.extended.ForeignCallNode;
10+
import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderContext;
11+
import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugin;
12+
import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugins;
13+
import jdk.vm.ci.meta.JavaKind;
14+
import jdk.vm.ci.meta.ResolvedJavaMethod;
15+
16+
/**
17+
* Verifies that deoptimization functions correctly when triggered during a method call invoked by
18+
* an {@link InvokeStaticJavaMethodNode}.
19+
*/
20+
public class HotSpotDeoptBoundJavaMethodCallerTest extends HotSpotInvokeBoundJavaMethodBaseTest {
21+
22+
/**
23+
* Calling {@link #getForeignCallInvokerMethod()} will deoptimize the calling frame. We will
24+
* deoptimize to {@link InvokeStaticJavaMethodNode#stateBefore()}.
25+
*/
26+
@Override
27+
protected boolean invocationPluginApply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode arg, JavaKind kind) {
28+
InvokeStaticJavaMethodNode node = InvokeStaticJavaMethodNode.create(b, getForeignCallInvokerMethod(), b.bci());
29+
b.add(node);
30+
// add the arg to the stack as the method has a return value
31+
b.addPush(kind, arg);
32+
return false;
33+
}
34+
35+
@Override
36+
protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) {
37+
invocationPlugins.register(HotSpotDeoptBoundJavaMethodCallerTest.class, new InvocationPlugin("testCallInt", int.class) {
38+
39+
@Override
40+
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg) {
41+
ForeignCallNode node = new ForeignCallNode(HotSpotForeignCallsProviderImpl.TEST_DEOPTIMIZE_CALLER_OF_CALLER, arg);
42+
b.addPush(JavaKind.Int, node);
43+
return true;
44+
}
45+
});
46+
super.registerInvocationPlugins(invocationPlugins);
47+
}
48+
49+
public static int testCallInt(int value) {
50+
return value;
51+
}
52+
53+
public static void invokeForeignCall() {
54+
testCallInt(3);
55+
}
56+
57+
public ResolvedJavaMethod getForeignCallInvokerMethod() {
58+
return getResolvedJavaMethod(HotSpotDeoptBoundJavaMethodCallerTest.class, "invokeForeignCall");
59+
}
60+
61+
@Before
62+
public void before() {
63+
getCode(getForeignCallInvokerMethod(), null, true, true, getInitialOptions());
64+
}
65+
66+
@Test
67+
@Override
68+
public void testMany() {
69+
super.testMany();
70+
}
71+
72+
}
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
/*
2+
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package jdk.graal.compiler.hotspot.test;
26+
27+
import jdk.graal.compiler.nodes.ValueNode;
28+
import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderContext;
29+
import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugin;
30+
import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugins;
31+
import jdk.vm.ci.meta.JavaKind;
32+
import jdk.vm.ci.meta.ResolvedJavaMethod;
33+
34+
/**
35+
* Base class for tests involving calls to bound methods.
36+
*/
37+
public abstract class HotSpotInvokeBoundJavaMethodBaseTest extends HotSpotGraalCompilerTest {
38+
39+
public static final JavaKind[] KINDS = {JavaKind.Boolean, JavaKind.Byte, JavaKind.Short, JavaKind.Char, JavaKind.Int, JavaKind.Long, JavaKind.Object};
40+
41+
@Override
42+
protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) {
43+
for (JavaKind kind : KINDS) {
44+
String name = kind.isObject() ? "passingObject" : "passing" + capitalize(kind.getJavaName());
45+
Class<?> argType = kind.isObject() ? Object.class : kind.toJavaClass();
46+
invocationPlugins.register(HotSpotInvokeBoundJavaMethodBaseTest.class, new InvocationPlugin(name, argType) {
47+
@Override
48+
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode arg) {
49+
invocationPluginApply(b, targetMethod, receiver, arg, kind);
50+
return true;
51+
}
52+
});
53+
}
54+
super.registerInvocationPlugins(invocationPlugins);
55+
}
56+
57+
private static String capitalize(String s) {
58+
return Character.toUpperCase(s.charAt(0)) + s.substring(1);
59+
}
60+
61+
protected abstract boolean invocationPluginApply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode arg, JavaKind kind);
62+
63+
static boolean[] booleanValues = new boolean[]{Boolean.TRUE, Boolean.FALSE};
64+
65+
static boolean passingBoolean(boolean arg) {
66+
return arg;
67+
}
68+
69+
public static boolean passingBooleanSnippet(boolean arg) {
70+
return passingBoolean(arg);
71+
}
72+
73+
public void testPassingBoolean() {
74+
for (boolean value : booleanValues) {
75+
test("passingBooleanSnippet", value);
76+
}
77+
}
78+
79+
static byte[] byteValues = new byte[]{Byte.MAX_VALUE, -1, 0, 1, Byte.MIN_VALUE};
80+
81+
static byte passingByte(byte arg) {
82+
return arg;
83+
}
84+
85+
public static byte passingByteSnippet(byte arg) {
86+
return passingByte(arg);
87+
}
88+
89+
public void testPassingByte() {
90+
for (byte value : byteValues) {
91+
test("passingByteSnippet", value);
92+
}
93+
}
94+
95+
static short[] shortValues = new short[]{Short.MAX_VALUE, -1, 0, 1, Short.MIN_VALUE};
96+
97+
static short passingShort(short arg) {
98+
return arg;
99+
}
100+
101+
public static short passingShortSnippet(short arg) {
102+
return passingShort(arg);
103+
}
104+
105+
public void testPassingShort() {
106+
for (short value : shortValues) {
107+
test("passingShortSnippet", value);
108+
}
109+
}
110+
111+
static char[] charValues = new char[]{Character.MAX_VALUE, 1, Character.MIN_VALUE};
112+
113+
static char passingChar(char arg) {
114+
return arg;
115+
}
116+
117+
public static char passingCharSnippet(char arg) {
118+
return passingChar(arg);
119+
}
120+
121+
public void testPassingChar() {
122+
for (char value : charValues) {
123+
test("passingCharSnippet", value);
124+
}
125+
}
126+
127+
static int[] intValues = new int[]{Integer.MAX_VALUE, -1, 0, 1, Integer.MIN_VALUE};
128+
129+
static int passingInt(int arg) {
130+
return arg;
131+
}
132+
133+
public static int passingIntSnippet(int arg) {
134+
return passingInt(arg);
135+
}
136+
137+
public void testPassingInt() {
138+
for (int value : intValues) {
139+
test("passingIntSnippet", value);
140+
}
141+
}
142+
143+
static long[] longValues = new long[]{Long.MAX_VALUE, -1, 0, 1, Long.MIN_VALUE};
144+
145+
static long passingLong(long arg) {
146+
return arg;
147+
}
148+
149+
public static long passingLongSnippet(long arg) {
150+
return passingLong(arg);
151+
}
152+
153+
public void testPassingLong() {
154+
for (long value : longValues) {
155+
test("passingLongSnippet", value);
156+
}
157+
}
158+
159+
static Object[] objectValues = new Object[]{null, "String", Integer.valueOf(-1)};
160+
161+
static Object passingObject(Object arg) {
162+
return arg;
163+
}
164+
165+
public static Object passingObjectSnippet(Object arg) {
166+
return passingObject(arg);
167+
}
168+
169+
public void testPassingObject() {
170+
for (Object value : objectValues) {
171+
test("passingObjectSnippet", value);
172+
}
173+
}
174+
175+
public void testMany() {
176+
testPassingObject();
177+
testPassingInt();
178+
testPassingByte();
179+
testPassingChar();
180+
testPassingLong();
181+
testPassingBoolean();
182+
testPassingShort();
183+
}
184+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package jdk.graal.compiler.hotspot.test;
26+
27+
import org.junit.Test;
28+
29+
import jdk.graal.compiler.hotspot.nodes.InvokeStaticJavaMethodNode;
30+
import jdk.graal.compiler.nodes.Invoke;
31+
import jdk.graal.compiler.nodes.ValueNode;
32+
import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderContext;
33+
import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugin;
34+
import jdk.vm.ci.meta.JavaKind;
35+
import jdk.vm.ci.meta.ResolvedJavaMethod;
36+
37+
/**
38+
* Tests that using an {@link InvokeStaticJavaMethodNode} instead of an {@link Invoke} to call a
39+
* side-effect-free static method produces identical behavior.
40+
*/
41+
public class HotSpotInvokeBoundJavaMethodTest extends HotSpotInvokeBoundJavaMethodBaseTest {
42+
43+
@Override
44+
protected boolean invocationPluginApply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode arg, JavaKind kind) {
45+
InvokeStaticJavaMethodNode node = InvokeStaticJavaMethodNode.create(b, targetMethod, b.bci(), arg);
46+
b.addPush(kind, node);
47+
return false;
48+
}
49+
50+
@Test
51+
@Override
52+
public void testMany() {
53+
super.testMany();
54+
}
55+
}

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,7 @@ private long getZGCAddressField(String name) {
701701
public final long validateObject = getAddress("JVMCIRuntime::validate_object");
702702

703703
public final long testDeoptimizeCallInt = getAddress("JVMCIRuntime::test_deoptimize_call_int");
704+
public final long testDeoptimizeCallerOfCaller = getAddress("JVMCIRuntime::test_deoptimize_caller_of_caller");
704705

705706
public final long registerFinalizerAddress = getAddress("SharedRuntime::register_finalizer");
706707
public final long exceptionHandlerForReturnAddressAddress = getAddress("SharedRuntime::exception_handler_for_return_address");

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ public abstract class HotSpotForeignCallsProviderImpl implements HotSpotForeignC
8282
Word.class);
8383

8484
public static final HotSpotForeignCallDescriptor TEST_DEOPTIMIZE_CALL_INT = new HotSpotForeignCallDescriptor(SAFEPOINT, NO_SIDE_EFFECT, any(), "test_deoptimize_call_int", int.class, int.class);
85+
public static final HotSpotForeignCallDescriptor TEST_DEOPTIMIZE_CALLER_OF_CALLER = new HotSpotForeignCallDescriptor(SAFEPOINT, NO_SIDE_EFFECT, any(), "test_deoptimize_caller_of_caller",
86+
int.class, int.class);
8587

8688
protected final HotSpotJVMCIRuntime jvmciRuntime;
8789
protected final HotSpotGraalRuntimeProvider runtime;

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,7 @@ public void initialize(HotSpotProviders providers, OptionValues options) {
596596
linkForeignCall(options, providers, VALIDATE_OBJECT, c.validateObject, PREPEND_THREAD);
597597

598598
linkForeignCall(options, providers, TEST_DEOPTIMIZE_CALL_INT, c.testDeoptimizeCallInt, PREPEND_THREAD);
599+
linkForeignCall(options, providers, TEST_DEOPTIMIZE_CALLER_OF_CALLER, c.testDeoptimizeCallerOfCaller, PREPEND_THREAD);
599600

600601
registerArrayCopy(JavaKind.Byte, c.jbyteArraycopy, c.jbyteAlignedArraycopy, c.jbyteDisjointArraycopy, c.jbyteAlignedDisjointArraycopy);
601602
registerArrayCopy(JavaKind.Boolean, c.jbyteArraycopy, c.jbyteAlignedArraycopy, c.jbyteDisjointArraycopy, c.jbyteAlignedDisjointArraycopy);

0 commit comments

Comments
 (0)