Skip to content

Commit

Permalink
[Wisp] Compatibility support with CDS.
Browse files Browse the repository at this point in the history
Summary:
Follow the rule to support CDS in wisp flow:
1. add serialize function
2. use macro
3. call serialize function when coroutine is enable.

Test Plan:
test/jdk/com/alibaba/cds/TestDumpAndLoadClassWithWisp.java
test/jdk/com/alibaba/cds/TestWispWithAppCDS.java
all wisp cases
all cds cases

Reviewed-by: yulei

Issue:
#112
  • Loading branch information
ZhaiMo15 authored and yuleil committed Aug 8, 2023
1 parent cee0d11 commit b8ba527
Show file tree
Hide file tree
Showing 7 changed files with 365 additions and 11 deletions.
8 changes: 8 additions & 0 deletions src/hotspot/share/cds/metaspaceShared.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,14 @@ void MetaspaceShared::serialize(SerializeClosure* soc) {
soc->do_tag(666);
}

void MetaspaceShared::serialize_well_known_classes(SerializeClosure* soc) {
if (EnableCoroutine) {
java_dyn_CoroutineBase::serialize(soc);
com_alibaba_wisp_engine_WispEngine::serialize(soc);
com_alibaba_wisp_engine_WispTask::serialize(soc);
}
}

static void rewrite_nofast_bytecode(const methodHandle& method) {
BytecodeStream bcs(method);
while (!bcs.is_last_bytecode()) {
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/cds/metaspaceShared.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ class MetaspaceShared : AllStatic {
static bool is_shared_dynamic(void* p) NOT_CDS_RETURN_(false);

static void serialize(SerializeClosure* sc) NOT_CDS_RETURN;
static void serialize_well_known_classes(SerializeClosure* soc) NOT_CDS_RETURN;

// JVM/TI RedefineClasses() support:
// Remap the shared readonly space to shared readwrite, private if
Expand Down
49 changes: 38 additions & 11 deletions src/hotspot/share/classfile/javaClasses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4735,15 +4735,24 @@ void java_nio_Buffer::compute_offsets() {

/* stack manipulation */

#define COROUTINEBASE_FIELDS_DO(macro) \
macro(_native_coroutine_offset, ik, vmSymbols::nativeCoroutine_name(), long_signature, false)

int java_dyn_CoroutineBase::_native_coroutine_offset = 0;

void java_dyn_CoroutineBase::compute_offsets() {
InstanceKlass* ik = vmClasses::java_dyn_CoroutineBase_klass();
if (ik != NULL) {
compute_offset(_native_coroutine_offset, ik, vmSymbols::nativeCoroutine_name(), vmSymbols::long_signature());
COROUTINEBASE_FIELDS_DO(FIELD_COMPUTE_OFFSET);
}
}

#if INCLUDE_CDS
void java_dyn_CoroutineBase::serialize(SerializeClosure* f) {
COROUTINEBASE_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif

jlong java_dyn_CoroutineBase::native_coroutine(oop obj) {
return obj->long_field(_native_coroutine_offset);
}
Expand All @@ -4752,14 +4761,23 @@ void java_dyn_CoroutineBase::set_native_coroutine(oop obj, jlong value) {
obj->long_field_put(_native_coroutine_offset, value);
}

#define WISPENGINE_FIELDS_DO(macro) \
macro(_isInCritical_offset, ik, vmSymbols::isInCritical_name(), bool_signature, false)

int com_alibaba_wisp_engine_WispEngine::_isInCritical_offset = 0;

void com_alibaba_wisp_engine_WispEngine::compute_offsets() {
InstanceKlass* ik = vmClasses::com_alibaba_wisp_engine_WispEngine_klass();
assert(ik != NULL, "WispEngine_klass is null");
compute_offset(_isInCritical_offset, ik, vmSymbols::isInCritical_name(), vmSymbols::bool_signature());
WISPENGINE_FIELDS_DO(FIELD_COMPUTE_OFFSET);
}

#if INCLUDE_CDS
void com_alibaba_wisp_engine_WispEngine::serialize(SerializeClosure* f) {
WISPENGINE_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif

bool com_alibaba_wisp_engine_WispEngine::in_critical(oop obj) {
return obj->bool_field(_isInCritical_offset);
}
Expand All @@ -4774,20 +4792,29 @@ int com_alibaba_wisp_engine_WispTask::_stealCount_offset = 0;
int com_alibaba_wisp_engine_WispTask::_stealFailureCount_offset = 0;
int com_alibaba_wisp_engine_WispTask::_preemptCount_offset = 0;

#define WISPTASK_FIELDS_DO(macro) \
macro(_jvmParkStatus_offset, ik, vmSymbols::jvmParkStatus_name(), int_signature, false); \
macro(_jdkParkStatus_offset, ik, vmSymbols::jdkParkStatus_name(), int_signature, false); \
macro(_id_offset, ik, vmSymbols::id_name(), int_signature, false); \
macro(_threadWrapper_offset, ik, vmSymbols::threadWrapper_name(), thread_signature, false); \
macro(_interrupted_offset, ik, vmSymbols::interrupted_name(), int_signature, false); \
macro(_activeCount_offset, ik, vmSymbols::activeCount_name(), int_signature, false); \
macro(_stealCount_offset, ik, vmSymbols::stealCount_name(), int_signature, false); \
macro(_stealFailureCount_offset, ik, vmSymbols::stealFailureCount_name(), int_signature, false); \
macro(_preemptCount_offset, ik, vmSymbols::preemptCount_name(), int_signature, false)

void com_alibaba_wisp_engine_WispTask::compute_offsets() {
InstanceKlass* ik = vmClasses::com_alibaba_wisp_engine_WispTask_klass();
assert(ik != NULL, "WispTask_klass is null");
compute_offset(_jvmParkStatus_offset, ik, vmSymbols::jvmParkStatus_name(), vmSymbols::int_signature());
compute_offset(_jdkParkStatus_offset, ik, vmSymbols::jdkParkStatus_name(), vmSymbols::int_signature());
compute_offset(_id_offset, ik, vmSymbols::id_name(), vmSymbols::int_signature());
compute_offset(_threadWrapper_offset, ik, vmSymbols::threadWrapper_name(), vmSymbols::thread_signature());
compute_offset(_interrupted_offset, ik, vmSymbols::interrupted_name(), vmSymbols::int_signature());
compute_offset(_activeCount_offset, ik, vmSymbols::activeCount_name(), vmSymbols::int_signature());
compute_offset(_stealCount_offset, ik, vmSymbols::stealCount_name(), vmSymbols::int_signature());
compute_offset(_stealFailureCount_offset, ik, vmSymbols::stealFailureCount_name(), vmSymbols::int_signature());
compute_offset(_preemptCount_offset, ik, vmSymbols::preemptCount_name(), vmSymbols::int_signature());
WISPTASK_FIELDS_DO(FIELD_COMPUTE_OFFSET);
}

#if INCLUDE_CDS
void com_alibaba_wisp_engine_WispTask::serialize(SerializeClosure* f) {
WISPTASK_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif

void com_alibaba_wisp_engine_WispTask::set_jvmParkStatus(oop obj, jint status) {
obj->int_field_put(_jvmParkStatus_offset, status);
}
Expand Down
4 changes: 4 additions & 0 deletions src/hotspot/share/classfile/javaClasses.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1805,6 +1805,8 @@ class java_dyn_CoroutineBase: AllStatic {

static int get_native_coroutine_offset() { return _native_coroutine_offset; }

static void serialize(SerializeClosure* f) NOT_CDS_RETURN;

// Debugging
friend class JavaClasses;
};
Expand All @@ -1816,6 +1818,7 @@ class com_alibaba_wisp_engine_WispEngine: AllStatic {
static bool in_critical(oop obj);

static void compute_offsets();
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
};

class com_alibaba_wisp_engine_WispTask: AllStatic {
Expand Down Expand Up @@ -1844,6 +1847,7 @@ class com_alibaba_wisp_engine_WispTask: AllStatic {
static void set_preemptCount(oop obj, jint count);

static void compute_offsets();
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
};

// Interface to hard-coded offset checking
Expand Down
158 changes: 158 additions & 0 deletions test/jdk/com/alibaba/cds/TestDumpAndLoadClassWithWisp.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
/*
* @test
* @summary Test EagerAppCDS Flow with wisp
* @library /lib/testlibrary /test/lib
* @modules java.base/jdk.internal.access
* java.management
* jdk.jartool/sun.tools.jar
* @modules jdk.compiler
* @modules java.base/com.alibaba.util:+open
* @build Classes4CDS
* @build TestSimple
* @build TestClassLoaderWithSignature
* @run driver ClassFileInstaller -jar test.jar TestClassLoaderWithSignature
* @run main/othervm -XX:+UnlockExperimentalVMOptions TestDumpAndLoadClassWithWisp
*/

import jdk.test.lib.cds.CDSTestUtils;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;

import java.util.ArrayList;
import java.util.List;
import java.io.*;

public class TestDumpAndLoadClassWithWisp {

private static final String TESTJAR = "./test.jar";
private static final String TESTNAME = "TestClassLoaderWithSignature";
private static final String TESTCLASS = TESTNAME + ".class";

private static final String CLASSLIST_FILE = "./TestDumpAndLoadClassWithWisp.classlist";
private static final String CLASSLIST_FILE_2 = "./TestDumpAndLoadClassWithWisp.classlist2";
private static final String ARCHIVE_FILE = "./TestDumpAndLoadClassWithWisp.jsa";
private static final String BOOTCLASS = "java.lang.Class";
private static final String TEST_CLASS = System.getProperty("test.classes");

public static void main(String[] args) throws Exception {

// dump loaded classes into a classlist file
dumpLoadedClasses(new String[] { BOOTCLASS, TESTNAME });

convertClassList();

// create an archive using the classlist
dumpArchive();

// start the java process with shared archive file
startWithJsa();
}

public static List<String> toClassNames(String filename) throws IOException {
ArrayList<String> classes = new ArrayList<>();
try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filename)))) {
for (; ; ) {
String line = br.readLine();
if (line == null) {
break;
}
classes.add(line.replaceAll("/", "."));
}
}
return classes;
}

static void dumpLoadedClasses(String[] expectedClasses) throws Exception {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true,
"-Dtest.classes=" + TEST_CLASS,
"-XX:DumpLoadedClassList=" + CLASSLIST_FILE,
// trigger JVMCI runtime init so that JVMCI classes will be
// included in the classlist
"-XX:+EagerAppCDS",
"-XX:+UseWisp2",
"-cp",
TESTJAR,
TESTNAME);

OutputAnalyzer output = CDSTestUtils.executeAndLog(pb, "dump-loaded-classes")
.shouldHaveExitValue(0);

List<String> dumpedClasses = toClassNames(CLASSLIST_FILE);

for (String clazz : expectedClasses) {
boolean findString = false;
for (String s: dumpedClasses) {
if (s.contains(clazz)) {
findString = true;
break;
}
}
if (findString == false) {
throw new RuntimeException(clazz + " missing in " +
CLASSLIST_FILE);
}
}
boolean findString = false;
for (String s: dumpedClasses) {
if (s.contains("source: file:")) {
findString = true;
break;
}
}
if (findString == false) {
throw new RuntimeException(" there is no class loaded by customer class loader");
}
}

static void convertClassList() throws Exception {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true,
"Classes4CDS",
CLASSLIST_FILE,
CLASSLIST_FILE_2);

OutputAnalyzer output = CDSTestUtils.executeAndLog(pb, "convert-class-list")
.shouldHaveExitValue(0);

}
static void dumpArchive() throws Exception {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true,
"-cp",
TESTJAR,
"-XX:+EagerAppCDS",
"-XX:SharedClassListFile=" + CLASSLIST_FILE_2,
"-XX:SharedArchiveFile=" + ARCHIVE_FILE,
"-XX:+UseWisp2",
"-Xlog:class+eagerappcds=trace",
"-Xshare:dump",
"-XX:MetaspaceSize=12M",
"-XX:MaxMetaspaceSize=12M");

OutputAnalyzer output = CDSTestUtils.executeAndLog(pb, "dump-archive");
int exitValue = output.getExitValue();
if (exitValue == 1) {
output.shouldContain("Failed allocating metaspace object type");
} else if (exitValue == 0) {
output.shouldContain("Loading classes to share");
} else {
throw new RuntimeException("Unexpected exit value " + exitValue);
}
}

static void startWithJsa() throws Exception {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true,
"-Dtest.classes=" + TEST_CLASS,
"-XX:+EagerAppCDS",
"-Xshare:on",
"-XX:SharedArchiveFile=" + ARCHIVE_FILE,
"-Xlog:class+eagerappcds=trace",
"-XX:+UseWisp2",
"-cp",
TESTJAR,
TESTNAME);

OutputAnalyzer output = CDSTestUtils.executeAndLog(pb, "start-with-shared-archive")
.shouldHaveExitValue(0);
output.shouldNotContain("[CDS load class Failed");
}

}
23 changes: 23 additions & 0 deletions test/jdk/com/alibaba/cds/TestSimpleWispUsage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
public class TestSimpleWispUsage {
public static void main(String[] args) throws Exception {
Thread io = new Thread(() -> {
try {
int i = 0;
while (i < 3) {
try {
Thread.sleep(1000);
} catch (Exception e) {
}
i++;
}

} catch (Throwable t) {
}
}, "IO thread");

io.start();

long start = System.currentTimeMillis();
Thread.sleep(1000);
}
}
Loading

0 comments on commit b8ba527

Please sign in to comment.