diff --git a/src/java.base/share/classes/jdk/internal/foreign/MemorySessionImpl.java b/src/java.base/share/classes/jdk/internal/foreign/MemorySessionImpl.java index 8f576625500c1..22eea183440d5 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/MemorySessionImpl.java +++ b/src/java.base/share/classes/jdk/internal/foreign/MemorySessionImpl.java @@ -55,7 +55,7 @@ */ public abstract sealed class MemorySessionImpl implements Scope - permits ConfinedSession, GlobalSession, SharedSession { + permits ConfinedSession, GlobalSession, SharedSession, StructuredSession { /** * The value of the {@code state} of a {@code MemorySessionImpl}. The only possible transition @@ -144,6 +144,10 @@ public static MemorySessionImpl createConfined(Thread thread) { return new ConfinedSession(thread); } + public static MemorySessionImpl createStructured(Thread thread) { + return new StructuredSession(thread); + } + public static MemorySessionImpl createShared() { return new SharedSession(); } @@ -174,7 +178,7 @@ public final Thread ownerThread() { return owner; } - public final boolean isAccessibleBy(Thread thread) { + public boolean isAccessibleBy(Thread thread) { Objects.requireNonNull(thread); return owner == null || owner == thread; } @@ -196,15 +200,20 @@ public boolean isAlive() { * please use {@link #checkValidState()}. */ @ForceInline - public void checkValidStateRaw() { - if (owner != null && owner != Thread.currentThread()) { - throw WRONG_THREAD; - } + public final void checkValidStateRaw() { + checkThreadRaw(); if (state < OPEN) { throw ALREADY_CLOSED; } } + @ForceInline + void checkThreadRaw() { + if (owner != null && owner != Thread.currentThread()) { + throw WRONG_THREAD; + } + } + /** * Checks that this session is still alive (see {@link #isAlive()}). * @throws IllegalStateException if this session is already closed or if this is diff --git a/src/java.base/share/classes/jdk/internal/foreign/Stack.java b/src/java.base/share/classes/jdk/internal/foreign/Stack.java index c34c4fbe7534f..3afa55999fbd4 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/Stack.java +++ b/src/java.base/share/classes/jdk/internal/foreign/Stack.java @@ -26,12 +26,20 @@ package jdk.internal.foreign; +import jdk.internal.access.JavaLangAccess; +import jdk.internal.access.SharedSecrets; +import jdk.internal.misc.Unsafe; +import jdk.internal.vm.ScopedValueContainer; +import jdk.internal.vm.ScopedValueContainer.BindingsSnapshot; +import jdk.internal.vm.StackableScope; import jdk.internal.vm.annotation.ForceInline; +import java.lang.ScopedValue.CallableOp; import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.StructureViolationException; public class Stack { @@ -139,7 +147,7 @@ MemorySegment nextSlice(long bytesSize, long bytesAlignment, Arena arena) { class ArenaStack implements Arena { - final Arena arena = Arena.ofConfined(); + final Arena arena = MemorySessionImpl.createStructured(Thread.currentThread()).asArena(); final long startOffset; final long prevPendingStart; diff --git a/src/java.base/share/classes/jdk/internal/foreign/StructuredSession.java b/src/java.base/share/classes/jdk/internal/foreign/StructuredSession.java new file mode 100644 index 0000000000000..d51a7c551fb2e --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/foreign/StructuredSession.java @@ -0,0 +1,51 @@ +package jdk.internal.foreign; + +import jdk.internal.foreign.ConfinedSession.ConfinedResourceList; +import jdk.internal.vm.StackableScope; +import jdk.internal.vm.annotation.ForceInline; + +import java.util.Objects; + +public final class StructuredSession extends MemorySessionImpl { + + private final StackableScope stackableScope = new StackableScope() { }; + + public StructuredSession(Thread owner) { + super(owner, new ConfinedResourceList()); + stackableScope.push(); + } + + public boolean isAccessibleBy(Thread thread) { + Objects.requireNonNull(thread); + return StackableScope.contains(stackableScope); + } + + @Override + @ForceInline + public void acquire0() { + checkValidState(); + // do nothing + } + + @Override + @ForceInline + public void release0() { + // do nothing + } + + @Override + @ForceInline + void checkThreadRaw() { + if (Thread.currentThread() != owner && + !StackableScope.contains(stackableScope)) { + throw WRONG_THREAD; + } + } + + void justClose() { + checkValidState(); + if (!stackableScope.tryPop()) { + throw new IllegalStateException("Cannot close"); + } + } +} diff --git a/src/java.base/share/classes/jdk/internal/vm/StackableScope.java b/src/java.base/share/classes/jdk/internal/vm/StackableScope.java index 85a5646db253f..badd92c3d9a3a 100644 --- a/src/java.base/share/classes/jdk/internal/vm/StackableScope.java +++ b/src/java.base/share/classes/jdk/internal/vm/StackableScope.java @@ -236,7 +236,7 @@ private void unlink() { /** * Returns true if the given scope is on the current thread's scope stack. */ - private static boolean contains(StackableScope scope) { + public static boolean contains(StackableScope scope) { assert scope != null; StackableScope current = head(); while (current != null && current != scope) {