Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
53b2490
Separating JVM functionality into own jvm-channel project
JaroslavTulach Jun 6, 2025
f0cff3d
Unit test using Channel functionality in a single JVM
JaroslavTulach Jun 6, 2025
365d50d
Testing ChannelInSingleJvm in jvm-channel project itself
JaroslavTulach Jun 9, 2025
837877d
jvm-interop module with dependency on Truffle
JaroslavTulach Jun 9, 2025
701006e
The enso language may not be enabled
JaroslavTulach Jun 9, 2025
9817a8e
Using Object[] as class argument yield proper AP error
JaroslavTulach Jun 9, 2025
9c129de
Messages to find out if an object is an array
JaroslavTulach Jun 9, 2025
2452421
Access String array elements
JaroslavTulach Jun 9, 2025
b96c9ff
Transfer all primitive types
JaroslavTulach Jun 9, 2025
dd9287c
Invoke methods on the other objects
JaroslavTulach Jun 9, 2025
73f087b
Able to invoke BigDecimal.add(BigDecimal) in the other JVM
JaroslavTulach Jun 9, 2025
3ed9c4a
Transfer of any TruffleObject yields OtherJvmObject and backwards
JaroslavTulach Jun 9, 2025
7a4024d
Report duplicated registrations
JaroslavTulach Jun 9, 2025
44edc03
Invoke java.lang.Short.valueOf in the other JVM
JaroslavTulach Jun 9, 2025
0b8c477
loadClass yields an exception
JaroslavTulach Jun 9, 2025
ba92d27
LoadClass really throws ClassNotFoundException
JaroslavTulach Jun 9, 2025
cd2e6b4
Merge remote-tracking branch 'origin/develop' into wip/jtulach/Channe…
JaroslavTulach Jun 10, 2025
cec892c
Provide support for additional PolyglotSymbolResolver extensions
JaroslavTulach Jun 10, 2025
cf3309c
Environment is associated with every DistributionManager
JaroslavTulach Jun 10, 2025
2b58d27
Sending messages must be behind @TruffleBoundary
JaroslavTulach Jun 10, 2025
e41d046
Use OtherSymbolResolver (via PolyglotSymbolResolver API) to load Java…
JaroslavTulach Jun 10, 2025
d6960ec
debug log message when setting value of java.home property
JaroslavTulach Jun 10, 2025
31eff03
Using Context with HostAccess.ALL
JaroslavTulach Jun 10, 2025
fc8f92e
Removing debugging printf statatements
JaroslavTulach Jun 10, 2025
1018884
Renaming to use OtherJvm prefix
JaroslavTulach Jun 10, 2025
9e75dd5
Environment is associated with DistributionManager
JaroslavTulach Jun 10, 2025
14d78f0
Easier to support execute message
JaroslavTulach Jun 10, 2025
2bf6895
Enter and leave the context before sending a message
JaroslavTulach Jun 10, 2025
3c81a1e
Delegate to default library implementation for non-InteropLibrary mes…
JaroslavTulach Jun 11, 2025
bb92781
Even mock Channel has two connected instances
JaroslavTulach Jun 11, 2025
0b970a2
Giving Channel.getData() to store local info on both JVM sides
JaroslavTulach Jun 11, 2025
3c7b2a6
Making os-environment/test pass again
JaroslavTulach Jun 11, 2025
f76710d
Fixing typo
JaroslavTulach Jun 11, 2025
673b8c0
Add entries to classpath
JaroslavTulach Jun 12, 2025
dda69c8
org.enso.jvm.interop needs a reflective registration to construct its…
JaroslavTulach Jun 12, 2025
139914d
Associate readResolve and writeReplace with Pool
JaroslavTulach Jun 13, 2025
4cb9c11
Merge remote-tracking branch 'origin/develop' into wip/jtulach/Channe…
JaroslavTulach Jun 13, 2025
0af6689
DistributionManager is already associated with an environment
JaroslavTulach Jun 13, 2025
7dabb52
Putting the configuration of a Channel into a dedicated Config
JaroslavTulach Jun 13, 2025
d8d7493
Reverting back to develop version
JaroslavTulach Jun 13, 2025
82c431e
Using createPool(Channel) to avoid global state in OtherJvmPool
JaroslavTulach Jun 13, 2025
b5c973f
Map of objects shall not be global
JaroslavTulach Jun 13, 2025
73a8916
withWriteReplace and withReadResolve instance methods form a nicer API
JaroslavTulach Jun 13, 2025
f383a7d
These options cannot be passed to in process JVM - removing
JaroslavTulach Jun 16, 2025
c47eefe
Testing differences in propagation of exceptions
JaroslavTulach Jun 16, 2025
269d66e
Support for --vm.D=polyglot.enso.hostClassLoading=false experimental …
JaroslavTulach Jun 16, 2025
f6171fb
Propagating UnsupportedMessageException
JaroslavTulach Jun 16, 2025
bd95d18
Compatible identity checks
JaroslavTulach Jun 16, 2025
6b77ae7
Can callback with a String
JaroslavTulach Jun 16, 2025
5d6adb2
Channel.isMaster
JaroslavTulach Jun 16, 2025
e745a10
Only enter the TruffleClassLoader.ctx() when on slave
JaroslavTulach Jun 16, 2025
4f373cd
Encapsulate general problems with other JVM into Truffle exception
JaroslavTulach Jun 17, 2025
44efcf3
Merge remote-tracking branch 'origin/develop' into wip/jtulach/Channe…
JaroslavTulach Jun 17, 2025
fdc89fb
Opt-in via --vm.D=polyglot.enso.classLoading to enable other JVM clas…
JaroslavTulach Jun 17, 2025
dc4db1f
Initialize with null
JaroslavTulach Jun 17, 2025
6018f38
Removing non-javadoc documentation
JaroslavTulach Jun 17, 2025
9ea85e3
Removing commented out requires statements
JaroslavTulach Jun 17, 2025
22f170c
A javadoc
JaroslavTulach Jun 17, 2025
e765579
Using name constants to identify special isolates
JaroslavTulach Jun 17, 2025
cda3980
Associate Channel.isMaster with a Context when running OtherJvmObject…
JaroslavTulach Jun 17, 2025
66a2045
Avoid PolyglotSymbolResolver.addToClassPath until it is turned on
JaroslavTulach Jun 17, 2025
06d01e5
Merge remote-tracking branch 'origin/develop' into wip/jtulach/Channe…
JaroslavTulach Jun 17, 2025
f4b374e
windows-2019 image is being deprecated
JaroslavTulach Jun 17, 2025
d77b80b
Backout of f383a7dfc412265597979ef245ba5b60fce0369d
JaroslavTulach Jun 18, 2025
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
2 changes: 1 addition & 1 deletion .github/workflows/enso4igv.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ jobs:
target/lib/**

build_windows_parser:
runs-on: windows-2019
runs-on: windows-2022

steps:
- uses: actions/checkout@v4
Expand Down
78 changes: 76 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,8 @@ lazy val enso = (project in file("."))
`interpreter-dsl-test`,
`jna-wrapper`,
`json-rpc-server`,
`jvm-channel`,
`jvm-interop`,
`language-server`,
`language-server-deps-wrapper`,
launcher,
Expand Down Expand Up @@ -788,6 +790,8 @@ lazy val componentModulesPaths =
(`logging-utils-akka` / Compile / exportedModuleBin).value,
(`logging-service` / Compile / exportedModuleBin).value,
(`logging-service-logback` / Compile / exportedModuleBin).value,
(`jvm-channel` / Compile / exportedModuleBin).value,
(`jvm-interop` / Compile / exportedModuleBin).value,
(`os-environment` / Compile / exportedModuleBin).value,
(`pkg` / Compile / exportedModuleBin).value,
(`refactoring-utils` / Compile / exportedModuleBin).value,
Expand Down Expand Up @@ -3806,6 +3810,7 @@ lazy val `engine-runner` = project
(`profiling-utils` / Compile / exportedModule).value,
(`semver` / Compile / exportedModule).value,
(`cli` / Compile / exportedModule).value,
(`jvm-channel` / Compile / exportedModule).value,
(`os-environment` / Compile / exportedModule).value,
(`distribution-manager` / Compile / exportedModule).value,
(`editions` / Compile / exportedModule).value,
Expand All @@ -3828,6 +3833,10 @@ lazy val `engine-runner` = project
NativeImage.additionalCp := {
val runnerDeps =
(Compile / fullClasspath).value.map(_.data.getAbsolutePath)
val jvmInteropDeps =
(`jvm-interop` / Compile / fullClasspath).value.map(
_.data.getAbsolutePath
)
val runtimeDeps =
(`runtime` / Compile / fullClasspath).value.map(_.data.getAbsolutePath)
val loggingDeps =
Expand Down Expand Up @@ -3861,6 +3870,7 @@ lazy val `engine-runner` = project
}
val core = (
runnerDeps ++
jvmInteropDeps ++
runtimeDeps ++
loggingDeps ++
replDebugInstr ++
Expand Down Expand Up @@ -4253,13 +4263,75 @@ lazy val `benchmarks-common` =
)
.dependsOn(`polyglot-api`)

lazy val `jvm-channel` =
project
.in(file("lib/java/jvm-channel"))
.enablePlugins(JPMSPlugin)
.settings(
customFrgaalJavaCompilerSettings("24"),
autoScalaLibrary := false,
(Test / fork) := true,
commands += WithDebugCommand.withDebug,
libraryDependencies ++= slf4jApi ++ Seq(
"org.graalvm.sdk" % "nativeimage" % graalMavenPackagesVersion % "provided",
"org.graalvm.sdk" % "graal-sdk" % graalMavenPackagesVersion % "provided",
"junit" % "junit" % junitVersion % Test,
"com.github.sbt" % "junit-interface" % junitIfVersion % Test
),
Compile / moduleDependencies ++= slf4jApi ++ Seq(
"org.graalvm.sdk" % "nativeimage" % graalMavenPackagesVersion,
"org.graalvm.polyglot" % "polyglot" % graalMavenPackagesVersion,
"org.graalvm.sdk" % "word" % graalMavenPackagesVersion
),
Compile / internalModuleDependencies ++= Seq(
(`engine-common` / Compile / exportedModule).value,
(`persistance` / Compile / exportedModule).value
)
)
.dependsOn(`engine-common`)
.dependsOn(`persistance`)
.dependsOn(`persistance-dsl` % "provided")

lazy val `jvm-interop` =
project
.in(file("lib/java/jvm-interop"))
.enablePlugins(JPMSPlugin)
.settings(
frgaalJavaCompilerSetting,
autoScalaLibrary := false,
(Test / fork) := true,
commands += WithDebugCommand.withDebug,
libraryDependencies ++= slf4jApi ++ Seq(
"org.graalvm.truffle" % "truffle-api" % graalMavenPackagesVersion % "provided",
"org.graalvm.truffle" % "truffle-dsl-processor" % graalMavenPackagesVersion % "provided",
"org.netbeans.api" % "org-openide-util-lookup" % netbeansApiVersion % "provided",
"org.graalvm.sdk" % "graal-sdk" % graalMavenPackagesVersion % Test,
"junit" % "junit" % junitVersion % Test,
"com.github.sbt" % "junit-interface" % junitIfVersion % Test
),
Compile / moduleDependencies ++= slf4jApi ++ Seq(
"org.netbeans.api" % "org-openide-util-lookup" % netbeansApiVersion,
"org.graalvm.truffle" % "truffle-api" % graalMavenPackagesVersion,
"org.graalvm.sdk" % "nativeimage" % graalMavenPackagesVersion,
"org.graalvm.polyglot" % "polyglot" % graalMavenPackagesVersion,
"org.graalvm.sdk" % "word" % graalMavenPackagesVersion
),
Compile / internalModuleDependencies ++= Seq(
(`jvm-channel` / Compile / exportedModule).value,
(`engine-common` / Compile / exportedModule).value,
(`persistance` / Compile / exportedModule).value
)
)
.dependsOn(`jvm-channel`)
.dependsOn(`persistance-dsl` % "provided")
.dependsOn(`test-utils` % Test)

lazy val `os-environment` =
project
.in(file("lib/java/os-environment"))
.enablePlugins(JPMSPlugin)
.settings(
customFrgaalJavaCompilerSettings("24"),
scalaModuleDependencySetting,
frgaalJavaCompilerSetting,
libraryDependencies ++= slf4jApi ++ Seq(
"org.graalvm.sdk" % "nativeimage" % graalMavenPackagesVersion % "provided",
"org.graalvm.sdk" % "graal-sdk" % graalMavenPackagesVersion % "provided",
Expand All @@ -4277,6 +4349,7 @@ lazy val `os-environment` =
Compile / internalModuleDependencies ++= Seq(
(`engine-common` / Compile / exportedModule).value,
(`persistance` / Compile / exportedModule).value,
(`jvm-channel` / Compile / exportedModule).value,
(`logging-utils` / Compile / exportedModule).value,
(`logging-config` / Compile / exportedModule).value
),
Expand Down Expand Up @@ -4332,6 +4405,7 @@ lazy val `os-environment` =
.value,
Test / fork := true
)
.dependsOn(`jvm-channel`)
.dependsOn(`persistance`)
.dependsOn(`persistance-dsl` % "provided")
.dependsOn(`engine-common`)
Expand Down
4 changes: 4 additions & 0 deletions engine/common/src/main/java/module-info.java
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import org.enso.common.PolyglotSymbolResolver;

module org.enso.engine.common {
requires org.graalvm.nativeimage;
requires org.graalvm.polyglot;
Expand All @@ -6,4 +8,6 @@
requires org.slf4j;

exports org.enso.common;

uses PolyglotSymbolResolver;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package org.enso.common;

import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.ServiceLoader;

/**
* Generic support for loading Java polyglot symbols. The resolver provides two kinds of interfaces:
*
* <ul>
* <li>the client API - represented by all the <b>public static</b> methods
* <li>the SPI - e.g. service provider interface - those are the <b>protected abstract</b> methods
* </ul>
*
* Those who tend to extend the capabilities of loading Java classes into Enso runtime shall
* register their own implementation visible via {@link ServiceLoader}.
*
* @see RuntimeOptions#HOST_CLASS_LOADING
*/
public abstract class PolyglotSymbolResolver {
private static final Collection<PolyglotSymbolResolver> ALL;

static {
var arr = new ArrayList<PolyglotSymbolResolver>();
for (var l : ServiceLoader.load(PolyglotSymbolResolver.class)) {
arr.add(l);
}
ALL = Collections.unmodifiableList(arr);
}

/**
* Search all providers for given name.
*
* @param name dot separated name to search for
* @return non-null object representing the name
* @throws java.lang.ClassNotFoundException if no name was found
*/
public static Object loadClass(String name) throws ClassNotFoundException {
ClassNotFoundException ex = null;
for (var p : ALL) {
try {
var found = p.handleLoadClass(name);
assert found != null;
return found;
} catch (ClassNotFoundException cnfe) {
ex = cnfe;
}
}
if (ex == null) {
throw new ClassNotFoundException(name);
} else {
throw ex;
}
}

public static void addToClassPath(URL url) {
for (var p : ALL) {
p.handleAddToClassPath(url);
}
}

/**
* Subclasses implement this method to search for class with the provided name.
*
* @param name dot separated name to search for
* @return non-{@code null} object representing the name
* @throws java.lang.ClassNotFoundException if no name was found
*/
protected abstract Object handleLoadClass(String name) throws ClassNotFoundException;

protected abstract void handleAddToClassPath(URL url);
}
10 changes: 10 additions & 0 deletions engine/common/src/main/java/org/enso/common/RuntimeOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,15 @@ private RuntimeOptions() {}
private static final OptionDescriptor ENABLE_STATIC_ANALYSIS_DESCRIPTOR =
OptionDescriptor.newBuilder(ENABLE_STATIC_ANALYSIS_KEY, ENABLE_STATIC_ANALYSIS).build();

public static final String HOST_CLASS_LOADING = optionName("classLoading");
public static final OptionKey<String> HOST_CLASS_LOADING_KEY = new OptionKey<>("hosted");
private static final OptionDescriptor HOST_CLASS_LOADING_DESCRIPTOR =
OptionDescriptor.newBuilder(HOST_CLASS_LOADING_KEY, HOST_CLASS_LOADING)
.help("Controls the way Enso runtime resolves polyglot java import statements")
.usageSyntax("Possible values are <hosted|service|all>")
.category(OptionCategory.INTERNAL)
.build();

public static final String TREAT_WARNINGS_AS_ERRORS = optionName("treatWarningsAsErrors");
public static final OptionKey<Boolean> TREAT_WARNINGS_AS_ERRORS_KEY = new OptionKey<>(false);
private static final OptionDescriptor TREAT_WARNINGS_AS_ERRORS_DESCRIPTOR =
Expand Down Expand Up @@ -173,6 +182,7 @@ private RuntimeOptions() {}
DISABLE_INLINE_CACHES_DESCRIPTOR,
DISABLE_PRIVATE_CHECK_DESCRIPTOR,
ENABLE_STATIC_ANALYSIS_DESCRIPTOR,
HOST_CLASS_LOADING_DESCRIPTOR,
TREAT_WARNINGS_AS_ERRORS_DESCRIPTOR,
ENABLE_AUTO_PARALLELISM_DESCRIPTOR,
ENABLE_PROJECT_SUGGESTIONS_DESCRIPTOR,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ object DefaultManagers {
alwaysInstallMissing
),
distributionManager,
new GraalVersionManager(distributionManager, LauncherEnvironment),
new GraalVersionManager(distributionManager),
temporaryDirectoryManager,
defaultResourceManager,
EngineRepository.defaultEngineReleaseProvider,
Expand Down
1 change: 1 addition & 0 deletions engine/runner/src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
requires org.enso.librarymanager;
requires org.enso.logging.config;
requires org.enso.logging.utils;
requires org.enso.jvm.channel;
requires org.enso.os.environment;
requires org.enso.runtime.parser;
requires org.enso.runtime.version.manager;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ private static Path findJavaExecutableInDistributionRuntimes() {
if (distributionManager.isRunningPortable()) {
logger.trace("Running in portable distribution");
}
var graalVersionManager = new GraalVersionManager(distributionManager, env);
var graalVersionManager = new GraalVersionManager(distributionManager);
var versionUsedForBuild =
new GraalVMVersion(BuildVersion.graalVersion(), BuildVersion.javaVersion());
var runtimeWithExactVersionMatch = graalVersionManager.findGraalRuntime(versionUsedForBuild);
Expand Down
11 changes: 10 additions & 1 deletion engine/runner/src/main/java/org/enso/runner/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@
import org.enso.distribution.DistributionManager;
import org.enso.distribution.Environment;
import org.enso.editions.DefaultEdition;
import org.enso.jvm.channel.JVM;
import org.enso.libraryupload.LibraryUploader.UploadFailedError;
import org.enso.os.environment.jni.JVM;
import org.enso.pkg.Contact;
import org.enso.pkg.PackageManager;
import org.enso.pkg.PackageManager$;
Expand Down Expand Up @@ -1574,6 +1574,15 @@ private void launch(String[] args) throws IOException, InterruptedException, URI
}
}

if (System.getProperty("java.home") == null) {
assert HostEnsoUtils.isAot() : "Otherwise java.home would be defined";
var exe = JavaFinder.findJavaExecutable();
if (exe != null) {
var path = exe.getParentFile().getParentFile().getAbsolutePath();
System.setProperty("java.home", path);
LOGGER.debug("Setting java.home property for AOT mode to {}", path);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • runner.Main contains logic for finding the right JVM to handle the --jvm
  • the same logic should be used by jvm-interop module when creating the "other JVM"
  • the simplest trick for these two to communicate is to set java.home property
  • the property is null in SVM by default, hence we don't override any value by setting it here
  • and reading it in jvm-interop module is simple

}
}
handleLaunch(originalCwdOrNull, line, logLevel, logMasking[0]);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,11 @@ private static <T> T serde(Class<T> clazz, T l, int expectedSize) throws IOExcep

private static <T> T serde(Class<T> clazz, T l, int expectedSize, Function<Object, Object> fn)
throws IOException {
var arr = POOL.write(l, fn);
var arr = POOL.withWriteReplace(fn).write(l);
if (expectedSize >= 0) {
assertEquals(expectedSize, arr.length - 12);
}
var ref = POOL.read(arr, null);
var ref = POOL.read(arr);
return ref.get(clazz);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1038,20 +1038,21 @@ class ImportExportTest
.toList
.collect({ case w: Warning.DuplicatedImport => w })
warn.size shouldEqual 1
val arr = org.enso.interpreter.caches.PersistUtils.POOL.write(
mainIr,
{
case metadata: ProcessingPass.Metadata =>
metadata.prepareForSerialization(
ctx
.ensoContext()
.getCompiler
.context
.asInstanceOf[metadata.Compiler]
);
case obj => obj
}
);
val arr = org.enso.interpreter.caches.PersistUtils.POOL
.withWriteReplace(
{
case metadata: ProcessingPass.Metadata =>
metadata.prepareForSerialization(
ctx
.ensoContext()
.getCompiler
.context
.asInstanceOf[metadata.Compiler]
);
case obj => obj
}
)
.write(mainIr);
arr should not be empty
}

Expand Down Expand Up @@ -1079,20 +1080,21 @@ class ImportExportTest
.asInstanceOf[errors.ImportExport.AmbiguousImport]
ambiguousImport.symbolName shouldEqual "A_Type"
try {
val arr = org.enso.interpreter.caches.PersistUtils.POOL.write(
mainIr,
{
case metadata: ProcessingPass.Metadata =>
metadata.prepareForSerialization(
ctx
.ensoContext()
.getCompiler
.context
.asInstanceOf[metadata.Compiler]
);
case obj => obj
}
);
val arr = org.enso.interpreter.caches.PersistUtils.POOL
.withWriteReplace(
{
case metadata: ProcessingPass.Metadata =>
metadata.prepareForSerialization(
ctx
.ensoContext()
.getCompiler
.context
.asInstanceOf[metadata.Compiler]
);
case obj => obj
}
)
.write(mainIr);
fail("Shouldn't return anything when there is an error" + arr)
} catch {
case ex: IOException =>
Expand Down
Loading
Loading