package com.oracle.svm.jni;
import java.lang.reflect.Array;
import org.graalvm.compiler.serviceprovider.GraalUnsafeAccess;
import org.graalvm.nativeimage.c.type.CCharPointer;
import org.graalvm.word.PointerBase;
import org.graalvm.word.WordBase;
import org.graalvm.word.WordFactory;
import com.oracle.svm.core.StaticFieldsSupport;
import com.oracle.svm.core.config.ConfigurationValues;
import com.oracle.svm.jni.access.JNIAccessibleField;
import com.oracle.svm.jni.access.JNINativeLinkage;
import com.oracle.svm.jni.nativeapi.JNIEnvironment;
import com.oracle.svm.jni.nativeapi.JNIFieldId;
import com.oracle.svm.jni.nativeapi.JNIObjectHandle;
import jdk.vm.ci.meta.JavaKind;
import sun.misc.Unsafe;
public final class JNIGeneratedMethodSupport {
private static final Unsafe UNSAFE = GraalUnsafeAccess.getUnsafe();
static PointerBase nativeCallAddress(JNINativeLinkage linkage) {
return linkage.getOrFindEntryPoint();
}
static int nativeCallPrologue() {
return JNIObjectHandles.pushLocalFrame(JNIObjectHandles.NATIVE_CALL_MIN_LOCAL_HANDLE_CAPACITY);
}
static void nativeCallEpilogue(int handleFrame) {
JNIObjectHandles.popLocalFramesIncluding(handleFrame);
}
static JNIEnvironment environment() {
return JNIThreadLocalEnvironment.getAddress();
}
static JNIObjectHandle boxObjectInLocalHandle(Object obj) {
return JNIObjectHandles.createLocal(obj);
}
static Object unboxHandle(JNIObjectHandle handle) {
return JNIObjectHandles.getObject(handle);
}
static WordBase getFieldOffsetFromId(JNIFieldId fieldId) {
return JNIAccessibleField.getOffsetFromId(fieldId);
}
static byte[] getStaticPrimitiveFieldsArray() {
return StaticFieldsSupport.getStaticPrimitiveFields();
}
static Object[] getStaticObjectFieldsArray() {
return StaticFieldsSupport.getStaticObjectFields();
}
static void setPendingException(Throwable t) {
JNIThreadLocalPendingException.set(t);
}
static Throwable getAndClearPendingException() {
Throwable t = JNIThreadLocalPendingException.get();
JNIThreadLocalPendingException.clear();
return t;
}
static void rethrowPendingException() throws Throwable {
Throwable t = getAndClearPendingException();
if (t != null) {
throw t;
}
}
static PointerBase pinArrayAndGetAddress(Object array, CCharPointer isCopy) throws Throwable {
if (array.getClass().isArray()) {
if (isCopy.isNonNull()) {
isCopy.write((byte) 0);
}
return JNIThreadLocalPinnedObjects.pinArrayAndGetAddress(array);
}
return WordFactory.nullPointer();
}
static boolean unpinArrayByAddress(PointerBase address) throws Throwable {
return JNIThreadLocalPinnedObjects.unpinArrayByAddress(address);
}
static void getPrimitiveArrayRegion(JavaKind elementKind, Object array, int start, int count, PointerBase buffer) {
if (start < 0 || count < 0 || start + count > Array.getLength(array)) {
throw new ArrayIndexOutOfBoundsException();
}
if (count > 0) {
long offset = ConfigurationValues.getObjectLayout().getArrayElementOffset(elementKind, start);
int elementSize = ConfigurationValues.getObjectLayout().sizeInBytes(elementKind);
UNSAFE.copyMemory(array, offset, null, buffer.rawValue(), count * elementSize);
}
}
static void setPrimitiveArrayRegion(JavaKind elementKind, Object array, int start, int count, PointerBase buffer) {
if (start < 0 || count < 0 || start + count > Array.getLength(array)) {
throw new ArrayIndexOutOfBoundsException();
}
if (count > 0) {
long offset = ConfigurationValues.getObjectLayout().getArrayElementOffset(elementKind, start);
int elementSize = ConfigurationValues.getObjectLayout().sizeInBytes(elementKind);
UNSAFE.copyMemory(null, buffer.rawValue(), array, offset, count * elementSize);
}
}
}