Skip to content

Commit fa6ba04

Browse files
committed
[GR-63056] Fix jdwp crash when writing a class object array.
PullRequest: graal/20534
2 parents 3216752 + bfc1041 commit fa6ba04

File tree

3 files changed

+53
-32
lines changed

3 files changed

+53
-32
lines changed

espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2601,7 +2601,13 @@ private static void setArrayValues(JDWPContext context, PacketStream input, int
26012601
case TagConstants.FLOAT -> input.readFloat();
26022602
case TagConstants.LONG -> input.readLong();
26032603
case TagConstants.DOUBLE -> input.readDouble();
2604-
case TagConstants.ARRAY, TagConstants.STRING, TagConstants.OBJECT ->
2604+
case TagConstants.ARRAY,
2605+
TagConstants.STRING,
2606+
TagConstants.CLASS_LOADER,
2607+
TagConstants.CLASS_OBJECT,
2608+
TagConstants.THREAD,
2609+
TagConstants.THREAD_GROUP,
2610+
TagConstants.OBJECT ->
26052611
context.getIds().fromId((int) input.readLong());
26062612
default -> throw new RuntimeException("should not reach here: " + tag);
26072613
};

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/quick/interop/ForeignArrayUtils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public static Object readForeignArrayElement(StaticObject array, int index, Espr
4949
throw EspressoError.shouldNotReachHere("readArrayElement on a non-array foreign object", e);
5050
} catch (InvalidArrayIndexException e) {
5151
exceptionProfile.enter();
52-
throw meta.throwExceptionWithMessage(meta.getMeta().java_lang_ArrayIndexOutOfBoundsException, e.getMessage());
52+
throw meta.throwExceptionWithMessage(meta.java_lang_ArrayIndexOutOfBoundsException, e.getMessage());
5353
}
5454
}
5555

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/JDWPContextImpl.java

Lines changed: 45 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,11 @@
3838
import com.oracle.truffle.api.frame.Frame;
3939
import com.oracle.truffle.api.instrumentation.InstrumentableNode;
4040
import com.oracle.truffle.api.interop.InteropLibrary;
41+
import com.oracle.truffle.api.interop.InvalidArrayIndexException;
4142
import com.oracle.truffle.api.interop.UnsupportedMessageException;
43+
import com.oracle.truffle.api.interop.UnsupportedTypeException;
4244
import com.oracle.truffle.api.nodes.Node;
4345
import com.oracle.truffle.api.nodes.RootNode;
44-
import com.oracle.truffle.api.profiles.BranchProfile;
4546
import com.oracle.truffle.espresso.EspressoLanguage;
4647
import com.oracle.truffle.espresso.blocking.EspressoLock;
4748
import com.oracle.truffle.espresso.classfile.bytecode.BytecodeStream;
@@ -73,7 +74,7 @@
7374
import com.oracle.truffle.espresso.nodes.BciProvider;
7475
import com.oracle.truffle.espresso.nodes.EspressoInstrumentableRootNode;
7576
import com.oracle.truffle.espresso.nodes.EspressoRootNode;
76-
import com.oracle.truffle.espresso.nodes.quick.interop.ForeignArrayUtils;
77+
import com.oracle.truffle.espresso.nodes.interop.ToEspressoNode;
7778
import com.oracle.truffle.espresso.runtime.staticobject.StaticObject;
7879
import com.oracle.truffle.espresso.threads.State;
7980
import com.oracle.truffle.espresso.vm.InterpreterToVM;
@@ -472,45 +473,59 @@ public void setStaticFieldValue(FieldRef field, Object value) {
472473
@Override
473474
public Object getArrayValue(Object array, int index) {
474475
StaticObject arrayRef = (StaticObject) array;
475-
Object value;
476+
Klass componentType = ((ArrayKlass) arrayRef.getKlass()).getComponentType();
477+
Meta meta = componentType.getMeta();
476478
if (arrayRef.isForeignObject()) {
477-
value = ForeignArrayUtils.readForeignArrayElement(arrayRef, index, context.getLanguage(), context.getMeta(), InteropLibrary.getUncached(), BranchProfile.create());
478-
if (!(value instanceof StaticObject)) {
479-
// For JDWP we have to have a ref type, so here we have to create a copy
480-
// value when possible as a StaticObject based on the foreign type.
481-
// Note: we only support Host String conversion for now
482-
if (value instanceof String) {
483-
return context.getMeta().toGuestString((String) value);
484-
} else {
485-
throw new IllegalStateException("foreign object conversion not supported");
486-
}
479+
Object value = null;
480+
try {
481+
value = InteropLibrary.getUncached().readArrayElement(arrayRef.rawForeignObject(arrayRef.getKlass().getLanguage()), index);
482+
return ToEspressoNode.getUncachedToEspresso(componentType, meta).execute(value);
483+
} catch (UnsupportedMessageException e) {
484+
throw EspressoError.shouldNotReachHere("readArrayElement on a non-array foreign object", e);
485+
} catch (InvalidArrayIndexException e) {
486+
throw meta.throwExceptionWithMessage(meta.java_lang_ArrayIndexOutOfBoundsException, e.getMessage());
487+
} catch (UnsupportedTypeException e) {
488+
throw meta.throwExceptionWithMessage(meta.java_lang_ClassCastException, "%s cannot be cast to %s", value, componentType.getTypeAsString());
487489
}
488-
} else if (((ArrayKlass) arrayRef.getKlass()).getComponentType().isPrimitive()) {
490+
} else if (componentType.isPrimitive()) {
489491
// primitive array type needs wrapping
490492
Object boxedArray = getUnboxedArray(array);
491-
value = Array.get(boxedArray, index);
493+
return Array.get(boxedArray, index);
492494
} else {
493-
value = arrayRef.get(context.getLanguage(), index);
495+
return arrayRef.get(context.getLanguage(), index);
494496
}
495-
return value;
496497
}
497498

498499
@Override
499500
public void setArrayValue(Object array, int index, Object value) {
500501
StaticObject arrayRef = (StaticObject) array;
501-
byte tag = getTag(value);
502-
switch (tag) {
503-
case TagConstants.BOOLEAN -> context.getInterpreterToVM().setArrayByte(context.getLanguage(), (boolean) value ? (byte) 1 : 0, index, arrayRef);
504-
case TagConstants.BYTE -> context.getInterpreterToVM().setArrayByte(context.getLanguage(), (byte) value, index, arrayRef);
505-
case TagConstants.SHORT -> context.getInterpreterToVM().setArrayShort(context.getLanguage(), (short) value, index, arrayRef);
506-
case TagConstants.CHAR -> context.getInterpreterToVM().setArrayChar(context.getLanguage(), (char) value, index, arrayRef);
507-
case TagConstants.INT -> context.getInterpreterToVM().setArrayInt(context.getLanguage(), (int) value, index, arrayRef);
508-
case TagConstants.FLOAT -> context.getInterpreterToVM().setArrayFloat(context.getLanguage(), (float) value, index, arrayRef);
509-
case TagConstants.LONG -> context.getInterpreterToVM().setArrayLong(context.getLanguage(), (long) value, index, arrayRef);
510-
case TagConstants.DOUBLE -> context.getInterpreterToVM().setArrayDouble(context.getLanguage(), (double) value, index, arrayRef);
511-
case TagConstants.ARRAY, TagConstants.STRING, TagConstants.OBJECT ->
512-
context.getInterpreterToVM().setArrayObject(context.getLanguage(), (StaticObject) value, index, arrayRef);
513-
default -> throw new RuntimeException("should not reach here: " + tag);
502+
Klass componentType = ((ArrayKlass) arrayRef.getKlass()).getComponentType();
503+
Meta meta = componentType.getMeta();
504+
if (arrayRef.isForeignObject()) {
505+
try {
506+
Object unWrappedValue = value;
507+
if (value instanceof StaticObject staticObject) {
508+
unWrappedValue = staticObject.isForeignObject() ? staticObject.rawForeignObject(meta.getLanguage()) : staticObject;
509+
}
510+
InteropLibrary.getUncached().writeArrayElement(arrayRef.rawForeignObject(arrayRef.getKlass().getLanguage()), index, unWrappedValue);
511+
} catch (UnsupportedMessageException e) {
512+
throw EspressoError.shouldNotReachHere("writeArrayElement on a non-array foreign object", e);
513+
} catch (InvalidArrayIndexException e) {
514+
throw meta.throwExceptionWithMessage(meta.java_lang_ArrayIndexOutOfBoundsException, e.getMessage());
515+
} catch (UnsupportedTypeException e) {
516+
throw meta.throwExceptionWithMessage(meta.java_lang_ClassCastException, "%s cannot be cast to %s", value, componentType.getTypeAsString());
517+
}
518+
} else if (componentType.isPrimitive()) {
519+
// primitive array type needs wrapping
520+
Object boxedArray = getUnboxedArray(array);
521+
// special handling for boolean because they're stored as byte
522+
if (value instanceof Boolean aBoolean) {
523+
Array.set(boxedArray, index, aBoolean ? (byte) 1 : (byte) 0);
524+
} else {
525+
Array.set(boxedArray, index, value);
526+
}
527+
} else {
528+
context.getInterpreterToVM().setArrayObject(meta.getLanguage(), (StaticObject) value, index, arrayRef);
514529
}
515530
}
516531

0 commit comments

Comments
 (0)