Skip to content

Commit

Permalink
Separate instance of HostClassLoader per project
Browse files Browse the repository at this point in the history
  • Loading branch information
Akirathan committed Dec 16, 2024
1 parent a67afda commit c98bdaf
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@ static AddToClassPathNode build() {
Object doExecute(Object path, @Cached ExpectStringNode expectStringNode) {
var ctx = EnsoContext.get(this);
var file = ctx.getTruffleFile(new File(expectStringNode.execute(path)));
ctx.addToClassPath(file);
return ctx.getBuiltins().nothing();
var pkg = ctx.getPackageOf(file);
if (pkg.isEmpty()) {
throw ctx.raiseAssertionPanic(this, "File " + file + "should be in a package", null);
} else {
ctx.addToClassPath(file, pkg.get());
return ctx.getBuiltins().nothing();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
Expand Down Expand Up @@ -82,7 +84,7 @@ public final class EnsoContext {

private final EnsoLanguage language;
private final Env environment;
private final HostClassLoader hostClassLoader = new HostClassLoader();
private final Map<LibraryName, HostClassLoader> hostClassLoaders = new HashMap<>();
private final boolean assertionsEnabled;
private final boolean isPrivateCheckDisabled;
private final boolean isStaticTypeAnalysisEnabled;
Expand Down Expand Up @@ -297,7 +299,7 @@ public void shutdown() {
packageRepository.shutdown();
guestJava = null;
topScope = null;
hostClassLoader.close();
hostClassLoaders.values().forEach(HostClassLoader::close);
EnsoParser.freeAll();
}

Expand Down Expand Up @@ -466,10 +468,16 @@ public Optional<Module> findModuleByExpressionId(UUID expressionId) {
* Modifies the classpath to use to lookup {@code polyglot java} imports.
*
* @param file the file to register
* @param pkg Package the file belongs to
*/
@TruffleBoundary
public void addToClassPath(TruffleFile file) {
public void addToClassPath(TruffleFile file, Package<TruffleFile> pkg) {
if (findGuestJava() == null) {
var hostClassLoader = hostClassLoaders.get(pkg.libraryName());
if (hostClassLoader == null) {
hostClassLoader = new HostClassLoader(pkg);
hostClassLoaders.put(pkg.libraryName(), hostClassLoader);
}
try {
var url = file.toUri().toURL();
hostClassLoader.add(url);
Expand Down Expand Up @@ -589,16 +597,32 @@ public TruffleObject lookupJavaClass(String className) {
return getBuiltins().error().makeMissingPolyglotImportError(className);
}

/**
* Tries to find a Java class by its fully qualified name in all the {@link HostClassLoader host
* class loaders}.
*/
private Object lookupHostSymbol(String fqn)
throws ClassNotFoundException, UnknownIdentifierException, UnsupportedMessageException {
try {
if (findGuestJava() == null) {
return environment.asHostSymbol(hostClassLoader.loadClass(fqn));
} else {
return InteropLibrary.getUncached().readMember(findGuestJava(), fqn);
if (findGuestJava() == null) {
Class<?> clazz = null;
ClassNotFoundException lastEx = null;
for (var hostClassLoader : hostClassLoaders.values()) {
try {
clazz = hostClassLoader.loadClass(fqn);
if (clazz != null) {
break;
}
} catch (ClassNotFoundException e) {
lastEx = e;
continue;
}
}
if (clazz == null) {
throw new ClassNotFoundException("Error loading host symbol " + fqn, lastEx);
}
} catch (Error e) {
throw new ClassNotFoundException("Error loading " + fqn, e);
return environment.asHostSymbol(clazz);
} else {
return InteropLibrary.getUncached().readMember(findGuestJava(), fqn);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package org.enso.interpreter.runtime;

import com.oracle.truffle.api.TruffleFile;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.enso.pkg.Package;
import org.graalvm.polyglot.Context;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -25,12 +28,16 @@ final class HostClassLoader extends URLClassLoader implements AutoCloseable {
// module layer's class loader.
private static final ClassLoader polyglotClassLoader = Context.class.getClassLoader();

private final Package<TruffleFile> pkg;

// polyglotClassLoader will be used only iff `org.enso.runtime` module is not in the
// boot module layer.
private static final boolean isRuntimeModInBootLayer;

public HostClassLoader() {
public HostClassLoader(Package<TruffleFile> pkg) {
super(new URL[0]);
this.pkg = pkg;
assert pkg.polyglotDir().exists();
}

static {
Expand Down Expand Up @@ -85,4 +92,9 @@ protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundE
public void close() {
loadedClasses.clear();
}

@Override
public String toString() {
return "HostClassLoader(" + pkg.libraryName() + ")";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ private class DefaultPackageRepository(
isLibrary: Boolean
): Unit = {
val extensions = pkg.listPolyglotExtensions("java")
extensions.foreach(context.addToClassPath)
extensions.foreach(ext => context.addToClassPath(ext, pkg))

val (regularModules, syntheticModulesMetadata) = pkg
.listSources()
Expand Down

0 comments on commit c98bdaf

Please sign in to comment.