diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java index 6c822d309410..8bee4d638a4a 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java @@ -2601,7 +2601,13 @@ private static void setArrayValues(JDWPContext context, PacketStream input, int case TagConstants.FLOAT -> input.readFloat(); case TagConstants.LONG -> input.readLong(); case TagConstants.DOUBLE -> input.readDouble(); - case TagConstants.ARRAY, TagConstants.STRING, TagConstants.OBJECT -> + case TagConstants.ARRAY, + TagConstants.STRING, + TagConstants.CLASS_LOADER, + TagConstants.CLASS_OBJECT, + TagConstants.THREAD, + TagConstants.THREAD_GROUP, + TagConstants.OBJECT -> context.getIds().fromId((int) input.readLong()); default -> throw new RuntimeException("should not reach here: " + tag); }; diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/quick/interop/ForeignArrayUtils.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/quick/interop/ForeignArrayUtils.java index 028ddb92bb50..1bd13b1c3cb5 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/quick/interop/ForeignArrayUtils.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/quick/interop/ForeignArrayUtils.java @@ -49,7 +49,7 @@ public static Object readForeignArrayElement(StaticObject array, int index, Espr throw EspressoError.shouldNotReachHere("readArrayElement on a non-array foreign object", e); } catch (InvalidArrayIndexException e) { exceptionProfile.enter(); - throw meta.throwExceptionWithMessage(meta.getMeta().java_lang_ArrayIndexOutOfBoundsException, e.getMessage()); + throw meta.throwExceptionWithMessage(meta.java_lang_ArrayIndexOutOfBoundsException, e.getMessage()); } } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/JDWPContextImpl.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/JDWPContextImpl.java index cbeaf8075598..b651b117746b 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/JDWPContextImpl.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/JDWPContextImpl.java @@ -38,10 +38,11 @@ import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.instrumentation.InstrumentableNode; import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.interop.InvalidArrayIndexException; import com.oracle.truffle.api.interop.UnsupportedMessageException; +import com.oracle.truffle.api.interop.UnsupportedTypeException; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.RootNode; -import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.espresso.EspressoLanguage; import com.oracle.truffle.espresso.blocking.EspressoLock; import com.oracle.truffle.espresso.classfile.bytecode.BytecodeStream; @@ -73,7 +74,7 @@ import com.oracle.truffle.espresso.nodes.BciProvider; import com.oracle.truffle.espresso.nodes.EspressoInstrumentableRootNode; import com.oracle.truffle.espresso.nodes.EspressoRootNode; -import com.oracle.truffle.espresso.nodes.quick.interop.ForeignArrayUtils; +import com.oracle.truffle.espresso.nodes.interop.ToEspressoNode; import com.oracle.truffle.espresso.runtime.staticobject.StaticObject; import com.oracle.truffle.espresso.threads.State; import com.oracle.truffle.espresso.vm.InterpreterToVM; @@ -472,45 +473,59 @@ public void setStaticFieldValue(FieldRef field, Object value) { @Override public Object getArrayValue(Object array, int index) { StaticObject arrayRef = (StaticObject) array; - Object value; + Klass componentType = ((ArrayKlass) arrayRef.getKlass()).getComponentType(); + Meta meta = componentType.getMeta(); if (arrayRef.isForeignObject()) { - value = ForeignArrayUtils.readForeignArrayElement(arrayRef, index, context.getLanguage(), context.getMeta(), InteropLibrary.getUncached(), BranchProfile.create()); - if (!(value instanceof StaticObject)) { - // For JDWP we have to have a ref type, so here we have to create a copy - // value when possible as a StaticObject based on the foreign type. - // Note: we only support Host String conversion for now - if (value instanceof String) { - return context.getMeta().toGuestString((String) value); - } else { - throw new IllegalStateException("foreign object conversion not supported"); - } + Object value = null; + try { + value = InteropLibrary.getUncached().readArrayElement(arrayRef.rawForeignObject(arrayRef.getKlass().getLanguage()), index); + return ToEspressoNode.getUncachedToEspresso(componentType, meta).execute(value); + } catch (UnsupportedMessageException e) { + throw EspressoError.shouldNotReachHere("readArrayElement on a non-array foreign object", e); + } catch (InvalidArrayIndexException e) { + throw meta.throwExceptionWithMessage(meta.java_lang_ArrayIndexOutOfBoundsException, e.getMessage()); + } catch (UnsupportedTypeException e) { + throw meta.throwExceptionWithMessage(meta.java_lang_ClassCastException, "%s cannot be cast to %s", value, componentType.getTypeAsString()); } - } else if (((ArrayKlass) arrayRef.getKlass()).getComponentType().isPrimitive()) { + } else if (componentType.isPrimitive()) { // primitive array type needs wrapping Object boxedArray = getUnboxedArray(array); - value = Array.get(boxedArray, index); + return Array.get(boxedArray, index); } else { - value = arrayRef.get(context.getLanguage(), index); + return arrayRef.get(context.getLanguage(), index); } - return value; } @Override public void setArrayValue(Object array, int index, Object value) { StaticObject arrayRef = (StaticObject) array; - byte tag = getTag(value); - switch (tag) { - case TagConstants.BOOLEAN -> context.getInterpreterToVM().setArrayByte(context.getLanguage(), (boolean) value ? (byte) 1 : 0, index, arrayRef); - case TagConstants.BYTE -> context.getInterpreterToVM().setArrayByte(context.getLanguage(), (byte) value, index, arrayRef); - case TagConstants.SHORT -> context.getInterpreterToVM().setArrayShort(context.getLanguage(), (short) value, index, arrayRef); - case TagConstants.CHAR -> context.getInterpreterToVM().setArrayChar(context.getLanguage(), (char) value, index, arrayRef); - case TagConstants.INT -> context.getInterpreterToVM().setArrayInt(context.getLanguage(), (int) value, index, arrayRef); - case TagConstants.FLOAT -> context.getInterpreterToVM().setArrayFloat(context.getLanguage(), (float) value, index, arrayRef); - case TagConstants.LONG -> context.getInterpreterToVM().setArrayLong(context.getLanguage(), (long) value, index, arrayRef); - case TagConstants.DOUBLE -> context.getInterpreterToVM().setArrayDouble(context.getLanguage(), (double) value, index, arrayRef); - case TagConstants.ARRAY, TagConstants.STRING, TagConstants.OBJECT -> - context.getInterpreterToVM().setArrayObject(context.getLanguage(), (StaticObject) value, index, arrayRef); - default -> throw new RuntimeException("should not reach here: " + tag); + Klass componentType = ((ArrayKlass) arrayRef.getKlass()).getComponentType(); + Meta meta = componentType.getMeta(); + if (arrayRef.isForeignObject()) { + try { + Object unWrappedValue = value; + if (value instanceof StaticObject staticObject) { + unWrappedValue = staticObject.isForeignObject() ? staticObject.rawForeignObject(meta.getLanguage()) : staticObject; + } + InteropLibrary.getUncached().writeArrayElement(arrayRef.rawForeignObject(arrayRef.getKlass().getLanguage()), index, unWrappedValue); + } catch (UnsupportedMessageException e) { + throw EspressoError.shouldNotReachHere("writeArrayElement on a non-array foreign object", e); + } catch (InvalidArrayIndexException e) { + throw meta.throwExceptionWithMessage(meta.java_lang_ArrayIndexOutOfBoundsException, e.getMessage()); + } catch (UnsupportedTypeException e) { + throw meta.throwExceptionWithMessage(meta.java_lang_ClassCastException, "%s cannot be cast to %s", value, componentType.getTypeAsString()); + } + } else if (componentType.isPrimitive()) { + // primitive array type needs wrapping + Object boxedArray = getUnboxedArray(array); + // special handling for boolean because they're stored as byte + if (value instanceof Boolean aBoolean) { + Array.set(boxedArray, index, aBoolean ? (byte) 1 : (byte) 0); + } else { + Array.set(boxedArray, index, value); + } + } else { + context.getInterpreterToVM().setArrayObject(meta.getLanguage(), (StaticObject) value, index, arrayRef); } }