Skip to content

Commit bf6df1d

Browse files
committed
[GR-54975] Add substitution for ArraysSupport for handling foreign objects.
PullRequest: graal/18198
2 parents 10223db + 0a27f2a commit bf6df1d

File tree

3 files changed

+247
-5
lines changed

3 files changed

+247
-5
lines changed

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/descriptors/Symbol.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,9 @@ public static void ensureInitialized() {
464464
// sun.misc.NativeSignalHandler
465465
public static final Symbol<Name> handler = StaticSymbols.putName("handler");
466466

467+
// jdk.internal.util.ArraysSupport
468+
public static final Symbol<Name> vectorizedMismatch = StaticSymbols.putName("vectorizedMismatch");
469+
467470
// Attribute names
468471
public static final Symbol<Name> AnnotationDefault = StaticSymbols.putName("AnnotationDefault");
469472
public static final Symbol<Name> BootstrapMethods = StaticSymbols.putName("BootstrapMethods");
@@ -689,7 +692,7 @@ public static void ensureInitialized() {
689692
public static final Symbol<Type> jdk_internal_loader_NativeLibraries = StaticSymbols.putType("Ljdk/internal/loader/NativeLibraries;");
690693
public static final Symbol<Type> sun_misc_Launcher$ExtClassLoader = StaticSymbols.putType("Lsun/misc/Launcher$ExtClassLoader;");
691694
public static final Symbol<Type> jdk_internal_loader_RawNativeLibraries$RawNativeLibraryImpl = StaticSymbols.putType("Ljdk/internal/loader/RawNativeLibraries$RawNativeLibraryImpl;");
692-
695+
public static final Symbol<Type> jdk_internal_util_ArraysSupport = StaticSymbols.putType("Ljdk/internal/util/ArraysSupport;");
693696
public static final Symbol<Type> java_io_InputStream = StaticSymbols.putType("Ljava/io/InputStream;");
694697
public static final Symbol<Type> java_io_PrintStream = StaticSymbols.putType("Ljava/io/PrintStream;");
695698
public static final Symbol<Type> java_nio_file_Path = StaticSymbols.putType("Ljava/nio/file/Path;");
@@ -1143,6 +1146,8 @@ public static void ensureInitialized() {
11431146
public static final Symbol<Signature> Object_long_int_int_int_int = StaticSymbols.putSignature(Type.java_lang_Object, Type._long, Type._int, Type._int, Type._int, Type._int);
11441147
public static final Symbol<Signature> Object_long_int_int_int_Object_array = StaticSymbols.putSignature(Type.java_lang_Object, Type._long, Type._int, Type._int, Type._int,
11451148
Type.java_lang_Object_array);
1149+
public static final Symbol<Signature> _int_Object_long_Object_long_int_int = StaticSymbols.putSignature(Type._int, Type.java_lang_Object, Type._long, Type.java_lang_Object, Type._long,
1150+
Type._int, Type._int);
11461151
public static final Symbol<Signature> Object_long_int_ContinuationScope_Continuation_int_int_Object_array = StaticSymbols.putSignature(Type.java_lang_Object, Type._long, Type._int,
11471152
Type.jdk_internal_vm_ContinuationScope, Type.jdk_internal_vm_Continuation, Type._int, Type._int,
11481153
Type.java_lang_Object_array);

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/meta/Meta.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,14 @@ public Meta(EspressoContext context) {
350350
jdk_internal_loader_RawNativeLibraries$RawNativeLibraryImpl_handle = null;
351351
}
352352

353+
if (getJavaVersion().java9OrLater()) {
354+
jdk_internal_util_ArraysSupport = knownKlass(Type.jdk_internal_util_ArraysSupport);
355+
jdk_internal_util_ArraysSupport_vectorizedMismatch = jdk_internal_util_ArraysSupport.requireDeclaredMethod(Name.vectorizedMismatch, Signature._int_Object_long_Object_long_int_int);
356+
} else {
357+
jdk_internal_util_ArraysSupport = null;
358+
jdk_internal_util_ArraysSupport_vectorizedMismatch = null;
359+
}
360+
353361
java_net_URL = knownKlass(Type.java_net_URL);
354362

355363
java_lang_ClassLoader_getResourceAsStream = java_lang_ClassLoader.requireDeclaredMethod(Name.getResourceAsStream, Signature.InputStream_String);
@@ -1373,6 +1381,8 @@ private DiffVersionLoadHelper diff() {
13731381
public final ObjectKlass jdk_internal_loader_RawNativeLibraries$RawNativeLibraryImpl;
13741382
public final Field jdk_internal_loader_RawNativeLibraries$RawNativeLibraryImpl_handle;
13751383

1384+
public final ObjectKlass jdk_internal_util_ArraysSupport;
1385+
public final Method jdk_internal_util_ArraysSupport_vectorizedMismatch;
13761386
public final ObjectKlass java_net_URL;
13771387

13781388
public final ObjectKlass sun_launcher_LauncherHelper;
@@ -2510,8 +2520,7 @@ public StaticObject toGuestString(Symbol<?> hostString) {
25102520
}
25112521

25122522
public static boolean isString(Object string) {
2513-
if (string instanceof StaticObject) {
2514-
StaticObject staticObject = (StaticObject) string;
2523+
if (string instanceof StaticObject staticObject) {
25152524
return staticObject.isString();
25162525
}
25172526
return false;
@@ -2547,8 +2556,7 @@ public Object toGuestBoxed(Object hostObject) {
25472556

25482557
public Object toHostBoxed(Object object) {
25492558
assert object != null;
2550-
if (object instanceof StaticObject) {
2551-
StaticObject guestObject = (StaticObject) object;
2559+
if (object instanceof StaticObject guestObject) {
25522560
if (StaticObject.isNull(guestObject)) {
25532561
return null;
25542562
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
/*
2+
* Copyright (c) 2024, 2024, 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.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
package com.oracle.truffle.espresso.substitutions;
24+
25+
import com.oracle.truffle.api.CompilerDirectives;
26+
import com.oracle.truffle.api.dsl.Bind;
27+
import com.oracle.truffle.api.dsl.Cached;
28+
import com.oracle.truffle.api.dsl.Specialization;
29+
import com.oracle.truffle.api.interop.InteropLibrary;
30+
import com.oracle.truffle.api.interop.InvalidArrayIndexException;
31+
import com.oracle.truffle.api.interop.InvalidBufferOffsetException;
32+
import com.oracle.truffle.api.interop.UnsupportedMessageException;
33+
import com.oracle.truffle.api.library.CachedLibrary;
34+
import com.oracle.truffle.api.nodes.DirectCallNode;
35+
import com.oracle.truffle.espresso.impl.Klass;
36+
import com.oracle.truffle.espresso.meta.EspressoError;
37+
import com.oracle.truffle.espresso.meta.Meta;
38+
import com.oracle.truffle.espresso.nodes.EspressoNode;
39+
import com.oracle.truffle.espresso.runtime.staticobject.StaticObject;
40+
41+
@EspressoSubstitutions
42+
public final class Target_jdk_internal_util_ArraysSupport {
43+
44+
@Substitution(versionFilter = VersionFilter.Java9OrLater.class)
45+
abstract static class VectorizedMismatch extends SubstitutionNode {
46+
47+
static final int LIMIT = 5;
48+
49+
abstract int execute(
50+
@JavaType(Object.class) StaticObject a, long aOffset, @JavaType(Object.class) StaticObject b, long bOffset, int length, int log2ArrayIndexScale);
51+
52+
@Specialization(guards = {
53+
"a.isEspressoObject()",
54+
"b.isEspressoObject()"
55+
})
56+
int doEspresso(
57+
@JavaType(Object.class) StaticObject a,
58+
long aOffset,
59+
@JavaType(Object.class) StaticObject b,
60+
long bOffset,
61+
int length,
62+
int log2ArrayIndexScale,
63+
@SuppressWarnings("unused") @Bind("getMeta()") Meta meta,
64+
@Cached("create(meta.jdk_internal_util_ArraysSupport_vectorizedMismatch.getCallTargetNoSubstitution())") DirectCallNode original) {
65+
return (int) original.call(a, aOffset, b, bOffset, length, log2ArrayIndexScale);
66+
}
67+
68+
@Specialization(guards = {
69+
"a.isForeignObject()",
70+
"b.isForeignObject()"
71+
})
72+
int doBothForeign(
73+
@JavaType(Object.class) StaticObject a,
74+
long aOffset,
75+
@JavaType(Object.class) StaticObject b,
76+
long bOffset,
77+
int length,
78+
int log2ArrayIndexScale,
79+
@SuppressWarnings("unused") @Bind("getMeta()") Meta meta,
80+
@Cached CopyToGuestArrayNode copyNode,
81+
@Cached("create(meta.jdk_internal_util_ArraysSupport_vectorizedMismatch.getCallTargetNoSubstitution())") DirectCallNode original) {
82+
assert a.getKlass().isArray();
83+
assert a.getKlass() == b.getKlass();
84+
85+
return (int) original.call(copyNode.execute(a), aOffset, copyNode.execute(b), bOffset, length, log2ArrayIndexScale);
86+
}
87+
88+
@Specialization(guards = {
89+
"a.isForeignObject()",
90+
"b.isEspressoObject()"
91+
})
92+
int doFirstForeign(
93+
@JavaType(Object.class) StaticObject a,
94+
long aOffset,
95+
@JavaType(Object.class) StaticObject b,
96+
long bOffset,
97+
int length,
98+
int log2ArrayIndexScale,
99+
@Cached CopyToGuestArrayNode copyNode,
100+
@SuppressWarnings("unused") @Bind("getMeta()") Meta meta,
101+
@Cached("create(meta.jdk_internal_util_ArraysSupport_vectorizedMismatch.getCallTargetNoSubstitution())") DirectCallNode original) {
102+
assert a.getKlass().isArray();
103+
assert a.getKlass() == b.getKlass();
104+
105+
return (int) original.call(copyNode.execute(a), aOffset, b, bOffset, length, log2ArrayIndexScale);
106+
}
107+
108+
@Specialization(guards = {
109+
"a.isEspressoObject()",
110+
"b.isForeignObject()"
111+
})
112+
int doSecondForeign(
113+
@JavaType(Object.class) StaticObject a,
114+
long aOffset,
115+
@JavaType(Object.class) StaticObject b,
116+
long bOffset,
117+
int length,
118+
int log2ArrayIndexScale,
119+
@SuppressWarnings("unused") @Bind("getMeta()") Meta meta,
120+
@Cached CopyToGuestArrayNode copyNode,
121+
@Cached("create(meta.jdk_internal_util_ArraysSupport_vectorizedMismatch.getCallTargetNoSubstitution())") DirectCallNode original) {
122+
assert a.getKlass().isArray();
123+
assert a.getKlass() == b.getKlass();
124+
125+
return (int) original.call(a, aOffset, copyNode.execute(b), bOffset, length, log2ArrayIndexScale);
126+
}
127+
}
128+
129+
abstract static class CopyToGuestArrayNode extends EspressoNode {
130+
131+
static final int LIMIT = 4;
132+
133+
public abstract @JavaType(Object.class) StaticObject execute(StaticObject foreignArray);
134+
135+
@SuppressWarnings("unused")
136+
@Specialization(guards = "foreignArray.getKlass() == cachedKlass", limit = "LIMIT")
137+
@JavaType(Object.class)
138+
StaticObject doCached(StaticObject foreignArray,
139+
@Cached("foreignArray.getKlass()") Klass cachedKlass,
140+
@Bind("getMeta()") Meta meta,
141+
@CachedLibrary("foreignArray.rawForeignObject(meta.getLanguage())") InteropLibrary interop) {
142+
return copyToGuestArray(foreignArray.rawForeignObject(meta.getLanguage()), meta, interop, cachedKlass);
143+
}
144+
145+
@Specialization(replaces = "doCached")
146+
@JavaType(Object.class)
147+
StaticObject generic(StaticObject foreignArray,
148+
@Bind("getMeta()") Meta meta,
149+
@CachedLibrary(limit = "LIMIT") InteropLibrary interop) {
150+
return copyToGuestArray(foreignArray.rawForeignObject(meta.getLanguage()), meta, interop, foreignArray.getKlass());
151+
}
152+
153+
private static StaticObject copyToGuestArray(Object rawForeignObject, Meta meta, InteropLibrary interop, Klass klass) {
154+
assert interop.hasArrayElements(rawForeignObject) || interop.hasBufferElements(rawForeignObject);
155+
156+
StaticObject result = null;
157+
try {
158+
if (klass == meta._boolean_array) {
159+
long arraySize = interop.getArraySize(rawForeignObject);
160+
boolean[] primitiveArray = new boolean[(int) arraySize];
161+
for (int i = 0; i < primitiveArray.length; i++) {
162+
primitiveArray[i] = (boolean) interop.readArrayElement(rawForeignObject, i);
163+
}
164+
result = StaticObject.createArray(meta._boolean_array, primitiveArray, meta.getContext());
165+
} else if (klass == meta._int_array) {
166+
long arraySize = interop.getArraySize(rawForeignObject);
167+
int[] primitiveArray = new int[(int) arraySize];
168+
for (int i = 0; i < primitiveArray.length; i++) {
169+
primitiveArray[i] = (int) interop.readArrayElement(rawForeignObject, i);
170+
}
171+
result = StaticObject.createArray(meta._int_array, primitiveArray, meta.getContext());
172+
} else if (klass == meta._long_array) {
173+
long arraySize = interop.getArraySize(rawForeignObject);
174+
long[] primitiveArray = new long[(int) arraySize];
175+
for (int i = 0; i < primitiveArray.length; i++) {
176+
primitiveArray[i] = (long) interop.readArrayElement(rawForeignObject, i);
177+
}
178+
result = StaticObject.createArray(meta._long_array, primitiveArray, meta.getContext());
179+
} else if (klass == meta._double_array) {
180+
long arraySize = interop.getArraySize(rawForeignObject);
181+
double[] primitiveArray = new double[(int) arraySize];
182+
for (int i = 0; i < primitiveArray.length; i++) {
183+
primitiveArray[i] = (double) interop.readArrayElement(rawForeignObject, i);
184+
}
185+
result = StaticObject.createArray(meta._double_array, primitiveArray, meta.getContext());
186+
} else if (klass == meta._float_array) {
187+
long arraySize = interop.getArraySize(rawForeignObject);
188+
float[] primitiveArray = new float[(int) arraySize];
189+
for (int i = 0; i < primitiveArray.length; i++) {
190+
primitiveArray[i] = (float) interop.readArrayElement(rawForeignObject, i);
191+
}
192+
result = StaticObject.createArray(meta._float_array, primitiveArray, meta.getContext());
193+
} else if (klass == meta._short_array) {
194+
long arraySize = interop.getArraySize(rawForeignObject);
195+
short[] primitiveArray = new short[(int) arraySize];
196+
for (int i = 0; i < primitiveArray.length; i++) {
197+
primitiveArray[i] = (short) interop.readArrayElement(rawForeignObject, i);
198+
}
199+
result = StaticObject.createArray(meta._short_array, primitiveArray, meta.getContext());
200+
} else if (klass == meta._byte_array) {
201+
if (interop.hasBufferElements(rawForeignObject)) {
202+
long bufferSize = interop.getBufferSize(rawForeignObject);
203+
byte[] primitiveArray = new byte[(int) bufferSize];
204+
interop.readBuffer(rawForeignObject, 0, primitiveArray, 0, (int) bufferSize);
205+
result = StaticObject.createArray(meta._byte_array, primitiveArray, meta.getContext());
206+
} else {
207+
long arraySize = interop.getArraySize(rawForeignObject);
208+
byte[] primitiveArray = new byte[(int) arraySize];
209+
for (int i = 0; i < primitiveArray.length; i++) {
210+
primitiveArray[i] = (byte) interop.readArrayElement(rawForeignObject, i);
211+
}
212+
result = StaticObject.createArray(meta._byte_array, primitiveArray, meta.getContext());
213+
}
214+
} else if (klass == meta._char_array) {
215+
long arraySize = interop.getArraySize(rawForeignObject);
216+
char[] primitiveArray = new char[(int) arraySize];
217+
for (int i = 0; i < primitiveArray.length; i++) {
218+
primitiveArray[i] = (char) interop.readArrayElement(rawForeignObject, i);
219+
}
220+
result = StaticObject.createArray(meta._char_array, primitiveArray, meta.getContext());
221+
}
222+
} catch (UnsupportedMessageException | InvalidArrayIndexException | InvalidBufferOffsetException ex) {
223+
CompilerDirectives.transferToInterpreterAndInvalidate();
224+
throw EspressoError.shouldNotReachHere("unsupported foreign array in ArraysSupport.vectorizedMismatch", ex);
225+
}
226+
return result;
227+
}
228+
}
229+
}

0 commit comments

Comments
 (0)