mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8284161: Implementation of Virtual Threads (Preview)
Co-authored-by: Ron Pressler <rpressler@openjdk.org> Co-authored-by: Alan Bateman <alanb@openjdk.org> Co-authored-by: Erik Österlund <eosterlund@openjdk.org> Co-authored-by: Andrew Haley <aph@openjdk.org> Co-authored-by: Rickard Bäckman <rbackman@openjdk.org> Co-authored-by: Markus Grönlund <mgronlun@openjdk.org> Co-authored-by: Leonid Mesnik <lmesnik@openjdk.org> Co-authored-by: Serguei Spitsyn <sspitsyn@openjdk.org> Co-authored-by: Chris Plummer <cjplummer@openjdk.org> Co-authored-by: Coleen Phillimore <coleenp@openjdk.org> Co-authored-by: Robbin Ehn <rehn@openjdk.org> Co-authored-by: Stefan Karlsson <stefank@openjdk.org> Co-authored-by: Thomas Schatzl <tschatzl@openjdk.org> Co-authored-by: Sergey Kuksenko <skuksenko@openjdk.org> Reviewed-by: lancea, eosterlund, rehn, sspitsyn, stefank, tschatzl, dfuchs, lmesnik, dcubed, kevinw, amenkov, dlong, mchung, psandoz, bpb, coleenp, smarks, egahlin, mseledtsov, coffeys, darcy
This commit is contained in:
parent
5212535a27
commit
9583e3657e
1133 changed files with 95935 additions and 8335 deletions
|
@ -41,6 +41,8 @@ import java.util.function.Consumer;
|
|||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
import jdk.internal.vm.Continuation;
|
||||
import jdk.internal.vm.ContinuationScope;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
import static java.lang.StackStreamFactory.WalkerState.*;
|
||||
|
@ -126,6 +128,8 @@ final class StackStreamFactory {
|
|||
protected int depth; // traversed stack depth
|
||||
protected FrameBuffer<? extends T> frameBuffer;
|
||||
protected long anchor;
|
||||
protected final ContinuationScope contScope;
|
||||
protected Continuation continuation;
|
||||
|
||||
// buffers to fill in stack frame information
|
||||
protected AbstractStackWalker(StackWalker walker, int mode) {
|
||||
|
@ -137,6 +141,14 @@ final class StackStreamFactory {
|
|||
this.walker = walker;
|
||||
this.maxDepth = maxDepth;
|
||||
this.depth = 0;
|
||||
ContinuationScope scope = walker.getContScope();
|
||||
if (scope == null && thread.isVirtual()) {
|
||||
this.contScope = VirtualThread.continuationScope();
|
||||
this.continuation = null;
|
||||
} else {
|
||||
this.contScope = scope;
|
||||
this.continuation = walker.getContinuation();
|
||||
}
|
||||
}
|
||||
|
||||
private int toStackWalkMode(StackWalker walker, int mode) {
|
||||
|
@ -236,6 +248,12 @@ final class StackStreamFactory {
|
|||
*/
|
||||
final R walk() {
|
||||
checkState(NEW);
|
||||
return (continuation != null)
|
||||
? Continuation.wrapWalk(continuation, contScope, this::walkHelper)
|
||||
: walkHelper();
|
||||
}
|
||||
|
||||
private final R walkHelper() {
|
||||
try {
|
||||
// VM will need to stabilize the stack before walking. It will invoke
|
||||
// the AbstractStackWalker::doStackWalk method once it fetches the first batch.
|
||||
|
@ -311,7 +329,10 @@ final class StackStreamFactory {
|
|||
*/
|
||||
private int getNextBatch() {
|
||||
int nextBatchSize = Math.min(maxDepth - depth, getNextBatchSize());
|
||||
if (!frameBuffer.isActive() || nextBatchSize <= 0) {
|
||||
|
||||
if (!frameBuffer.isActive()
|
||||
|| (nextBatchSize <= 0)
|
||||
|| (frameBuffer.isAtBottom() && !hasMoreContinuations())) {
|
||||
if (isDebug) {
|
||||
System.out.format(" more stack walk done%n");
|
||||
}
|
||||
|
@ -319,7 +340,26 @@ final class StackStreamFactory {
|
|||
return 0;
|
||||
}
|
||||
|
||||
return fetchStackFrames(nextBatchSize);
|
||||
if (frameBuffer.isAtBottom() && hasMoreContinuations()) {
|
||||
setContinuation(continuation.getParent());
|
||||
}
|
||||
|
||||
int numFrames = fetchStackFrames(nextBatchSize);
|
||||
if (numFrames == 0 && !hasMoreContinuations()) {
|
||||
frameBuffer.freeze(); // done stack walking
|
||||
}
|
||||
return numFrames;
|
||||
}
|
||||
|
||||
private boolean hasMoreContinuations() {
|
||||
return (continuation != null)
|
||||
&& (continuation.getScope() != contScope)
|
||||
&& (continuation.getParent() != null);
|
||||
}
|
||||
|
||||
private void setContinuation(Continuation cont) {
|
||||
this.continuation = cont;
|
||||
setContinuation(anchor, frameBuffer.frames(), cont);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -368,6 +408,7 @@ final class StackStreamFactory {
|
|||
initFrameBuffer();
|
||||
|
||||
return callStackWalk(mode, 0,
|
||||
contScope, continuation,
|
||||
frameBuffer.curBatchFrameCount(),
|
||||
frameBuffer.startIndex(),
|
||||
frameBuffer.frames());
|
||||
|
@ -390,10 +431,10 @@ final class StackStreamFactory {
|
|||
System.out.format(" more stack walk requesting %d got %d to %d frames%n",
|
||||
batchSize, frameBuffer.startIndex(), endIndex);
|
||||
}
|
||||
|
||||
int numFrames = endIndex - startIndex;
|
||||
if (numFrames == 0) {
|
||||
frameBuffer.freeze(); // done stack walking
|
||||
} else {
|
||||
|
||||
if (numFrames > 0) {
|
||||
frameBuffer.setBatch(depth, startIndex, endIndex);
|
||||
}
|
||||
return numFrames;
|
||||
|
@ -405,6 +446,8 @@ final class StackStreamFactory {
|
|||
*
|
||||
* @param mode mode of stack walking
|
||||
* @param skipframes number of frames to be skipped before filling the frame buffer.
|
||||
* @param contScope the continuation scope to walk.
|
||||
* @param continuation the continuation to walk, or {@code null} if walking a thread.
|
||||
* @param batchSize the batch size, max. number of elements to be filled in the frame buffers.
|
||||
* @param startIndex start index of the frame buffers to be filled.
|
||||
* @param frames Either a Class<?> array, if mode is {@link #FILL_CLASS_REFS_ONLY}
|
||||
|
@ -412,6 +455,7 @@ final class StackStreamFactory {
|
|||
* @return Result of AbstractStackWalker::doStackWalk
|
||||
*/
|
||||
private native R callStackWalk(long mode, int skipframes,
|
||||
ContinuationScope contScope, Continuation continuation,
|
||||
int batchSize, int startIndex,
|
||||
T[] frames);
|
||||
|
||||
|
@ -430,6 +474,8 @@ final class StackStreamFactory {
|
|||
private native int fetchStackFrames(long mode, long anchor,
|
||||
int batchSize, int startIndex,
|
||||
T[] frames);
|
||||
|
||||
private native void setContinuation(long anchor, T[] frames, Continuation cont);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -497,6 +543,12 @@ final class StackStreamFactory {
|
|||
final Class<?> at(int index) {
|
||||
return stackFrames[index].declaringClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
final boolean filter(int index) {
|
||||
return stackFrames[index].declaringClass() == Continuation.class
|
||||
&& "yield0".equals(stackFrames[index].getMethodName());
|
||||
}
|
||||
}
|
||||
|
||||
final Function<? super Stream<StackFrame>, ? extends T> function; // callback
|
||||
|
@ -633,6 +685,9 @@ final class StackStreamFactory {
|
|||
@Override
|
||||
final Class<?> at(int index) { return classes[index];}
|
||||
|
||||
@Override
|
||||
final boolean filter(int index) { return false; }
|
||||
|
||||
|
||||
// ------ subclass may override the following methods -------
|
||||
/**
|
||||
|
@ -765,6 +820,12 @@ final class StackStreamFactory {
|
|||
final Class<?> at(int index) {
|
||||
return stackFrames[index].declaringClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
final boolean filter(int index) {
|
||||
return stackFrames[index].declaringClass() == Continuation.class
|
||||
&& "yield0".equals(stackFrames[index].getMethodName());
|
||||
}
|
||||
}
|
||||
|
||||
LiveStackInfoTraverser(StackWalker walker,
|
||||
|
@ -834,6 +895,13 @@ final class StackStreamFactory {
|
|||
*/
|
||||
abstract Class<?> at(int index);
|
||||
|
||||
/**
|
||||
* Filter out frames at the top of a batch
|
||||
* @param index the position of the frame.
|
||||
* @return true if the frame should be skipped
|
||||
*/
|
||||
abstract boolean filter(int index);
|
||||
|
||||
// ------ subclass may override the following methods -------
|
||||
|
||||
/*
|
||||
|
@ -881,7 +949,15 @@ final class StackStreamFactory {
|
|||
* it is done for traversal. All stack frames have been traversed.
|
||||
*/
|
||||
final boolean isActive() {
|
||||
return origin > 0 && (fence == 0 || origin < fence || fence == currentBatchSize);
|
||||
return origin > 0; // && (fence == 0 || origin < fence || fence == currentBatchSize);
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests if this frame buffer is at the end of the stack
|
||||
* and all frames have been traversed.
|
||||
*/
|
||||
final boolean isAtBottom() {
|
||||
return origin > 0 && origin >= fence && fence < currentBatchSize;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -929,16 +1005,13 @@ final class StackStreamFactory {
|
|||
|
||||
this.origin = startIndex;
|
||||
this.fence = endIndex;
|
||||
if (depth == 0 && fence > 0) {
|
||||
// filter the frames due to the stack stream implementation
|
||||
for (int i = START_POS; i < fence; i++) {
|
||||
Class<?> c = at(i);
|
||||
if (isDebug) System.err.format(" frame %d: %s%n", i, c);
|
||||
if (filterStackWalkImpl(c)) {
|
||||
origin++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
for (int i = START_POS; i < fence; i++) {
|
||||
if (isDebug) System.err.format(" frame %d: %s%n", i, at(i));
|
||||
if ((depth == 0 && filterStackWalkImpl(at(i))) // filter the frames due to the stack stream implementation
|
||||
|| filter(i)) {
|
||||
origin++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue