Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/hotspot/share/runtime/continuationEntry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class RegisterMap;

// Metadata stored in the continuation entry frame
class ContinuationEntry {
friend class VMStructs;
friend class JVMCIVMStructs;
ContinuationEntryPD _pd;
#ifdef ASSERT
Expand Down
5 changes: 4 additions & 1 deletion src/hotspot/share/runtime/vmStructs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,7 @@
nonstatic_field(JavaThread, _active_handles, JNIHandleBlock*) \
nonstatic_field(JavaThread, _monitor_owner_id, int64_t) \
volatile_nonstatic_field(JavaThread, _terminated, JavaThread::TerminatedTypes) \
nonstatic_field(JavaThread, _cont_entry, ContinuationEntry*) \
nonstatic_field(Thread, _osthread, OSThread*) \
\
/************/ \
Expand Down Expand Up @@ -796,7 +797,8 @@
nonstatic_field(Mutex, _name, const char*) \
static_field(Mutex, _mutex_array, Mutex**) \
static_field(Mutex, _num_mutex, int) \
volatile_nonstatic_field(Mutex, _owner, Thread*)
volatile_nonstatic_field(Mutex, _owner, Thread*) \
static_field(ContinuationEntry, _return_pc, address)

//--------------------------------------------------------------------------------
// VM_TYPES
Expand Down Expand Up @@ -1270,6 +1272,7 @@
declare_toplevel_type(FileMapHeader) \
declare_toplevel_type(CDSFileMapRegion) \
declare_toplevel_type(UpcallStub::FrameData) \
declare_toplevel_type(ContinuationEntry) \
\
/************/ \
/* GC types */ \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ public ImmutableOopMapSet getOopMaps() {

public boolean isUpcallStub() { return getKind() == UpcallKind; }

public boolean isContinuationStub() { return getName().equals("StubRoutines (continuation stubs)"); }

public boolean isJavaMethod() { return false; }

public boolean isNativeMethod() { return false; }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2025, NTT DATA.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/

package sun.jvm.hotspot.runtime;

import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.types.*;


public class ContinuationEntry extends VMObject {
private static long size;
private static Address returnPC;

static {
VM.registerVMInitializedObserver((o, d) -> initialize(VM.getVM().getTypeDataBase()));
}

private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("ContinuationEntry");
size = type.getSize();
returnPC = type.getAddressField("_return_pc").getValue();
}

public ContinuationEntry(Address addr) {
super(addr);
}

public Address getEntryPC() {
return returnPC;
}

public Address getEntrySP(){
return this.getAddress();
}

public Address getEntryFP(){
return this.getAddress().addOffsetTo(size);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public class JavaThread extends Thread {
private static AddressField stackBaseField;
private static CIntegerField stackSizeField;
private static CIntegerField terminatedField;
private static AddressField contEntryField;
private static AddressField activeHandlesField;
private static CIntegerField monitorOwnerIDField;
private static long oopPtrSize;
Expand Down Expand Up @@ -95,6 +96,7 @@ private static synchronized void initialize(TypeDataBase db) {
stackBaseField = type.getAddressField("_stack_base");
stackSizeField = type.getCIntegerField("_stack_size");
terminatedField = type.getCIntegerField("_terminated");
contEntryField = type.getAddressField("_cont_entry");
activeHandlesField = type.getAddressField("_active_handles");
monitorOwnerIDField = type.getCIntegerField("_monitor_owner_id");

Expand Down Expand Up @@ -340,6 +342,10 @@ public int getTerminated() {
return (int) terminatedField.getValue(addr);
}

public ContinuationEntry getContEntry() {
return VMObjectFactory.newObject(ContinuationEntry.class, contEntryField.getValue(addr));
}

/** Gets the Java-side thread object for this JavaThread */
public Oop getThreadObj() {
Oop obj = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,13 @@ public Frame sender(RegisterMap regMap, CodeBlob cb) {
}

if (cb != null) {
return cb.isUpcallStub() ? senderForUpcallStub(map, (UpcallStub)cb) : senderForCompiledFrame(map, cb);
if (cb.isUpcallStub()) {
return senderForUpcallStub(map, (UpcallStub)cb);
} else if (cb.isContinuationStub()) {
return senderForContinuationStub(map, cb);
} else {
return senderForCompiledFrame(map, cb);
}
}

// Must be native-compiled frame, i.e. the marshaling code for native
Expand Down Expand Up @@ -356,6 +362,16 @@ private void updateMapWithSavedLink(RegisterMap map, Address savedFPAddr) {
map.setLocation(fp, savedFPAddr);
}

private Frame senderForContinuationStub(AARCH64RegisterMap map, CodeBlob cb) {
var contEntry = map.getThread().getContEntry();

Address senderSP = contEntry.getEntrySP();
Address senderPC = contEntry.getEntryPC();
Address senderFP = contEntry.getEntryFP();

return new AARCH64Frame(senderSP, senderFP, senderPC);
}

private Frame senderForCompiledFrame(AARCH64RegisterMap map, CodeBlob cb) {
if (DEBUG) {
System.out.println("senderForCompiledFrame");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,13 @@ public Frame sender(RegisterMap regMap, CodeBlob cb) {
}

if (cb != null) {
return cb.isUpcallStub() ? senderForUpcallStub(map, (UpcallStub)cb) : senderForCompiledFrame(map, cb);
if (cb.isUpcallStub()) {
return senderForUpcallStub(map, (UpcallStub)cb);
} else if (cb.isContinuationStub()) {
return senderForContinuationStub(map, cb);
} else {
return senderForCompiledFrame(map, cb);
}
}

// Must be native-compiled frame, i.e. the marshaling code for native
Expand Down Expand Up @@ -348,6 +354,16 @@ private void updateMapWithSavedLink(RegisterMap map, Address savedFPAddr) {
map.setLocation(fp, savedFPAddr);
}

private Frame senderForContinuationStub(RISCV64RegisterMap map, CodeBlob cb) {
var contEntry = map.getThread().getContEntry();

Address senderSP = contEntry.getEntrySP();
Address senderPC = contEntry.getEntryPC();
Address senderFP = contEntry.getEntryFP();

return new RISCV64Frame(senderSP, senderFP, senderPC);
}

private Frame senderForCompiledFrame(RISCV64RegisterMap map, CodeBlob cb) {
if (DEBUG) {
System.out.println("senderForCompiledFrame");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,13 @@ public Frame sender(RegisterMap regMap, CodeBlob cb) {
}

if (cb != null) {
return cb.isUpcallStub() ? senderForUpcallStub(map, (UpcallStub)cb) : senderForCompiledFrame(map, cb);
if (cb.isUpcallStub()) {
return senderForUpcallStub(map, (UpcallStub)cb);
} else if (cb.isContinuationStub()) {
return senderForContinuationStub(map, cb);
} else {
return senderForCompiledFrame(map, cb);
}
}

// Must be native-compiled frame, i.e. the marshaling code for native
Expand Down Expand Up @@ -356,6 +362,16 @@ private void updateMapWithSavedLink(RegisterMap map, Address savedFPAddr) {
map.setLocation(rbp, savedFPAddr);
}

private Frame senderForContinuationStub(X86RegisterMap map, CodeBlob cb) {
var contEntry = map.getThread().getContEntry();

Address senderSP = contEntry.getEntrySP();
Address senderPC = contEntry.getEntryPC();
Address senderFP = contEntry.getEntryFP();

return new X86Frame(senderSP, senderFP, senderPC);
}

private Frame senderForCompiledFrame(X86RegisterMap map, CodeBlob cb) {
if (DEBUG) {
System.out.println("senderForCompiledFrame");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@

/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2025, NTT DATA
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

import java.lang.invoke.MethodHandle;
import java.lang.foreign.Arena;
import java.lang.foreign.FunctionDescriptor;
import java.lang.foreign.Linker;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.SymbolLookup;
import java.lang.foreign.ValueLayout;
import java.util.concurrent.CountDownLatch;

import jdk.test.lib.apps.LingeredApp;

public class LingeredAppWithVirtualThread extends LingeredApp implements Runnable {

private static final String THREAD_NAME = "target thread";

private static final MethodHandle hndSleep;

private static final int sleepArg;

private static final CountDownLatch signal = new CountDownLatch(1);

static {
MemorySegment func;
if (System.getProperty("os.name").startsWith("Windows")) {
func = SymbolLookup.libraryLookup("Kernel32", Arena.global())
.findOrThrow("Sleep");
sleepArg = 3600_000; // 1h in milliseconds
} else {
func = Linker.nativeLinker()
.defaultLookup()
.findOrThrow("sleep");
sleepArg = 3600; // 1h in seconds
}

var desc = FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.JAVA_INT);
hndSleep = Linker.nativeLinker().downcallHandle(func, desc);
}

@Override
public void run() {
Thread.yield();
signal.countDown();
try {
hndSleep.invoke(sleepArg);
} catch (Throwable t) {
throw new RuntimeException(t);
}
}

public static void main(String[] args) {
try {
Thread.ofVirtual()
.name(THREAD_NAME)
.start(new LingeredAppWithVirtualThread());

signal.await();
LingeredApp.main(args);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
Loading