|
38 | 38 | import com.oracle.truffle.api.frame.Frame; |
39 | 39 | import com.oracle.truffle.api.instrumentation.InstrumentableNode; |
40 | 40 | import com.oracle.truffle.api.interop.InteropLibrary; |
| 41 | +import com.oracle.truffle.api.interop.InvalidArrayIndexException; |
41 | 42 | import com.oracle.truffle.api.interop.UnsupportedMessageException; |
| 43 | +import com.oracle.truffle.api.interop.UnsupportedTypeException; |
42 | 44 | import com.oracle.truffle.api.nodes.Node; |
43 | 45 | import com.oracle.truffle.api.nodes.RootNode; |
44 | | -import com.oracle.truffle.api.profiles.BranchProfile; |
45 | 46 | import com.oracle.truffle.espresso.EspressoLanguage; |
46 | 47 | import com.oracle.truffle.espresso.blocking.EspressoLock; |
47 | 48 | import com.oracle.truffle.espresso.classfile.bytecode.BytecodeStream; |
|
73 | 74 | import com.oracle.truffle.espresso.nodes.BciProvider; |
74 | 75 | import com.oracle.truffle.espresso.nodes.EspressoInstrumentableRootNode; |
75 | 76 | 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; |
77 | 78 | import com.oracle.truffle.espresso.runtime.staticobject.StaticObject; |
78 | 79 | import com.oracle.truffle.espresso.threads.State; |
79 | 80 | import com.oracle.truffle.espresso.vm.InterpreterToVM; |
@@ -472,45 +473,59 @@ public void setStaticFieldValue(FieldRef field, Object value) { |
472 | 473 | @Override |
473 | 474 | public Object getArrayValue(Object array, int index) { |
474 | 475 | StaticObject arrayRef = (StaticObject) array; |
475 | | - Object value; |
| 476 | + Klass componentType = ((ArrayKlass) arrayRef.getKlass()).getComponentType(); |
| 477 | + Meta meta = componentType.getMeta(); |
476 | 478 | 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()); |
487 | 489 | } |
488 | | - } else if (((ArrayKlass) arrayRef.getKlass()).getComponentType().isPrimitive()) { |
| 490 | + } else if (componentType.isPrimitive()) { |
489 | 491 | // primitive array type needs wrapping |
490 | 492 | Object boxedArray = getUnboxedArray(array); |
491 | | - value = Array.get(boxedArray, index); |
| 493 | + return Array.get(boxedArray, index); |
492 | 494 | } else { |
493 | | - value = arrayRef.get(context.getLanguage(), index); |
| 495 | + return arrayRef.get(context.getLanguage(), index); |
494 | 496 | } |
495 | | - return value; |
496 | 497 | } |
497 | 498 |
|
498 | 499 | @Override |
499 | 500 | public void setArrayValue(Object array, int index, Object value) { |
500 | 501 | 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); |
514 | 529 | } |
515 | 530 | } |
516 | 531 |
|
|
0 commit comments