Skip to content

Commit

Permalink
[GR-50801] Implement new readBuffer interop API in Espresso.
Browse files Browse the repository at this point in the history
PullRequest: graal/16479
  • Loading branch information
javeleon committed Feb 5, 2024
2 parents 36af33b + c5e8969 commit 10b547b
Show file tree
Hide file tree
Showing 8 changed files with 699 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1463,6 +1463,26 @@ public static boolean isMemberExisting(Object receiver, String member) {
*/
public static native long getBufferSize(Object receiver) throws UnsupportedMessageException;

/**
* Reads bytes from the receiver object into the specified byte array.
* <p>
* The access is <em>not</em> guaranteed to be atomic. Therefore, this message is <em>not</em>
* thread-safe.
* <p>
* Invoking this message does not cause any observable side-effects.
*
* @param byteOffset offset in the buffer to start reading from.
* @param destination byte array to write the read bytes into.
* @param destinationOffset offset in the destination array to start writing from.
* @param length number of bytes to read.
* @throws InvalidBufferOffsetException if and only if
* <code>byteOffset < 0 || length < 0 || byteOffset + length > </code>{@link #getBufferSize(Object)}
* @throws UnsupportedMessageException if and only if {@link #hasBufferElements(Object)} returns
* {@code false}
* @since 24.0
*/
public static native void readBuffer(Object receiver, long byteOffset, byte[] destination, int destinationOffset, int length) throws InvalidBufferOffsetException, UnsupportedMessageException;

/**
* Reads the byte from the receiver object at the given byte offset from the start of the
* buffer.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -309,13 +309,26 @@ public static void ensureInitialized() {

// java.nio.ByteBuffer
public static final Symbol<Name> wrap = StaticSymbols.putName("wrap");
public static final Symbol<Name> order = StaticSymbols.putName("order");
public static final Symbol<Name> isReadOnly = StaticSymbols.putName("isReadOnly");
public static final Symbol<Name> getShort = StaticSymbols.putName("getShort");
public static final Symbol<Name> getInt = StaticSymbols.putName("getInt");
public static final Symbol<Name> getLong = StaticSymbols.putName("getLong");
public static final Symbol<Name> getFloat = StaticSymbols.putName("getFloat");
public static final Symbol<Name> getDouble = StaticSymbols.putName("getDouble");
public static final Symbol<Name> putShort = StaticSymbols.putName("putShort");
public static final Symbol<Name> putInt = StaticSymbols.putName("putInt");
public static final Symbol<Name> putLong = StaticSymbols.putName("putLong");
public static final Symbol<Name> putFloat = StaticSymbols.putName("putFloat");
public static final Symbol<Name> putDouble = StaticSymbols.putName("putDouble");

// java.nio.ByteOrder
public static final Symbol<Name> LITTLE_ENDIAN = StaticSymbols.putName("LITTLE_ENDIAN");

// java.nio.Buffer
public static final Symbol<Name> address = StaticSymbols.putName("address");
public static final Symbol<Name> capacity = StaticSymbols.putName("capacity");
public static final Symbol<Name> limit = StaticSymbols.putName("limit");
public static final Symbol<Name> wait = StaticSymbols.putName("wait");

// java.io.InputStream
Expand Down Expand Up @@ -1018,7 +1031,22 @@ public static void ensureInitialized() {
public static final Symbol<Signature> Class_String = StaticSymbols.putSignature(Type.java_lang_Class, Type.java_lang_String);
public static final Symbol<Signature> InputStream_String = StaticSymbols.putSignature(Type.java_io_InputStream, Type.java_lang_String);
public static final Symbol<Signature> _int_byte_array_int_int = StaticSymbols.putSignature(Type._int, Type._byte_array, Type._int, Type._int);
public static final Symbol<Signature> ByteBuffer_int_byte_array_int_int = StaticSymbols.putSignature(Type.java_nio_ByteBuffer, Type._int, Type._byte_array, Type._int, Type._int);
public static final Symbol<Signature> ByteBuffer_int_byte = StaticSymbols.putSignature(Type.java_nio_ByteBuffer, Type._int, Type._byte);
public static final Symbol<Signature> ByteBuffer_int_short = StaticSymbols.putSignature(Type.java_nio_ByteBuffer, Type._int, Type._short);
public static final Symbol<Signature> ByteBuffer_int_int = StaticSymbols.putSignature(Type.java_nio_ByteBuffer, Type._int, Type._int);
public static final Symbol<Signature> ByteBuffer_int_long = StaticSymbols.putSignature(Type.java_nio_ByteBuffer, Type._int, Type._long);
public static final Symbol<Signature> ByteBuffer_int_float = StaticSymbols.putSignature(Type.java_nio_ByteBuffer, Type._int, Type._float);
public static final Symbol<Signature> ByteBuffer_int_double = StaticSymbols.putSignature(Type.java_nio_ByteBuffer, Type._int, Type._double);
public static final Symbol<Signature> _byte_int = StaticSymbols.putSignature(Type._byte, Type._int);
public static final Symbol<Signature> _short_int = StaticSymbols.putSignature(Type._short, Type._int);
public static final Symbol<Signature> _int_int = StaticSymbols.putSignature(Type._int, Type._int);
public static final Symbol<Signature> _long_int = StaticSymbols.putSignature(Type._long, Type._int);
public static final Symbol<Signature> _float_int = StaticSymbols.putSignature(Type._float, Type._int);
public static final Symbol<Signature> _double_int = StaticSymbols.putSignature(Type._double, Type._int);
public static final Symbol<Signature> ByteBuffer_byte_array = StaticSymbols.putSignature(Type.java_nio_ByteBuffer, Type._byte_array);
public static final Symbol<Signature> ByteOrder = StaticSymbols.putSignature(Type.java_nio_ByteOrder);
public static final Symbol<Signature> ByteBuffer_ByteOrder = StaticSymbols.putSignature(Type.java_nio_ByteBuffer, Type.java_nio_ByteOrder);
public static final Symbol<Signature> _long_ClassLoader_String = StaticSymbols.putSignature(Type._long, Type.java_lang_ClassLoader, Type.java_lang_String);
public static final Symbol<Signature> _void_Exception = StaticSymbols.putSignature(Type._void, Type.java_lang_Exception);
public static final Symbol<Signature> _void_String_String_String_int = StaticSymbols.putSignature(Type._void, Type.java_lang_String, Type.java_lang_String, Type.java_lang_String, Type._int);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

package com.oracle.truffle.espresso.meta;

import com.oracle.truffle.espresso.runtime.dispatch.staticobject.ByteBufferInterop;
import org.graalvm.collections.Pair;

import com.oracle.truffle.api.CompilerDirectives;
Expand Down Expand Up @@ -50,8 +51,9 @@ public class InteropKlassesDispatch {
public static final int MAP_ENTRY_INTEROP_ID = 7;
public static final int MAP_INTEROP_ID = 8;
public static final int THROWABLE_INTEROP_ID = 9;
public static final int BYTE_BUFFER_INTEROP_ID = 10;

public static final int DISPATCH_TOTAL = THROWABLE_INTEROP_ID + 1;
public static final int DISPATCH_TOTAL = BYTE_BUFFER_INTEROP_ID + 1;

/**
* Represents all known guest classes with special interop library handling. Each entry in the
Expand All @@ -75,6 +77,7 @@ public class InteropKlassesDispatch {
new Pair[]{Pair.create(meta.java_util_Map, MapInterop.class)},
new Pair[]{Pair.create(meta.java_util_Map_Entry, MapEntryInterop.class)},
new Pair[]{Pair.create(meta.java_util_Iterator, IteratorInterop.class)},
new Pair[]{Pair.create(meta.java_nio_ByteBuffer, ByteBufferInterop.class)},
new Pair[]{Pair.create(meta.java_lang_InterruptedException, InterruptedExceptionInterop.class), Pair.create(meta.java_lang_Throwable, ThrowableInterop.class)}
};
}
Expand Down Expand Up @@ -136,6 +139,8 @@ public static int dispatchToId(Class<?> dispatch) {
return MAP_INTEROP_ID;
} else if (dispatch == ThrowableInterop.class) {
return THROWABLE_INTEROP_ID;
} else if (dispatch == ByteBufferInterop.class) {
return BYTE_BUFFER_INTEROP_ID;
} else {
throw EspressoError.shouldNotReachHere();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -393,16 +393,39 @@ public Meta(EspressoContext context) {
sun_nio_ch_DirectBuffer = knownKlass(Type.sun_nio_ch_DirectBuffer);
java_nio_Buffer_address = java_nio_Buffer.requireDeclaredField(Name.address, Type._long);
java_nio_Buffer_capacity = java_nio_Buffer.requireDeclaredField(Name.capacity, Type._int);
java_nio_Buffer_limit = java_nio_Buffer.requireDeclaredMethod(Name.limit, Signature._int);
java_nio_Buffer_isReadOnly = java_nio_Buffer.requireDeclaredMethod(Name.isReadOnly, Signature._boolean);

java_nio_ByteBuffer = knownKlass(Type.java_nio_ByteBuffer);
java_nio_ByteBuffer_wrap = java_nio_ByteBuffer.requireDeclaredMethod(Name.wrap, Signature.ByteBuffer_byte_array);
if (getJavaVersion().java13OrLater()) {
java_nio_ByteBuffer_get = java_nio_ByteBuffer.requireDeclaredMethod(Name.get, Signature.ByteBuffer_int_byte_array_int_int);
} else {
java_nio_ByteBuffer_get = null;
}
java_nio_ByteBuffer_getByte = java_nio_ByteBuffer.requireDeclaredMethod(Name.get, Signature._byte_int);
java_nio_ByteBuffer_getShort = java_nio_ByteBuffer.requireDeclaredMethod(Name.getShort, Signature._short_int);
java_nio_ByteBuffer_getInt = java_nio_ByteBuffer.requireDeclaredMethod(Name.getInt, Signature._int_int);
java_nio_ByteBuffer_getLong = java_nio_ByteBuffer.requireDeclaredMethod(Name.getLong, Signature._long_int);
java_nio_ByteBuffer_getFloat = java_nio_ByteBuffer.requireDeclaredMethod(Name.getFloat, Signature._float_int);
java_nio_ByteBuffer_getDouble = java_nio_ByteBuffer.requireDeclaredMethod(Name.getDouble, Signature._double_int);
java_nio_ByteBuffer_putByte = java_nio_ByteBuffer.requireDeclaredMethod(Name.put, Signature.ByteBuffer_int_byte);
java_nio_ByteBuffer_putShort = java_nio_ByteBuffer.requireDeclaredMethod(Name.putShort, Signature.ByteBuffer_int_short);
java_nio_ByteBuffer_putInt = java_nio_ByteBuffer.requireDeclaredMethod(Name.putInt, Signature.ByteBuffer_int_int);
java_nio_ByteBuffer_putLong = java_nio_ByteBuffer.requireDeclaredMethod(Name.putLong, Signature.ByteBuffer_int_long);
java_nio_ByteBuffer_putFloat = java_nio_ByteBuffer.requireDeclaredMethod(Name.putFloat, Signature.ByteBuffer_int_float);
java_nio_ByteBuffer_putDouble = java_nio_ByteBuffer.requireDeclaredMethod(Name.putDouble, Signature.ByteBuffer_int_double);
java_nio_ByteBuffer_order = java_nio_ByteBuffer.requireDeclaredMethod(Name.order, Signature.ByteOrder);
java_nio_ByteBuffer_setOrder = java_nio_ByteBuffer.requireDeclaredMethod(Name.order, Signature.ByteBuffer_ByteOrder);

java_nio_DirectByteBuffer = knownKlass(Type.java_nio_DirectByteBuffer);
java_nio_DirectByteBuffer_init_long_int = diff() //
.method(lower(20), Name._init_, Signature._void_long_int) //
.method(higher(21), Name._init_, Signature._void_long_long) //
.method(java_nio_DirectByteBuffer);
java_nio_ByteOrder = knownKlass(Type.java_nio_ByteOrder);
java_nio_ByteOrder_LITTLE_ENDIAN = java_nio_ByteOrder.requireDeclaredField(Name.LITTLE_ENDIAN, Type.java_nio_ByteOrder);
java_nio_ByteOrder_BIG_ENDIAN = java_nio_ByteOrder.requireDeclaredField(Name.BIG_ENDIAN, Type.java_nio_ByteOrder);

java_lang_Thread = knownKlass(Type.java_lang_Thread);
// The interrupted field is no longer hidden as of JDK14+
Expand Down Expand Up @@ -983,7 +1006,7 @@ private static void initializeEspressoClassInHierarchy(ObjectKlass klass) {
* <p>
* Espresso's Polyglot API (polyglot.jar) is injected on the boot CP, must be loaded after
* modules initialization.
*
* <p>
* The classes in module java.management become known after modules initialization.
*/
public void postSystemInit() {
Expand Down Expand Up @@ -1315,15 +1338,33 @@ private DiffVersionLoadHelper diff() {

public final ObjectKlass sun_nio_ch_DirectBuffer;
public final ObjectKlass java_nio_Buffer;
public final Method java_nio_Buffer_isReadOnly;
public final Field java_nio_Buffer_address;
public final Field java_nio_Buffer_capacity;
public final Method java_nio_Buffer_limit;

public final ObjectKlass java_nio_ByteBuffer;
public final Method java_nio_ByteBuffer_wrap;
public final Method java_nio_ByteBuffer_get;
public final Method java_nio_ByteBuffer_getByte;
public final Method java_nio_ByteBuffer_getShort;
public final Method java_nio_ByteBuffer_getInt;
public final Method java_nio_ByteBuffer_getLong;
public final Method java_nio_ByteBuffer_getFloat;
public final Method java_nio_ByteBuffer_getDouble;
public final Method java_nio_ByteBuffer_putByte;
public final Method java_nio_ByteBuffer_putShort;
public final Method java_nio_ByteBuffer_putInt;
public final Method java_nio_ByteBuffer_putLong;
public final Method java_nio_ByteBuffer_putFloat;
public final Method java_nio_ByteBuffer_putDouble;
public final Method java_nio_ByteBuffer_order;
public final Method java_nio_ByteBuffer_setOrder;
public final ObjectKlass java_nio_DirectByteBuffer;
public final Method java_nio_DirectByteBuffer_init_long_int;
public final ObjectKlass java_nio_ByteOrder;
public final Field java_nio_ByteOrder_LITTLE_ENDIAN;
public final Field java_nio_ByteOrder_BIG_ENDIAN;

public final ObjectKlass java_lang_BaseVirtualThread;
public final ObjectKlass java_lang_ThreadGroup;
Expand Down Expand Up @@ -1994,7 +2035,7 @@ public Class<?> resolveDispatch(Klass k) {
* asks the given class loader to perform the load, even for internal primitive types. This is
* the method to use when loading symbols that are not directly taken from a constant pool, for
* example, when loading a class whose name is given by a guest string.
*
* <p>
* This method is designed to fail if given the type symbol for primitives (eg: 'Z' for
* booleans).
*
Expand Down Expand Up @@ -2382,7 +2423,7 @@ public StaticObject boxPrimitive(Object hostPrimitive) {

/**
* Converts a boxed value to a boolean.
*
* <p>
* In {@link SpecComplianceMode#HOTSPOT HotSpot} compatibility-mode, the conversion is lax and
* will take the lower bits that fit in the primitive type or fill upper bits with 0. If the
* conversion is not possible, throws {@link EspressoError}.
Expand All @@ -2399,7 +2440,7 @@ public boolean asBoolean(Object value, boolean defaultIfNull) {

/**
* Converts a boxed value to a byte.
*
* <p>
* In {@link SpecComplianceMode#HOTSPOT HotSpot} compatibility-mode, the conversion is lax and
* will take the lower bits that fit in the primitive type or fill upper bits with 0. If the
* conversion is not possible, throws {@link EspressoError}.
Expand All @@ -2416,7 +2457,7 @@ public byte asByte(Object value, boolean defaultIfNull) {

/**
* Converts a boxed value to a short.
*
* <p>
* In {@link SpecComplianceMode#HOTSPOT HotSpot} compatibility-mode, the conversion is lax and
* will take the lower bits that fit in the primitive type or fill upper bits with 0. If the
* conversion is not possible, throws {@link EspressoError}.
Expand All @@ -2433,7 +2474,7 @@ public short asShort(Object value, boolean defaultIfNull) {

/**
* Converts a boxed value to a char.
*
* <p>
* In {@link SpecComplianceMode#HOTSPOT HotSpot} compatibility-mode, the conversion is lax and
* will take the lower bits that fit in the primitive type or fill upper bits with 0. If the
* conversion is not possible, throws {@link EspressoError}.
Expand All @@ -2450,7 +2491,7 @@ public char asChar(Object value, boolean defaultIfNull) {

/**
* Converts a boxed value to an int.
*
* <p>
* In {@link SpecComplianceMode#HOTSPOT HotSpot} compatibility-mode, the conversion is lax and
* will take the lower bits that fit in the primitive type or fill upper bits with 0. If the
* conversion is not possible, throws {@link EspressoError}.
Expand All @@ -2467,7 +2508,7 @@ public int asInt(Object value, boolean defaultIfNull) {

/**
* Converts a boxed value to a float.
*
* <p>
* In {@link SpecComplianceMode#HOTSPOT HotSpot} compatibility-mode, the conversion is lax and
* will take the lower bits that fit in the primitive type or fill upper bits with 0. If the
* conversion is not possible, throws {@link EspressoError}.
Expand All @@ -2484,7 +2525,7 @@ public float asFloat(Object value, boolean defaultIfNull) {

/**
* Converts a boxed value to a double.
*
* <p>
* In {@link SpecComplianceMode#HOTSPOT HotSpot} compatibility-mode, the conversion is lax and
* will take the lower bits that fit in the primitive type or fill upper bits with 0. If the
* conversion is not possible, throws {@link EspressoError}.
Expand All @@ -2501,7 +2542,7 @@ public double asDouble(Object value, boolean defaultIfNull) {

/**
* Converts a boxed value to a long.
*
* <p>
* In {@link SpecComplianceMode#HOTSPOT HotSpot} compatibility-mode, the conversion is lax and
* will take the lower bits that fit in the primitive type or fill upper bits with 0. If the
* conversion is not possible, throws {@link EspressoError}.
Expand All @@ -2518,7 +2559,7 @@ public long asLong(Object value, boolean defaultIfNull) {

/**
* Converts a Object value to a StaticObject.
*
* <p>
* In {@link SpecComplianceMode#HOTSPOT HotSpot} compatibility-mode, the conversion is lax and
* will return StaticObject.NULL when the Object value is not a StaticObject. If the conversion
* is not possible, throws {@link EspressoError}.
Expand All @@ -2532,7 +2573,7 @@ public StaticObject asObject(Object value) {

/**
* Bitwise conversion from a boxed value to a long.
*
* <p>
* In {@link SpecComplianceMode#HOTSPOT HotSpot} compatibility-mode, the conversion is lax and
* will fill the upper bits with 0. If the conversion is not possible, throws
* {@link EspressoError}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ public boolean java13OrEarlier() {
return version <= 13;
}

public boolean java13OrLater() {
return version >= 13;
}

public boolean java15OrLater() {
return version >= 15;
}
Expand Down
Loading

0 comments on commit 10b547b

Please sign in to comment.