Skip to content

[GR-64282] Espresso CDS: Module layer caching. #11413

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 16, 2025
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
package com.oracle.truffle.espresso.classfile.tables;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReadWriteLock;

import com.oracle.truffle.espresso.classfile.descriptors.Name;
Expand All @@ -36,11 +37,11 @@ public AbstractModuleTable(ReadWriteLock lock) {
}

public ME createAndAddEntry(Symbol<Name> name, String version, String location, boolean isOpen, M module) {
return createAndAddEntry(name, new ModuleData<>(version, location, module, isOpen));
return createAndAddEntry(name, new ModuleData<>(version, location, module, 0, isOpen));
}

public ME createUnnamedModuleEntry(M module) {
ME result = createEntry(null, new ModuleData<>(null, null, module, true));
ME result = createEntry(null, new ModuleData<>(null, null, module, 0, true));
result.setCanReadAllUnnamed();
return result;
}
Expand All @@ -50,22 +51,36 @@ public static final class ModuleData<M> {
private final String location;
private final boolean isOpen;
private final M module;
private final int archivedModuleRefId;

public ModuleData(String version, String location, M module, boolean isOpen) {
public ModuleData(String version, String location, M module, int archivedModuleRefId, boolean isOpen) {
this.version = version;
this.location = location;
this.isOpen = isOpen;
this.module = module;
this.archivedModuleRefId = archivedModuleRefId;
}
}

public abstract static class AbstractModuleEntry<M> extends EntryTable.NamedEntry {
private final boolean isOpen;
private M module;

public int getArchivedModuleRefId() {
return archivedModuleRefId;
}

private int archivedModuleRefId;
private String version;
private String location;

public boolean canReadAllUnnamed() {
return canReadAllUnnamed;
}

private boolean canReadAllUnnamed;
private ArrayList<AbstractModuleEntry<M>> reads;

protected List<AbstractModuleEntry<M>> reads;
private volatile boolean hasDefaultReads;

protected AbstractModuleEntry(Symbol<Name> name, ModuleData<M> data) {
Expand All @@ -74,6 +89,7 @@ protected AbstractModuleEntry(Symbol<Name> name, ModuleData<M> data) {
this.location = data.location;
this.isOpen = data.isOpen;
this.module = data.module;
this.archivedModuleRefId = data.archivedModuleRefId;
}

public void addReads(AbstractModuleEntry<M> from) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ protected AbstractPackageEntry(Symbol<Name> name, ME module) {
}

private final ME module;
private ArrayList<ME> exports;
protected ArrayList<ME> exports;
private boolean isUnqualifiedExported;
private boolean isExportedAllUnnamed;
private String bootClasspathLocation;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
import com.oracle.truffle.espresso.classfile.descriptors.Symbol;

public abstract class EntryTable<T extends EntryTable.NamedEntry, K> {
private final HashMap<Symbol<Name>, T> entries = new HashMap<>();
protected final HashMap<Symbol<Name>, T> entries = new HashMap<>();

private final BlockLock readBlock;
private final BlockLock writeBlock;
Expand Down
4 changes: 2 additions & 2 deletions espresso/mx.espresso/mx_espresso.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,9 @@ def _run_java_truffle(args=None, cwd=None, nonZeroIsFatal=True, out=None, err=No

def _run_espresso(args=None, cwd=None, nonZeroIsFatal=True, out=None, err=None, timeout=None):
if _has_native_espresso_standalone():
_run_java_truffle(args, cwd, nonZeroIsFatal, out, err, timeout)
return _run_java_truffle(args, cwd, nonZeroIsFatal, out, err, timeout)
else:
_run_espresso_launcher(args, cwd, nonZeroIsFatal, out, err, timeout)
return _run_espresso_launcher(args, cwd, nonZeroIsFatal, out, err, timeout)


def _run_espresso_meta(args, nonZeroIsFatal=True, timeout=None):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,10 +272,6 @@ protected List<String> preprocessArguments(List<String> arguments, Map<String, S
case "-Xint":
espressoOptions.put("engine.Compilation", "false");
break;
case "-Xshare:auto":
case "-Xshare:off":
// ignore
break;

case "-XX:+PauseOnExit":
pauseOnExit = true;
Expand Down Expand Up @@ -320,6 +316,9 @@ protected List<String> preprocessArguments(List<String> arguments, Map<String, S
espressoOptions.put(AGENT_PATH + split[0], split[1]);
} else if (arg.startsWith("-Xmn") || arg.startsWith("-Xms") || arg.startsWith("-Xmx") || arg.startsWith("-Xss") || arg.startsWith("-XX:MaxHeapSize=")) {
unrecognized.add("--vm." + arg.substring(1));
} else if (arg.startsWith("-Xshare:")) {
String value = arg.substring("-Xshare:".length());
espressoOptions.put("java.CDS", value);
} else if (arg.startsWith("-XX:")) {
handleXXArg(arg, unrecognized);
} else
Expand Down Expand Up @@ -428,6 +427,7 @@ private void parseArgFile(String pathArg, List<String> expanded) {
}

private static final Set<String> knownPassThroughOptions = Set.of(
"SharedArchiveFile",
"WhiteBoxAPI",
"EnableJVMCI");

Expand Down Expand Up @@ -644,6 +644,12 @@ protected void launch(Builder contextBuilder) {
}
}

boolean dumpSharedSpaces = "dump".equals(espressoOptions.get("java.CDS")); // -Xshare:dump
if (dumpSharedSpaces) {
context.initialize("java");
exit();
}

if (mainClassName == null) {
throw abort(usage());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,9 @@ public static int setupContext(Context.Builder builder, JNIJavaVMInitArgs args,
builder.option("engine.CompileImmediately", "true");
} else if (optionString.startsWith("-Xint") || "-XX:TieredStopAtLevel=0".equals(optionString)) {
builder.option("engine.Compilation", "false");
} else if ("-Xshare:auto".equals(optionString) || "-Xshare:off".equals(optionString)) {
// ignore
} else if (optionString.startsWith("-Xshare:")) {
String value = optionString.substring("-Xshare:".length());
builder.option("java.CDS", value);
} else if (optionString.startsWith("-XX:")) {
handler.handleXXArg(optionString);
} else if (optionString.startsWith("--help:")) {
Expand Down
20 changes: 17 additions & 3 deletions espresso/src/com.oracle.truffle.espresso.mokapot/src/mokapot.c
Original file line number Diff line number Diff line change
Expand Up @@ -1569,7 +1569,15 @@ JNIEXPORT void JNICALL JVM_RegisterLambdaProxyClassForArchiving(JNIEnv* env, jcl
jobject implMethodMember,
jobject instantiatedMethodType,
jclass lambdaProxyClass) {
UNIMPLEMENTED(JVM_RegisterLambdaProxyClassForArchiving);
IMPLEMENTED(JVM_RegisterLambdaProxyClassForArchiving);
(*getEnv())->JVM_RegisterLambdaProxyClassForArchiving(env,
caller,
invokedName,
invokedType,
methodType,
implMethodMember,
instantiatedMethodType,
lambdaProxyClass);
return;
}

Expand All @@ -1579,8 +1587,14 @@ JNIEXPORT jclass JNICALL JVM_LookupLambdaProxyClassFromArchive(JNIEnv* env, jcla
jobject methodType,
jobject implMethodMember,
jobject instantiatedMethodType) {
UNIMPLEMENTED(JVM_LookupLambdaProxyClassFromArchive);
return NULL;
IMPLEMENTED(JVM_LookupLambdaProxyClassFromArchive);
return (*getEnv())->JVM_LookupLambdaProxyClassFromArchive(env,
caller,
invokedName,
invokedType,
methodType,
implMethodMember,
instantiatedMethodType);
}

JNIEXPORT jboolean JNICALL JVM_IsCDSDumpingEnabled(JNIEnv* env) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -725,6 +725,25 @@ public enum GuestFieldOffsetStrategyEnum {
stability = OptionStability.EXPERIMENTAL, //
usageSyntax = "false|true") public static final OptionKey<Boolean> EagerFrameAnalysis = new OptionKey<>(false);

public enum XShareOption {
auto,
on,
off,
dump
}

@Option(help = "Sets the class data sharing (CDS) mode.", //
category = OptionCategory.EXPERT, //
stability = OptionStability.EXPERIMENTAL, //
usageSyntax = "auto|on|off|dump") //
public static final OptionKey<XShareOption> CDS = new OptionKey<>(XShareOption.auto);

@Option(help = "Overrides the default path to the (static) CDS archive.", //
category = OptionCategory.EXPERT, //
stability = OptionStability.EXPERIMENTAL, //
usageSyntax = "<path>") //
public static final OptionKey<Path> SharedArchiveFile = new OptionKey<>(EMPTY, PATH_OPTION_TYPE);

/**
* Property used to force liveness analysis to also be applied by the interpreter. For testing
* purpose only. Use a host property rather than an option. An option would slow interpreter
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved.
* 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 com.oracle.truffle.espresso.cds;

import com.oracle.truffle.espresso.impl.ModuleTable;
import com.oracle.truffle.espresso.impl.PackageTable;

public final class ArchivedRegistryData {
PackageTable packageTable;
ModuleTable moduleTable;
ModuleTable.ModuleEntry unnamedModule;

public ArchivedRegistryData(PackageTable packageTable, ModuleTable moduleTable, ModuleTable.ModuleEntry unnamedModule) {
this.packageTable = packageTable;
this.moduleTable = moduleTable;
this.unnamedModule = unnamedModule;
}

public PackageTable packageTable() {
return packageTable;
}

public ModuleTable moduleTable() {
return moduleTable;
}

public ModuleTable.ModuleEntry unnamedModule() {
return unnamedModule;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved.
* 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 com.oracle.truffle.espresso.cds;

interface CDSArchiveFormat {

int TAG_NULL = 1;
int TAG_REFERENCE = 2;
int TAG_STRING = 3;
int TAG_SYMBOL = 4;
int TAG_CLASS_REGISTRY_DATA = 5;
int TAG_MODULE_ENTRY = 6;
int TAG_PACKAGE_ENTRY = 7;
int TAG_ARRAY_LIST = 8;

int TAG_GUEST_NULL = 31;
int TAG_GUEST_ARRAY = 32;
int TAG_GUEST_CLASS = 33;
int TAG_GUEST_STRING = 34;
int TAG_GUEST_OBJECT = 35;
int TAG_GUEST_CLASS_LOADER = 36;

int MAGIC = 0x35973550;

int MAJOR_VERSION = 1;
int MINOR_VERSION = 1;
}
Loading