package jdk.internal.foreign;
import jdk.incubator.foreign.MemoryAddress;
import jdk.incubator.foreign.MemoryHandles;
import jdk.internal.access.foreign.MemoryAddressProxy;
import jdk.internal.misc.VM;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.invoke.VarHandle;
import java.util.Optional;
import java.util.function.Supplier;
public final class Utils {
private static final String foreignRestrictedAccess = Optional.ofNullable(VM.getSavedProperty("foreign.restricted"))
.orElse("deny");
private static final MethodHandle ADDRESS_FILTER;
static {
try {
ADDRESS_FILTER = MethodHandles.lookup().findStatic(Utils.class, "filterAddress",
MethodType.methodType(MemoryAddressProxy.class, MemoryAddress.class));
} catch (Throwable ex) {
throw new ExceptionInInitializerError(ex);
}
}
public static long alignUp(long n, long alignment) {
return (n + alignment - 1) & -alignment;
}
public static long bitsToBytesOrThrow(long bits, Supplier<RuntimeException> exFactory) {
if (bits % 8 == 0) {
return bits / 8;
} else {
throw exFactory.get();
}
}
public static VarHandle fixUpVarHandle(VarHandle handle) {
return MemoryHandles.filterCoordinates(handle, 0, ADDRESS_FILTER);
}
private static MemoryAddressProxy filterAddress(MemoryAddress addr) {
return (MemoryAddressImpl)addr;
}
public static void checkRestrictedAccess(String method) {
switch (foreignRestrictedAccess) {
case "deny" -> throwIllegalAccessError(foreignRestrictedAccess, method);
case "warn" -> System.err.println("WARNING: Accessing restricted foreign method: " + method);
case "debug" -> {
StringBuilder sb = new StringBuilder("DEBUG: restricted foreign method: \" + method");
StackWalker.getInstance().forEach(f -> sb.append(System.lineSeparator())
.append("\tat ")
.append(f));
System.err.println(sb.toString());
}
case "permit" -> {}
default -> throwIllegalAccessError(foreignRestrictedAccess, method);
}
}
private static void throwIllegalAccessError(String value, String method) {
throw new IllegalAccessError("Illegal access to restricted foreign method: " + method +
" ; system property 'foreign.restricted' is set to '" + value + "'");
}
}