Skip to content

Commit 196031d

Browse files
committed
Additions for new foreign API capabilities in jdk 25:
* Foreign API supports passing raw pointers into primitive arrays. * Passed buffers now writes back to the original guest object. * More robust 'stubID <-> stub' mechanisms * Passing a heap pointer is now encoded in the shuffle array. * CloseScope is now implemented as a no-op, warning of this once per context
1 parent e6d9e3f commit 196031d

File tree

14 files changed

+306
-26
lines changed

14 files changed

+306
-26
lines changed

espresso/src/com.oracle.truffle.espresso.launcher/src/com/oracle/truffle/espresso/launcher/EspressoLauncher.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -276,10 +276,6 @@ protected List<String> preprocessArguments(List<String> arguments, Map<String, S
276276
case "-Xshare:off":
277277
// ignore
278278
break;
279-
case "-XX:+UseJVMCICompiler":
280-
case "-XX:-UseJVMCICompiler":
281-
getError().println("Ignoring " + arg);
282-
break;
283279

284280
case "-XX:+PauseOnExit":
285281
pauseOnExit = true;
@@ -435,6 +431,10 @@ private void parseArgFile(String pathArg, List<String> expanded) {
435431
"WhiteBoxAPI",
436432
"EnableJVMCI");
437433

434+
private static final Set<String> ignoredXXOptions = Set.of(
435+
"UseJVMCICompiler",
436+
"EnableDynamicAgentLoading");
437+
438438
private void handleXXArg(String fullArg, ArrayList<String> unrecognized) {
439439
String arg = fullArg.substring("-XX:".length());
440440
String name;
@@ -451,6 +451,10 @@ private void handleXXArg(String fullArg, ArrayList<String> unrecognized) {
451451
name = arg.substring(0, idx);
452452
value = arg.substring(idx + 1);
453453
}
454+
if (ignoredXXOptions.contains(name)) {
455+
getError().println("Ignoring " + arg);
456+
return;
457+
}
454458
if (knownPassThroughOptions.contains(name)) {
455459
espressoOptions.put("java." + name, value);
456460
return;

espresso/src/com.oracle.truffle.espresso.libjavavm/src/com/oracle/truffle/espresso/libjavavm/Arguments.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ private Arguments() {
7777
"TieredStopAtLevel",
7878
"MaxMetaspaceSize",
7979
"HeapDumpOnOutOfMemoryError",
80-
"UseJVMCICompiler");
80+
"UseJVMCICompiler",
81+
"EnableDynamicAgentLoading");
8182

8283
private static final Map<String, String> MAPPED_XX_OPTIONS = Map.of(
8384
"TieredCompilation", "engine.MultiTier");

espresso/src/com.oracle.truffle.espresso.mokapot/src/mokapot.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1419,7 +1419,7 @@ JNIEXPORT void JNICALL JVM_BeforeHalt() {
14191419
JNIEXPORT void JNICALL
14201420
JVM_ExpandStackFrameInfo(JNIEnv *env, jobject obj) {
14211421
IMPLEMENTED(JVM_ExpandStackFrameInfo);
1422-
return (*getEnv())->JVM_ExpandStackFrameInfo(env, obj);
1422+
(*getEnv())->JVM_ExpandStackFrameInfo(env, obj);
14231423
}
14241424

14251425
JNIEXPORT jobject JNICALL JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mode,

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ClassRegistry.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ Klass loadKlass(EspressoContext context, Symbol<Type> type, StaticObject protect
348348
}
349349
assert entry != null;
350350
StaticObject classLoader = getClassLoader();
351-
if (!StaticObject.isNull(classLoader) && context.getJavaVersion().java21OrEarlier()) {
351+
if (!StaticObject.isNull(classLoader) && context.getJavaVersion().java23OrEarlier()) {
352352
entry.checkPackageAccess(env.getMeta(), classLoader, protectionDomain);
353353
}
354354
return entry.klass();

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/jni/RawBuffer.java

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,17 @@
2727
import java.nio.charset.CharsetEncoder;
2828
import java.nio.charset.CoderResult;
2929
import java.nio.charset.StandardCharsets;
30+
import java.util.ArrayList;
3031

32+
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
3133
import com.oracle.truffle.api.interop.TruffleObject;
34+
import com.oracle.truffle.espresso.classfile.JavaKind;
3235
import com.oracle.truffle.espresso.classfile.descriptors.ByteSequence;
3336
import com.oracle.truffle.espresso.ffi.nfi.NativeUtils;
37+
import com.oracle.truffle.espresso.impl.ArrayKlass;
3438
import com.oracle.truffle.espresso.meta.EspressoError;
39+
import com.oracle.truffle.espresso.runtime.EspressoContext;
40+
import com.oracle.truffle.espresso.runtime.staticobject.StaticObject;
3541

3642
public final class RawBuffer implements AutoCloseable {
3743
private ByteBuffer buffer;
@@ -86,9 +92,146 @@ public TruffleObject pointer() {
8692
return pointer;
8793
}
8894

95+
@TruffleBoundary
96+
public static RawBuffer getNativeHeapPointer(StaticObject obj, EspressoContext ctx) {
97+
assert obj.getKlass().isArray();
98+
JavaKind componentKind = ((ArrayKlass) obj.getKlass()).getComponentType().getJavaKind();
99+
ByteBuffer bb = NativeUtils.allocateDirect(obj.length(ctx.getLanguage()) * componentKind.getByteCount());
100+
switch (componentKind) {
101+
case Boolean -> {
102+
boolean[] array = obj.unwrap(ctx.getLanguage());
103+
for (boolean b : array) {
104+
bb.put((byte) (b ? 1 : 0));
105+
}
106+
}
107+
case Byte -> {
108+
byte[] array = obj.unwrap(ctx.getLanguage());
109+
for (byte b : array) {
110+
bb.put(b);
111+
}
112+
}
113+
case Short -> {
114+
short[] array = obj.unwrap(ctx.getLanguage());
115+
for (short s : array) {
116+
bb.putShort(s);
117+
}
118+
}
119+
case Char -> {
120+
char[] array = obj.unwrap(ctx.getLanguage());
121+
for (char c : array) {
122+
bb.putChar(c);
123+
}
124+
}
125+
case Int -> {
126+
int[] array = obj.unwrap(ctx.getLanguage());
127+
for (int i : array) {
128+
bb.putInt(i);
129+
}
130+
}
131+
case Float -> {
132+
float[] array = obj.unwrap(ctx.getLanguage());
133+
for (float f : array) {
134+
bb.putFloat(f);
135+
}
136+
}
137+
case Long -> {
138+
long[] array = obj.unwrap(ctx.getLanguage());
139+
for (long l : array) {
140+
bb.putLong(l);
141+
}
142+
}
143+
case Double -> {
144+
double[] array = obj.unwrap(ctx.getLanguage());
145+
for (double d : array) {
146+
bb.putDouble(d);
147+
}
148+
}
149+
default -> throw ctx.getMeta().throwExceptionWithMessage(ctx.getMeta().java_lang_IllegalArgumentException, "Unsupported java heap access in downcall stub: " + obj.getKlass());
150+
}
151+
return new RawBuffer(bb, NativeUtils.byteBufferPointer(bb));
152+
}
153+
154+
@TruffleBoundary
155+
public void writeBack(StaticObject obj, EspressoContext ctx) {
156+
assert obj.getKlass().isArray();
157+
JavaKind componentKind = ((ArrayKlass) obj.getKlass()).getComponentType().getJavaKind();
158+
ByteBuffer bb = buffer.rewind();
159+
switch (componentKind) {
160+
case Boolean -> {
161+
boolean[] array = obj.unwrap(ctx.getLanguage());
162+
for (int i = 0; i < array.length; i++) {
163+
array[i] = bb.get() != 0;
164+
}
165+
}
166+
case Byte -> {
167+
byte[] array = obj.unwrap(ctx.getLanguage());
168+
for (int i = 0; i < array.length; i++) {
169+
array[i] = bb.get();
170+
}
171+
}
172+
case Short -> {
173+
short[] array = obj.unwrap(ctx.getLanguage());
174+
for (int i = 0; i < array.length; i++) {
175+
array[i] = bb.getShort();
176+
}
177+
}
178+
case Char -> {
179+
char[] array = obj.unwrap(ctx.getLanguage());
180+
for (int i = 0; i < array.length; i++) {
181+
array[i] = bb.getChar();
182+
}
183+
}
184+
case Int -> {
185+
int[] array = obj.unwrap(ctx.getLanguage());
186+
for (int i = 0; i < array.length; i++) {
187+
array[i] = bb.getInt();
188+
}
189+
}
190+
case Float -> {
191+
float[] array = obj.unwrap(ctx.getLanguage());
192+
for (int i = 0; i < array.length; i++) {
193+
array[i] = bb.getFloat();
194+
}
195+
}
196+
case Long -> {
197+
long[] array = obj.unwrap(ctx.getLanguage());
198+
for (int i = 0; i < array.length; i++) {
199+
array[i] = bb.getLong();
200+
}
201+
}
202+
case Double -> {
203+
double[] array = obj.unwrap(ctx.getLanguage());
204+
for (int i = 0; i < array.length; i++) {
205+
array[i] = bb.getDouble();
206+
}
207+
}
208+
default -> throw ctx.getMeta().throwExceptionWithMessage(ctx.getMeta().java_lang_IllegalArgumentException, "Unsupported java heap access in downcall stub: " + obj.getKlass());
209+
}
210+
}
211+
89212
@Override
90213
public void close() {
91214
buffer.clear();
92215
this.buffer = null;
93216
}
217+
218+
public static class Buffers {
219+
private final ArrayList<RawBuffer> buffers = new ArrayList<>(0);
220+
private final ArrayList<StaticObject> arrays = new ArrayList<>(0);
221+
222+
public void writeBack(EspressoContext ctx) {
223+
assert buffers.size() == arrays.size();
224+
for (int i = 0; i < buffers.size(); i++) {
225+
RawBuffer b = buffers.get(i);
226+
StaticObject target = arrays.get(i);
227+
b.writeBack(target, ctx);
228+
b.close();
229+
}
230+
}
231+
232+
public void add(RawBuffer b, StaticObject obj) {
233+
buffers.add(b);
234+
arrays.add(obj);
235+
}
236+
}
94237
}

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/methodhandle/MHLinkToNativeNode.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,13 @@ protected Object doUncached(Object[] args) {
6969
assert args.length == argCount;
7070
long downcallStubId = getDowncallStubId(args);
7171
EspressoContext context = getContext();
72-
DowncallStubs.DowncallStub stub = context.getDowncallStubs().getStub(downcallStubId);
72+
DowncallStubs.DowncallStub stub = context.getDowncallStubs().getStub(downcallStubId, context);
7373
return stub.uncachedCall(args, context);
7474
}
7575

7676
protected DowncallStubNode createDowncallStubNode(long downcallStubId) {
7777
EspressoContext context = getContext();
78-
DowncallStubs.DowncallStub stub = context.getDowncallStubs().getStub(downcallStubId);
78+
DowncallStubs.DowncallStub stub = context.getDowncallStubs().getStub(downcallStubId, context);
7979
return DowncallStubNode.create(stub, context.getNativeAccess());
8080
}
8181

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/panama/DowncallStubNode.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import com.oracle.truffle.api.nodes.Node;
3131
import com.oracle.truffle.espresso.ffi.NativeAccess;
3232
import com.oracle.truffle.espresso.ffi.SignatureCallNode;
33+
import com.oracle.truffle.espresso.jni.RawBuffer;
3334
import com.oracle.truffle.espresso.meta.EspressoError;
3435
import com.oracle.truffle.espresso.runtime.EspressoContext;
3536
import com.oracle.truffle.espresso.runtime.panama.DowncallStubs.DowncallStub;
@@ -51,18 +52,22 @@ public static DowncallStubNode create(DowncallStub stub, NativeAccess access) {
5152
return new DowncallStubNode(stub, access.createSignatureCall(stub.signature));
5253
}
5354

55+
@SuppressWarnings("try") // Throwable.addSuppressed blocklisted by SVM.
5456
public Object call(Object[] args) {
5557
EspressoContext context = EspressoContext.get(this);
5658
Object target = downcallStub.getTarget(args, context);
59+
RawBuffer.Buffers bb = new RawBuffer.Buffers();
5760
try {
58-
Object result = signatureCall.call(target, downcallStub.processArgs(args));
61+
Object result = signatureCall.call(target, downcallStub.processArgs(args, bb, context));
5962
if (downcallStub.hasCapture()) {
6063
downcallStub.captureState(args, interop, context);
6164
}
6265
return result;
6366
} catch (ArityException | UnsupportedTypeException | UnsupportedMessageException e) {
6467
CompilerDirectives.transferToInterpreterAndInvalidate();
6568
throw EspressoError.shouldNotReachHere(e);
69+
} finally {
70+
bb.writeBack(context);
6671
}
6772
}
6873
}

0 commit comments

Comments
 (0)