Avoid Compiler compile time dependency on EnsoContext (#7299)

This commit is contained in:
Jaroslav Tulach 2023-07-17 09:24:22 +01:00 committed by GitHub
parent 7264d81f2a
commit 6864792653
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 685 additions and 245 deletions

View File

@ -0,0 +1,38 @@
package org.enso.polyglot;
/** Defines a stage of compilation of the module. */
public enum CompilationStage {
INITIAL(0),
AFTER_PARSING(1),
AFTER_IMPORT_RESOLUTION(2),
AFTER_GLOBAL_TYPES(3),
AFTER_STATIC_PASSES(4),
AFTER_RUNTIME_STUBS(5),
AFTER_CODEGEN(6);
private final int ordinal;
CompilationStage(int ordinal) {
this.ordinal = ordinal;
}
/**
* Checks whether the current compilation stage is at least as advanced as the provided one.
*
* @param stage the stage to compare to.
* @return whether or not {@code this} is at least as advanced as {@code stage}.
*/
public boolean isAtLeast(CompilationStage stage) {
return ordinal >= stage.ordinal;
}
/**
* Checks that the current compilation stage is before the provided one.
*
* @param stage the stage to compare to.
* @return whether or not {@code this} is before then {@code stage}.
*/
public boolean isBefore(CompilationStage stage) {
return ordinal < stage.ordinal;
}
}

View File

@ -4,8 +4,8 @@ import java.util.logging.Level;
import org.enso.compiler.SerializationManager;
import org.enso.interpreter.instrument.execution.RuntimeContext;
import org.enso.interpreter.runtime.EnsoContext;
import org.enso.interpreter.runtime.Module;
import org.enso.pkg.QualifiedName;
import org.enso.polyglot.CompilationStage;
import org.enso.polyglot.RuntimeOptions;
/** The job that serializes module. */
@ -36,7 +36,7 @@ public final class SerializeModuleJob extends BackgroundJob<Void> {
.findModule(moduleName.toString())
.ifPresent(
module -> {
if (module.getCompilationStage().isBefore(Module.CompilationStage.AFTER_CODEGEN)) {
if (module.getCompilationStage().isBefore(CompilationStage.AFTER_CODEGEN)) {
ctx.executionService()
.getLogger()
.log(

View File

@ -22,6 +22,7 @@ import org.enso.interpreter.instrument.{
import org.enso.interpreter.runtime.Module
import org.enso.interpreter.service.error.ModuleNotFoundForFileException
import org.enso.pkg.QualifiedName
import org.enso.polyglot.CompilationStage
import org.enso.polyglot.runtime.Runtime.Api
import org.enso.polyglot.runtime.Runtime.Api.StackItem
import org.enso.text.buffer.Rope
@ -217,7 +218,7 @@ final class EnsureCompiledJob(protected val files: Iterable[File])
)(implicit ctx: RuntimeContext): Either[Throwable, CompilerResult] =
Either.catchNonFatal {
val compilationStage = module.getCompilationStage
if (!compilationStage.isAtLeast(Module.CompilationStage.AFTER_CODEGEN)) {
if (!compilationStage.isAtLeast(CompilationStage.AFTER_CODEGEN)) {
ctx.executionService.getLogger
.log(Level.FINEST, s"Compiling ${module.getName}.")
val result = ctx.executionService.getContext.getCompiler.run(module)

View File

@ -13,6 +13,7 @@ import org.enso.compiler.core.IR;
import org.enso.interpreter.runtime.EnsoContext;
import org.enso.interpreter.runtime.Module;
import org.enso.interpreter.runtime.builtin.Builtins;
import org.enso.polyglot.CompilationStage;
import java.io.IOException;
import java.io.ObjectInputStream;
@ -49,7 +50,7 @@ public final class ModuleCache extends Cache<ModuleCache.CachedModule, ModuleCac
try (var stream = new ObjectInputStream(new ByteArrayInputStream(data))) {
if (stream.readObject() instanceof IR.Module ir) {
try {
return new CachedModule(ir, Module.CompilationStage.valueOf(meta.compilationStage()), module.getSource());
return new CachedModule(ir,CompilationStage.valueOf(meta.compilationStage()), module.getSource());
} catch (IOException ioe) {
throw new ClassNotFoundException(ioe.getMessage());
}
@ -178,9 +179,9 @@ public final class ModuleCache extends Cache<ModuleCache.CachedModule, ModuleCac
// CachedModule is not a record **on purpose**. There appears to be a Frgaal bug leading to invalid compilation error.
static class CachedModule {
private final IR.Module _moduleIR;
private final Module.CompilationStage _compilationStage;
private final CompilationStage _compilationStage;
private final Source _source;
public CachedModule(IR.Module moduleIR, Module.CompilationStage compilationStage, Source source) {
public CachedModule(IR.Module moduleIR, CompilationStage compilationStage, Source source) {
this._moduleIR = moduleIR;
this._compilationStage = compilationStage;
this._source = source;
@ -189,7 +190,7 @@ public final class ModuleCache extends Cache<ModuleCache.CachedModule, ModuleCac
IR.Module moduleIR() {
return _moduleIR;
}
Module.CompilationStage compilationStage() {
CompilationStage compilationStage() {
return _compilationStage;
}
Source source() {

View File

@ -0,0 +1,98 @@
package org.enso.compiler.context;
import com.oracle.truffle.api.TruffleFile;
import com.oracle.truffle.api.source.Source;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.logging.Level;
import org.enso.compiler.Cache;
import org.enso.compiler.Compiler;
import org.enso.compiler.PackageRepository;
import org.enso.compiler.core.IR;
import org.enso.compiler.data.CompilerConfig;
import org.enso.interpreter.node.ExpressionNode;
import org.enso.interpreter.runtime.Module;
import org.enso.interpreter.runtime.scope.ModuleScope;
import org.enso.interpreter.runtime.scope.TopLevelScope;
import org.enso.pkg.QualifiedName;
import org.enso.polyglot.CompilationStage;
/**
* Interface that encapsulate all services {@link Compiler} needs from Truffle or other environment.
*/
public interface CompilerContext {
boolean isIrCachingDisabled();
boolean isUseGlobalCacheLocations();
boolean isInteractiveMode();
PackageRepository getPackageRepository();
PrintStream getErr();
PrintStream getOut();
void log(Level level, String msg, Object... args);
void logSerializationManager(Level level, String msg, Object... args);
void notifySerializeModule(QualifiedName moduleName);
TopLevelScope getTopScope();
// threads
boolean isCreateThreadAllowed();
Thread createThread(Runnable r);
Thread createSystemThread(Runnable r);
// Truffle related
void truffleRunCodegen(Module module, CompilerConfig config) throws IOException;
void truffleRunCodegen(Source source, ModuleScope scope, CompilerConfig config, IR.Module ir);
ExpressionNode truffleRunInline(
Source source, InlineContext scope, CompilerConfig config, IR.Expression ir);
// module related
QualifiedName getModuleName(Module module);
CharSequence getCharacters(Module module) throws IOException;
void updateModule(Module module, Consumer<Updater> callback);
boolean isSynthetic(Module module);
boolean isInteractive(Module module);
boolean wasLoadedFromCache(Module module);
boolean hasCrossModuleLinks(Module module);
IR.Module getIr(Module module);
CompilationStage getCompilationStage(Module module);
<T> Optional<T> loadCache(Cache<T, ?> cache);
<T> Optional<TruffleFile> saveCache(Cache<T, ?> cache, T entry, boolean useGlobalCacheLocations);
public static interface Updater {
void ir(IR.Module ir);
void compilationStage(CompilationStage stage);
void loadedFromCache(boolean b);
void hasCrossModuleLinks(boolean b);
void resetScope();
void invalidateCache();
}
}

View File

@ -166,7 +166,8 @@ public class EnsoContext {
builtins,
notificationHandler);
topScope = new TopLevelScope(builtins, packageRepository);
this.compiler = new Compiler(this, builtins, packageRepository, compilerConfig);
this.compiler =
new Compiler(new TruffleCompilerContext(this), builtins, packageRepository, compilerConfig);
projectPackage.ifPresent(
pkg -> packageRepository.registerMainProjectPackage(pkg.libraryName(), pkg));

View File

@ -40,6 +40,7 @@ import org.enso.interpreter.runtime.scope.ModuleScope;
import org.enso.interpreter.runtime.type.Types;
import org.enso.pkg.Package;
import org.enso.pkg.QualifiedName;
import org.enso.polyglot.CompilationStage;
import org.enso.polyglot.LanguageInfo;
import org.enso.polyglot.MethodNames;
import org.enso.text.buffer.Rope;
@ -48,44 +49,6 @@ import scala.Function1;
/** Represents a source module with a known location. */
@ExportLibrary(InteropLibrary.class)
public final class Module implements TruffleObject {
/** Defines a stage of compilation of the module. */
public enum CompilationStage {
INITIAL(0),
AFTER_PARSING(1),
AFTER_IMPORT_RESOLUTION(2),
AFTER_GLOBAL_TYPES(3),
AFTER_STATIC_PASSES(4),
AFTER_RUNTIME_STUBS(5),
AFTER_CODEGEN(6);
private final int ordinal;
CompilationStage(int ordinal) {
this.ordinal = ordinal;
}
/**
* Checks whether the current compilation stage is at least as advanced as the provided one.
*
* @param stage the stage to compare to.
* @return whether or not {@code this} is at least as advanced as {@code stage}.
*/
public boolean isAtLeast(CompilationStage stage) {
return ordinal >= stage.ordinal;
}
/**
* Checks that the current compilation stage is before the provided one.
*
* @param stage the stage to compare to.
* @return whether or not {@code this} is before then {@code stage}.
*/
public boolean isBefore(CompilationStage stage) {
return ordinal < stage.ordinal;
}
}
private ModuleScope scope;
private ModuleSources sources;
private PatchedModuleValues patchedValues;
@ -446,7 +409,7 @@ public final class Module implements TruffleObject {
*
* @param compilationStage the new compilation stage for the module.
*/
public void unsafeSetCompilationStage(CompilationStage compilationStage) {
void unsafeSetCompilationStage(CompilationStage compilationStage) {
this.compilationStage = compilationStage;
}
@ -459,7 +422,7 @@ public final class Module implements TruffleObject {
*
* @param ir the new IR for the module.
*/
public void unsafeSetIr(IR.Module ir) {
void unsafeSetIr(IR.Module ir) {
this.ir = ir;
this.uuidsMap = null;
}
@ -532,7 +495,7 @@ public final class Module implements TruffleObject {
}
/** @param wasLoadedFromCache whether or not the module was loaded from the cache */
public void setLoadedFromCache(boolean wasLoadedFromCache) {
void setLoadedFromCache(boolean wasLoadedFromCache) {
this.wasLoadedFromCache = wasLoadedFromCache;
}
@ -545,7 +508,7 @@ public final class Module implements TruffleObject {
}
/** @param hasCrossModuleLinks whether or not the module has cross-module links restored */
public void setHasCrossModuleLinks(boolean hasCrossModuleLinks) {
void setHasCrossModuleLinks(boolean hasCrossModuleLinks) {
this.hasCrossModuleLinks = hasCrossModuleLinks;
}

View File

@ -0,0 +1,246 @@
package org.enso.interpreter.runtime;
import com.oracle.truffle.api.TruffleFile;
import com.oracle.truffle.api.TruffleLogger;
import com.oracle.truffle.api.source.Source;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.logging.Level;
import org.enso.compiler.Cache;
import org.enso.compiler.Compiler;
import org.enso.compiler.PackageRepository;
import org.enso.compiler.SerializationManager;
import org.enso.compiler.codegen.IrToTruffle;
import org.enso.compiler.context.CompilerContext;
import org.enso.compiler.context.InlineContext;
import org.enso.compiler.core.IR;
import org.enso.compiler.data.CompilerConfig;
import org.enso.interpreter.node.ExpressionNode;
import org.enso.interpreter.runtime.scope.LocalScope;
import org.enso.interpreter.runtime.scope.ModuleScope;
import org.enso.interpreter.runtime.scope.TopLevelScope;
import org.enso.pkg.QualifiedName;
import org.enso.polyglot.CompilationStage;
import org.enso.polyglot.RuntimeOptions;
final class TruffleCompilerContext implements CompilerContext {
private final EnsoContext context;
private final TruffleLogger compiler;
private final TruffleLogger serializationManager;
TruffleCompilerContext(EnsoContext context) {
this.context = context;
this.compiler = context.getLogger(Compiler.class);
this.serializationManager = context.getLogger(SerializationManager.class);
}
@Override
public boolean isIrCachingDisabled() {
return context.isIrCachingDisabled();
}
@Override
public boolean isUseGlobalCacheLocations() {
return context
.getEnvironment()
.getOptions()
.get(RuntimeOptions.USE_GLOBAL_IR_CACHE_LOCATION_KEY);
}
@Override
public boolean isInteractiveMode() {
return context.getEnvironment().getOptions().get(RuntimeOptions.INTERACTIVE_MODE_KEY);
}
@Override
public PackageRepository getPackageRepository() {
return context.getPackageRepository();
}
@Override
public PrintStream getErr() {
return context.getErr();
}
@Override
public PrintStream getOut() {
return context.getOut();
}
@Override
public void log(Level level, String msg, Object... args) {
compiler.log(level, msg, args);
}
@Override
public void logSerializationManager(Level level, String msg, Object... args) {
serializationManager.log(level, msg, args);
}
@Override
public void notifySerializeModule(QualifiedName moduleName) {
context.getNotificationHandler().serializeModule(moduleName);
}
@Override
public TopLevelScope getTopScope() {
return context.getTopScope();
}
@Override
public boolean isCreateThreadAllowed() {
return context.getEnvironment().isCreateThreadAllowed();
}
@Override
public Thread createThread(Runnable r) {
return context.getEnvironment().createThread(r);
}
@Override
public Thread createSystemThread(Runnable r) {
return context.getEnvironment().createSystemThread(r);
}
@Override
public void truffleRunCodegen(Module module, CompilerConfig config) throws IOException {
truffleRunCodegen(module.getSource(), module.getScope(), config, module.getIr());
}
@Override
public void truffleRunCodegen(
Source source, ModuleScope scope, CompilerConfig config, IR.Module ir) {
new IrToTruffle(context, source, scope, config).run(ir);
}
@Override
public ExpressionNode truffleRunInline(
Source source, InlineContext inlineContext, CompilerConfig config, IR.Expression ir) {
var localScope =
inlineContext.localScope().isDefined()
? inlineContext.localScope().get()
: LocalScope.root();
return new IrToTruffle(context, source, inlineContext.module().getScope(), config)
.runInline(ir, localScope, "<inline_source>");
}
// module related
@Override
public QualifiedName getModuleName(Module module) {
return module.getName();
}
@Override
public CharSequence getCharacters(Module module) throws IOException {
return module.getSource().getCharacters();
}
@Override
public boolean isSynthetic(Module module) {
return module.isSynthetic();
}
@Override
public boolean isInteractive(Module module) {
return module.isInteractive();
}
@Override
public boolean wasLoadedFromCache(Module module) {
return module.wasLoadedFromCache();
}
@Override
public boolean hasCrossModuleLinks(Module module) {
return module.hasCrossModuleLinks();
}
@Override
public IR.Module getIr(Module module) {
return module.getIr();
}
@Override
public CompilationStage getCompilationStage(Module module) {
return module.getCompilationStage();
}
@Override
public void updateModule(Module module, Consumer<Updater> callback) {
try (var u = new ModuleUpdater(module)) {
callback.accept(u);
}
}
@Override
public <T> Optional<T> loadCache(Cache<T, ?> cache) {
return cache.load(context);
}
@Override
public <T> Optional<TruffleFile> saveCache(
Cache<T, ?> cache, T entry, boolean useGlobalCacheLocations) {
return cache.save(entry, context, useGlobalCacheLocations);
}
private final class ModuleUpdater implements Updater, AutoCloseable {
private final Module module;
private IR.Module ir;
private CompilationStage stage;
private Boolean loadedFromCache;
private Boolean hasCrossModuleLinks;
private boolean resetScope;
private boolean invalidateCache;
private ModuleUpdater(org.enso.interpreter.runtime.Module module) {
this.module = module;
}
@Override
public void ir(IR.Module ir) {
this.ir = ir;
}
@Override
public void compilationStage(CompilationStage stage) {
this.stage = stage;
}
@Override
public void loadedFromCache(boolean b) {
this.loadedFromCache = b;
}
@Override
public void hasCrossModuleLinks(boolean b) {
this.hasCrossModuleLinks = b;
}
@Override
public void resetScope() {
this.resetScope = true;
}
@Override
public void invalidateCache() {
this.invalidateCache = true;
}
@Override
public void close() {
if (ir != null) module.unsafeSetIr(ir);
if (stage != null) module.unsafeSetCompilationStage(stage);
if (loadedFromCache != null) module.setLoadedFromCache(loadedFromCache);
if (hasCrossModuleLinks != null) module.setHasCrossModuleLinks(hasCrossModuleLinks);
if (resetScope) {
module.ensureScopeExists();
module.getScope().reset();
}
if (invalidateCache) {
module.getCache().invalidate(context);
}
}
}
}

View File

@ -17,6 +17,7 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import org.enso.compiler.context.CompilerContext;
import org.enso.compiler.Passes;
import org.enso.compiler.context.FreshNameSupply;
import org.enso.compiler.core.CompilerError;
@ -216,12 +217,12 @@ public final class Builtins {
* @param passes the passes manager for the compiler
*/
@CompilerDirectives.TruffleBoundary
public void initializeBuiltinsIr(FreshNameSupply freshNameSupply, Passes passes) {
public void initializeBuiltinsIr(CompilerContext context, FreshNameSupply freshNameSupply, Passes passes) {
try {
if (module.getSource() == null) {
initializeBuiltinsSource();
}
BuiltinsIrBuilder.build(module, freshNameSupply, passes);
BuiltinsIrBuilder.build(context, module, freshNameSupply, passes);
} catch (IOException e) {
e.printStackTrace();
}

View File

@ -1,9 +1,13 @@
package org.enso.compiler
import com.oracle.truffle.api.TruffleLogger
import com.oracle.truffle.api.source.{Source, SourceSection}
import org.enso.compiler.codegen.{IrToTruffle, RuntimeStubsGenerator}
import org.enso.compiler.context.{FreshNameSupply, InlineContext, ModuleContext}
import org.enso.compiler.codegen.RuntimeStubsGenerator
import org.enso.compiler.context.{
CompilerContext,
FreshNameSupply,
InlineContext,
ModuleContext
}
import org.enso.compiler.core.CompilerError
import org.enso.compiler.core.CompilerStub
import org.enso.compiler.core.IR
@ -20,12 +24,11 @@ import org.enso.compiler.phase.{
import org.enso.editions.LibraryName
import org.enso.interpreter.node.{ExpressionNode => RuntimeExpression}
import org.enso.interpreter.runtime.builtin.Builtins
import org.enso.interpreter.runtime.scope.{LocalScope, ModuleScope}
import org.enso.interpreter.runtime.{EnsoContext, Module}
import org.enso.interpreter.runtime.scope.ModuleScope
import org.enso.interpreter.runtime.Module
import org.enso.pkg.QualifiedName
import org.enso.polyglot.{LanguageInfo, RuntimeOptions}
//import org.enso.syntax.text.Parser
//import org.enso.syntax.text.Parser.IDMap
import org.enso.polyglot.LanguageInfo
import org.enso.polyglot.CompilationStage
import org.enso.syntax2.Tree
import java.io.{PrintStream, StringReader}
@ -47,7 +50,7 @@ import scala.jdk.OptionConverters._
* @param context the language context
*/
class Compiler(
val context: EnsoContext,
val context: CompilerContext,
val builtins: Builtins,
val packageRepository: PackageRepository,
config: CompilerConfig
@ -58,15 +61,11 @@ class Compiler(
private val importResolver: ImportResolver = new ImportResolver(this)
private val stubsGenerator: RuntimeStubsGenerator =
new RuntimeStubsGenerator(builtins)
private val irCachingEnabled = !context.isIrCachingDisabled
private val useGlobalCacheLocations = context.getEnvironment.getOptions.get(
RuntimeOptions.USE_GLOBAL_IR_CACHE_LOCATION_KEY
)
private val isInteractiveMode =
context.getEnvironment.getOptions.get(RuntimeOptions.INTERACTIVE_MODE_KEY)
private val irCachingEnabled = !context.isIrCachingDisabled
private val useGlobalCacheLocations = context.isUseGlobalCacheLocations
private val isInteractiveMode = context.isInteractiveMode()
private val serializationManager: SerializationManager =
new SerializationManager(this)
private val logger: TruffleLogger = context.getLogger(getClass)
private val output: PrintStream =
if (config.outputRedirect.isDefined)
new PrintStream(config.outputRedirect.get)
@ -82,7 +81,7 @@ class Compiler(
TimeUnit.SECONDS,
new LinkedBlockingDeque[Runnable](),
(runnable: Runnable) => {
context.getEnvironment.createThread(runnable)
context.createThread(runnable)
}
)
} else null
@ -108,7 +107,7 @@ class Compiler(
/** Lazy-initializes the IR for the builtins module. */
private def initializeBuiltinsIr(): Unit = {
if (!builtins.isIrInitialized) {
logger.log(
context.log(
Compiler.defaultLogLevel,
"Initialising IR for [{0}].",
builtins.getModule.getName
@ -120,20 +119,28 @@ class Compiler(
serializationManager.deserialize(builtins.getModule) match {
case Some(true) =>
// Ensure that builtins doesn't try and have codegen run on it.
builtins.getModule.unsafeSetCompilationStage(
Module.CompilationStage.AFTER_CODEGEN
context.updateModule(
builtins.getModule,
{ u =>
u.compilationStage(CompilationStage.AFTER_CODEGEN)
}
)
case _ =>
builtins.initializeBuiltinsIr(freshNameSupply, passes)
builtins.getModule.setHasCrossModuleLinks(true)
builtins.initializeBuiltinsIr(context, freshNameSupply, passes)
context.updateModule(
builtins.getModule,
u => u.hasCrossModuleLinks(true)
)
}
} else {
builtins.initializeBuiltinsIr(freshNameSupply, passes)
builtins.getModule.setHasCrossModuleLinks(true)
builtins.initializeBuiltinsIr(context, freshNameSupply, passes)
context.updateModule(
builtins.getModule,
u => u.hasCrossModuleLinks(true)
)
}
if (irCachingEnabled && !builtins.getModule.wasLoadedFromCache()) {
if (irCachingEnabled && !context.wasLoadedFromCache(builtins.getModule)) {
serializationManager.serializeModule(
builtins.getModule,
useGlobalCacheLocations = true // Builtins can't have a local cache.
@ -146,6 +153,10 @@ class Compiler(
def getSerializationManager: SerializationManager =
serializationManager
/** @return the package repository instance. */
def getPackageRepository(): PackageRepository =
context.getPackageRepository
/** Processes the provided language sources, registering any bindings in the
* given scope.
*
@ -173,11 +184,9 @@ class Compiler(
shouldCompileDependencies: Boolean,
useGlobalCacheLocations: Boolean
): Future[Boolean] = {
val packageRepository = context.getPackageRepository
packageRepository.getMainProjectPackage match {
getPackageRepository().getMainProjectPackage match {
case None =>
logger.log(
context.log(
Level.SEVERE,
"No package found in the compiler environment. Aborting."
)
@ -188,14 +197,14 @@ class Compiler(
)
packageModule match {
case None =>
logger.log(
context.log(
Level.SEVERE,
"Could not find entry point for compilation in package [{0}.{1}]",
Array(pkg.namespace, pkg.name)
)
CompletableFuture.completedFuture(false)
case Some(m) =>
logger.log(
context.log(
Compiler.defaultLogLevel,
s"Compiling the package [${pkg.namespace}.${pkg.name}] " +
s"starting at the root [${m.getName}]."
@ -273,25 +282,25 @@ class Compiler(
var requiredModules = modules.flatMap { module =>
val importedModules = runImportsAndExportsResolution(module, generateCode)
val isLoadedFromSource =
(m: Module) => !m.wasLoadedFromCache() && !m.isSynthetic
(m: Module) => !context.wasLoadedFromCache(m) && !context.isSynthetic(m)
if (
shouldCompileDependencies &&
module.wasLoadedFromCache() &&
context.wasLoadedFromCache(module) &&
importedModules.exists(isLoadedFromSource)
) {
val importedModulesLoadedFromSource = importedModules
.filter(isLoadedFromSource)
.map(_.getName)
logger.log(
.map(context.getModuleName(_))
context.log(
Compiler.defaultLogLevel,
"{0} imported module caches were invalided, forcing invalidation of {1}. [{2}]",
Array(
importedModulesLoadedFromSource.length,
module.getName.toString,
context.getModuleName(module).toString,
importedModulesLoadedFromSource.take(10).mkString("", ",", "...")
)
)
module.getCache.invalidate(context)
context.updateModule(module, _.invalidateCache)
parseModule(module)
runImportsAndExportsResolution(module, generateCode)
} else {
@ -302,22 +311,25 @@ class Compiler(
var hasInvalidModuleRelink = false
if (irCachingEnabled) {
requiredModules.foreach { module =>
if (!module.hasCrossModuleLinks) {
if (!context.hasCrossModuleLinks(module)) {
val flags =
module.getIr.preorder.map(_.passData.restoreFromSerialization(this))
context
.getIr(module)
.preorder
.map(_.passData.restoreFromSerialization(this))
if (!flags.contains(false)) {
logger.log(
context.log(
Compiler.defaultLogLevel,
"Restored links (late phase) for module [{0}].",
module.getName
context.getModuleName(module)
)
} else {
hasInvalidModuleRelink = true
logger.log(
context.log(
Compiler.defaultLogLevel,
"Failed to restore links (late phase) for module [{0}].",
module.getName
context.getModuleName(module)
)
uncachedParseModule(module, isGenDocs = false)
}
@ -326,7 +338,7 @@ class Compiler(
}
if (hasInvalidModuleRelink) {
logger.log(
context.log(
Compiler.defaultLogLevel,
s"Some modules failed to relink. Re-running import and " +
s"export resolution."
@ -338,9 +350,11 @@ class Compiler(
requiredModules.foreach { module =>
if (
!module.getCompilationStage.isAtLeast(
Module.CompilationStage.AFTER_GLOBAL_TYPES
)
!context
.getCompilationStage(module)
.isAtLeast(
CompilationStage.AFTER_GLOBAL_TYPES
)
) {
val moduleContext = ModuleContext(
@ -348,18 +362,25 @@ class Compiler(
freshNameSupply = Some(freshNameSupply),
compilerConfig = config
)
val compilerOutput = runGlobalTypingPasses(module.getIr, moduleContext)
module.unsafeSetIr(compilerOutput)
module.unsafeSetCompilationStage(
Module.CompilationStage.AFTER_GLOBAL_TYPES
val compilerOutput =
runGlobalTypingPasses(context.getIr(module), moduleContext)
context.updateModule(
module,
{ u =>
u.ir(compilerOutput)
u.compilationStage(CompilationStage.AFTER_GLOBAL_TYPES)
}
)
}
}
requiredModules.foreach { module =>
if (
!module.getCompilationStage.isAtLeast(
Module.CompilationStage.AFTER_STATIC_PASSES
)
!context
.getCompilationStage(module)
.isAtLeast(
CompilationStage.AFTER_STATIC_PASSES
)
) {
val moduleContext = ModuleContext(
@ -368,10 +389,14 @@ class Compiler(
compilerConfig = config,
pkgRepo = Some(packageRepository)
)
val compilerOutput = runMethodBodyPasses(module.getIr, moduleContext)
module.unsafeSetIr(compilerOutput)
module.unsafeSetCompilationStage(
Module.CompilationStage.AFTER_STATIC_PASSES
val compilerOutput =
runMethodBodyPasses(context.getIr(module), moduleContext)
context.updateModule(
module,
{ u =>
u.ir(compilerOutput)
u.compilationStage(CompilationStage.AFTER_STATIC_PASSES)
}
)
}
}
@ -380,40 +405,52 @@ class Compiler(
requiredModules.foreach { module =>
if (
!module.getCompilationStage.isAtLeast(
Module.CompilationStage.AFTER_RUNTIME_STUBS
)
!context
.getCompilationStage(module)
.isAtLeast(
CompilationStage.AFTER_RUNTIME_STUBS
)
) {
stubsGenerator.run(module)
module.unsafeSetCompilationStage(
Module.CompilationStage.AFTER_RUNTIME_STUBS
context.updateModule(
module,
{ u =>
u.compilationStage(CompilationStage.AFTER_RUNTIME_STUBS)
}
)
}
}
requiredModules.foreach { module =>
if (
!module.getCompilationStage.isAtLeast(
Module.CompilationStage.AFTER_CODEGEN
)
!context
.getCompilationStage(module)
.isAtLeast(
CompilationStage.AFTER_CODEGEN
)
) {
if (generateCode) {
logger.log(
context.log(
Compiler.defaultLogLevel,
"Generating code for module [{0}].",
module.getName
context.getModuleName(module)
)
truffleCodegen(module.getIr, module.getSource, module.getScope)
context.truffleRunCodegen(module, config)
}
module.unsafeSetCompilationStage(Module.CompilationStage.AFTER_CODEGEN)
context.updateModule(
module,
{ u =>
u.compilationStage(CompilationStage.AFTER_CODEGEN)
}
)
if (shouldCompileDependencies || isModuleInRootPackage(module)) {
val shouldStoreCache =
irCachingEnabled && !module.wasLoadedFromCache()
irCachingEnabled && !context.wasLoadedFromCache(module)
if (shouldStoreCache && !hasErrors(module) && !module.isInteractive) {
if (isInteractiveMode) {
context.getNotificationHandler.serializeModule(module.getName)
context.notifySerializeModule(context.getModuleName(module))
} else {
serializationManager.serializeModule(
module,
@ -422,10 +459,10 @@ class Compiler(
}
}
} else {
logger.log(
context.log(
Compiler.defaultLogLevel,
"Skipping serialization for [{0}].",
module.getName
context.getModuleName(module)
)
}
}
@ -435,11 +472,11 @@ class Compiler(
}
private def isModuleInRootPackage(module: Module): Boolean = {
if (!module.isInteractive) {
if (!context.isInteractive(module)) {
val pkg = PackageRepositoryUtils
.getPackageOf(context.getPackageRepository, module.getSourceFile)
.getPackageOf(getPackageRepository(), module.getSourceFile)
.toScala
pkg.contains(context.getPackageRepository.getMainProjectPackage.get)
pkg.contains(getPackageRepository().getMainProjectPackage.get)
} else false
}
@ -483,7 +520,7 @@ class Compiler(
private def ensureParsedAndAnalyzed(module: Module): Unit = {
ensureParsed(module)
if (module.isSynthetic) {
if (context.isSynthetic(module)) {
// Synthetic modules need to be import-analyzed
// i.e. we need to fill in resolved{Imports/Exports} and exportedSymbols in bindings
// because we do not generate (and deserialize) IR for them
@ -495,7 +532,7 @@ class Compiler(
.map { concreteBindings =>
concreteBindings
}
val ir = module.getIr
val ir = context.getIr(module)
val currentLocal = ir.unsafeGetMetadata(
BindingAnalysis,
"Synthetic parsed module missing bindings"
@ -524,7 +561,7 @@ class Compiler(
*/
def gatherImportStatements(module: Module): Array[String] = {
ensureParsed(module)
val importedModules = module.getIr.imports.flatMap {
val importedModules = context.getIr(module).imports.flatMap {
case imp: IR.Module.Scope.Import.Module =>
imp.name.parts.take(2).map(_.name) match {
case List(namespace, name) => List(LibraryName(namespace, name))
@ -537,7 +574,8 @@ class Compiler(
Nil
case other =>
throw new CompilerError(
s"Unexpected import type after processing ${module.getName}: [$other]."
s"Unexpected import type after processing ${context
.getModuleName(module)}: [$other]."
)
}
importedModules.distinct.map(_.qualifiedName).toArray
@ -547,15 +585,14 @@ class Compiler(
module: Module,
isGenDocs: Boolean = false
): Unit = {
logger.log(
context.log(
Compiler.defaultLogLevel,
"Parsing module [{0}].",
module.getName
context.getModuleName(module)
)
module.ensureScopeExists()
module.getScope.reset()
context.updateModule(module, _.resetScope)
if (irCachingEnabled && !module.isInteractive) {
if (irCachingEnabled && !context.isInteractive(module)) {
serializationManager.deserialize(module) match {
case Some(_) => return
case _ =>
@ -571,7 +608,7 @@ class Compiler(
* @return module's bindings, if available in libraries' bindings cache
*/
def importExportBindings(module: Module): Option[BindingsMap] = {
if (irCachingEnabled && !module.isInteractive) {
if (irCachingEnabled && !context.isInteractive(module)) {
val libraryName = Option(module.getPackage).map(_.libraryName)
libraryName
.flatMap(packageRepository.getLibraryBindings(_, serializationManager))
@ -580,13 +617,12 @@ class Compiler(
}
private def uncachedParseModule(module: Module, isGenDocs: Boolean): Unit = {
logger.log(
context.log(
Compiler.defaultLogLevel,
"Loading module [{0}] from source.",
module.getName
context.getModuleName(module)
)
module.ensureScopeExists()
module.getScope.reset()
context.updateModule(module, _.resetScope)
val moduleContext = ModuleContext(
module = module,
@ -595,21 +631,26 @@ class Compiler(
isGeneratingDocs = isGenDocs
)
val src = module.getSource
val tree = ensoCompiler.parse(src.getCharacters)
val src = context.getCharacters(module)
val tree = ensoCompiler.parse(src)
val expr = ensoCompiler.generateIR(tree)
val exprWithModuleExports =
if (module.isSynthetic)
if (context.isSynthetic(module))
expr
else
injectSyntheticModuleExports(expr, module.getDirectModulesRefs)
val discoveredModule =
recognizeBindings(exprWithModuleExports, moduleContext)
module.unsafeSetIr(discoveredModule)
module.unsafeSetCompilationStage(Module.CompilationStage.AFTER_PARSING)
module.setLoadedFromCache(false)
module.setHasCrossModuleLinks(true)
context.updateModule(
module,
{ u =>
u.ir(discoveredModule)
u.compilationStage(CompilationStage.AFTER_PARSING)
u.loadedFromCache(false)
u.hasCrossModuleLinks(true)
}
)
}
/* Note [Polyglot Imports In Dependency Gathering]
@ -640,9 +681,11 @@ class Compiler(
*/
def ensureParsed(module: Module): Unit = {
if (
!module.getCompilationStage.isAtLeast(
Module.CompilationStage.AFTER_PARSING
)
!context
.getCompilationStage(module)
.isAtLeast(
CompilationStage.AFTER_PARSING
)
) {
parseModule(module)
}
@ -703,7 +746,7 @@ class Compiler(
}
if (
!module.getCompilationStage.isAtLeast(
Module.CompilationStage.AFTER_RUNTIME_STUBS
CompilationStage.AFTER_RUNTIME_STUBS
)
) {
throw new CompilerError(
@ -903,7 +946,7 @@ class Compiler(
def gatherDiagnostics(module: Module): List[IR.Diagnostic] = {
GatherDiagnostics
.runModule(
module.getIr,
context.getIr(module),
ModuleContext(module, compilerConfig = config)
)
.unsafeGetMetadata(
@ -1212,7 +1255,7 @@ class Compiler(
source: Source,
scope: ModuleScope
): Unit = {
new IrToTruffle(context, source, scope, config).run(ir)
context.truffleRunCodegen(source, scope, config, ir)
}
/** Generates code for the truffle interpreter in an inline context.
@ -1228,16 +1271,7 @@ class Compiler(
source: Source,
inlineContext: InlineContext
): RuntimeExpression = {
new IrToTruffle(
context,
source,
inlineContext.module.getScope,
config
).runInline(
ir,
inlineContext.localScope.getOrElse(LocalScope.root),
"<inline_source>"
)
context.truffleRunInline(source, inlineContext, config, ir);
}
/** Performs shutdown actions for the compiler.

View File

@ -29,6 +29,7 @@ import org.enso.pkg.{
SourceFile
}
import org.enso.text.buffer.Rope
import org.enso.polyglot.CompilationStage
import java.nio.file.Path
import scala.collection.immutable.ListSet
@ -292,7 +293,7 @@ object PackageRepository {
module <- getComponentModules
isCompiled =
module.getCompilationStage.isAtLeast(
Module.CompilationStage.AFTER_CODEGEN
CompilationStage.AFTER_CODEGEN
)
if !isCompiled
} yield module

View File

@ -1,6 +1,5 @@
package org.enso.compiler
import com.oracle.truffle.api.TruffleLogger
import com.oracle.truffle.api.source.Source
import org.enso.compiler.context.{ExportsBuilder, ExportsMap, SuggestionBuilder}
import org.enso.compiler.core.IR
@ -9,6 +8,7 @@ import org.enso.editions.LibraryName
import org.enso.interpreter.runtime.Module
import org.enso.pkg.QualifiedName
import org.enso.polyglot.Suggestion
import org.enso.polyglot.CompilationStage
import java.io.NotSerializableException
import java.util
@ -35,10 +35,6 @@ final class SerializationManager(
/** The debug logging level. */
private val debugLogLevel = Level.FINE
/** A logger for messages regarding serialization. */
private val logger: TruffleLogger =
compiler.context.getLogger(classOf[SerializationManager])
/** A set of the modules that are currently being serialized.
*
* This set is accessed concurrently. This is safe as it is backed by a
@ -54,9 +50,6 @@ final class SerializationManager(
private val isWaitingForSerialization =
collection.concurrent.TrieMap[QualifiedName, Future[Boolean]]()
/** The runtime's environment. */
private val env = compiler.context.getEnvironment
/** The thread pool that handles serialization. */
private val pool: ThreadPoolExecutor = new ThreadPoolExecutor(
SerializationManager.startingThreadCount,
@ -65,13 +58,13 @@ final class SerializationManager(
TimeUnit.SECONDS,
new LinkedBlockingDeque[Runnable](),
(runnable: Runnable) => {
env.createSystemThread(runnable)
compiler.context.createSystemThread(runnable)
}
)
// Make sure it is started to avoid races with language shutdown with low job
// count.
if (compiler.context.getEnvironment.isCreateThreadAllowed) {
if (compiler.context.isCreateThreadAllowed) {
pool.prestartAllCoreThreads()
}
@ -103,7 +96,7 @@ final class SerializationManager(
useGlobalCacheLocations: Boolean,
useThreadPool: Boolean = true
): Future[Boolean] = {
logger.log(
compiler.context.logSerializationManager(
debugLogLevel,
"Requesting serialization for module [{0}].",
module.getName
@ -133,7 +126,7 @@ final class SerializationManager(
CompletableFuture.completedFuture(task.call())
} catch {
case e: Throwable =>
logger.log(
compiler.context.logSerializationManager(
debugLogLevel,
s"Serialization task failed in module [${module.getName}].",
e
@ -147,7 +140,7 @@ final class SerializationManager(
libraryName: LibraryName,
useGlobalCacheLocations: Boolean
): Future[Boolean] = {
logger.log(
compiler.context.logSerializationManager(
Level.INFO,
"Requesting serialization for library [{0}].",
libraryName
@ -155,7 +148,7 @@ final class SerializationManager(
val task: Callable[Boolean] =
doSerializeLibrary(libraryName, useGlobalCacheLocations)
if (compiler.context.getEnvironment.isCreateThreadAllowed) {
if (compiler.context.isCreateThreadAllowed) {
isWaitingForSerialization.synchronized {
val future = pool.submit(task)
isWaitingForSerialization.put(libraryName.toQualifiedName, future)
@ -166,7 +159,7 @@ final class SerializationManager(
CompletableFuture.completedFuture(task.call())
} catch {
case e: Throwable =>
logger.log(
compiler.context.logSerializationManager(
debugLogLevel,
s"Serialization task failed for library [$libraryName].",
e
@ -184,7 +177,7 @@ final class SerializationManager(
Thread.sleep(100)
}
logger.log(
compiler.context.logSerializationManager(
debugLogLevel,
"Running serialization for bindings [{0}].",
libraryName
@ -213,19 +206,23 @@ final class SerializationManager(
try {
val result =
try {
new ImportExportCache(libraryName)
.save(bindingsCache, compiler.context, useGlobalCacheLocations)
.isPresent
val cache = new ImportExportCache(libraryName)
val file = compiler.context.saveCache(
cache,
bindingsCache,
useGlobalCacheLocations
)
file.isPresent
} catch {
case e: NotSerializableException =>
logger.log(
compiler.context.logSerializationManager(
Level.SEVERE,
s"Could not serialize bindings [$libraryName].",
e
)
throw e
case e: Throwable =>
logger.log(
compiler.context.logSerializationManager(
Level.SEVERE,
s"Serialization of bindings `$libraryName` failed: ${e.getMessage}`",
e
@ -275,19 +272,23 @@ final class SerializationManager(
.getPackageForLibraryJava(libraryName)
.map(_.listSourcesJava())
)
new SuggestionsCache(libraryName)
.save(cachedSuggestions, compiler.context, useGlobalCacheLocations)
.isPresent
val cache = new SuggestionsCache(libraryName)
val file = compiler.context.saveCache(
cache,
cachedSuggestions,
useGlobalCacheLocations
)
file.isPresent
} catch {
case e: NotSerializableException =>
logger.log(
compiler.context.logSerializationManager(
Level.SEVERE,
s"Could not serialize suggestions [$libraryName].",
e
)
throw e
case e: Throwable =>
logger.log(
compiler.context.logSerializationManager(
Level.SEVERE,
s"Serialization of suggestions `$libraryName` failed: ${e.getMessage}`",
e
@ -306,16 +307,17 @@ final class SerializationManager(
while (isSerializingLibrary(libraryName)) {
Thread.sleep(100)
}
new SuggestionsCache(libraryName).load(compiler.context).toScala match {
val cache = new SuggestionsCache(libraryName)
compiler.context.loadCache(cache).toScala match {
case result @ Some(_: SuggestionsCache.CachedSuggestions) =>
logger.log(
compiler.context.logSerializationManager(
Level.FINE,
"Restored suggestions for library [{0}].",
libraryName
)
result
case _ =>
logger.log(
compiler.context.logSerializationManager(
Level.FINEST,
"Unable to load suggestions for library [{0}].",
libraryName
@ -335,16 +337,17 @@ final class SerializationManager(
while (isSerializingLibrary(libraryName)) {
Thread.sleep(100)
}
new ImportExportCache(libraryName).load(compiler.context).toScala match {
val cache = new ImportExportCache(libraryName)
compiler.context.loadCache(cache).toScala match {
case result @ Some(_: ImportExportCache.CachedBindings) =>
logger.log(
compiler.context.logSerializationManager(
Level.FINE,
"Restored bindings for library [{0}].",
libraryName
)
result
case _ =>
logger.log(
compiler.context.logSerializationManager(
Level.FINEST,
"Unable to load bindings for library [{0}].",
libraryName
@ -376,41 +379,46 @@ final class SerializationManager(
Thread.sleep(100)
}
module.getCache.load(compiler.context).toScala match {
compiler.context.loadCache(module.getCache).toScala match {
case Some(loadedCache) =>
val relinkedIrChecks =
loadedCache
.moduleIR()
.preorder
.map(_.passData.restoreFromSerialization(this.compiler))
module.unsafeSetIr(loadedCache.moduleIR())
module.unsafeSetCompilationStage(loadedCache.compilationStage())
module.setLoadedFromCache(true)
logger.log(
compiler.context.updateModule(
module,
{ u =>
u.ir(loadedCache.moduleIR())
u.compilationStage(loadedCache.compilationStage())
u.loadedFromCache(true)
}
)
compiler.context.logSerializationManager(
debugLogLevel,
"Restored IR from cache for module [{0}] at stage [{1}].",
Array[Object](module.getName, loadedCache.compilationStage())
)
if (!relinkedIrChecks.contains(false)) {
module.setHasCrossModuleLinks(true)
logger.log(
compiler.context.updateModule(module, _.hasCrossModuleLinks(true))
compiler.context.logSerializationManager(
debugLogLevel,
"Restored links (early phase) in module [{0}].",
module.getName
)
Some(true)
} else {
logger.log(
compiler.context.logSerializationManager(
debugLogLevel,
"Could not restore links (early phase) in module [{0}].",
module.getName
)
module.setHasCrossModuleLinks(false)
compiler.context.updateModule(module, _.hasCrossModuleLinks(false))
Some(false)
}
case None =>
logger.log(
compiler.context.logSerializationManager(
debugLogLevel,
"Unable to load a cache for module [{0}].",
module.getName
@ -507,7 +515,7 @@ final class SerializationManager(
isWaitingForSerialization.size
}
val jobCount = waitingCount + isSerializing.size
logger.log(
compiler.context.logSerializationManager(
debugLogLevel,
"Waiting for #{0} serialization jobs to complete.",
jobCount
@ -534,7 +542,10 @@ final class SerializationManager(
pool.shutdownNow()
Thread.sleep(100)
logger.log(debugLogLevel, "Serialization manager has been shut down.")
compiler.context.logSerializationManager(
debugLogLevel,
"Serialization manager has been shut down."
)
}
}
@ -562,7 +573,7 @@ final class SerializationManager(
private def doSerializeModule(
cache: ModuleCache,
ir: IR.Module,
stage: Module.CompilationStage,
stage: CompilationStage,
name: QualifiedName,
source: Source,
useGlobalCacheLocations: Boolean
@ -571,7 +582,7 @@ final class SerializationManager(
Thread.sleep(100)
}
logger.log(
compiler.context.logSerializationManager(
debugLogLevel,
"Running serialization for module [{0}].",
name
@ -579,27 +590,27 @@ final class SerializationManager(
startSerializing(name)
try {
val fixedStage =
if (stage.isAtLeast(Module.CompilationStage.AFTER_STATIC_PASSES)) {
Module.CompilationStage.AFTER_STATIC_PASSES
if (stage.isAtLeast(CompilationStage.AFTER_STATIC_PASSES)) {
CompilationStage.AFTER_STATIC_PASSES
} else stage
cache
.save(
compiler.context
.saveCache(
cache,
new ModuleCache.CachedModule(ir, fixedStage, source),
compiler.context,
useGlobalCacheLocations
)
.map(_ => true)
.orElse(false)
} catch {
case e: NotSerializableException =>
logger.log(
compiler.context.logSerializationManager(
Level.SEVERE,
s"Could not serialize module [$name].",
e
)
throw e
case e: Throwable =>
logger.log(
compiler.context.logSerializationManager(
Level.SEVERE,
s"Serialization of module `$name` failed: ${e.getMessage}`",
e

View File

@ -56,7 +56,7 @@ case class BindingsMap(
override def restoreFromSerialization(
compiler: Compiler
): Option[BindingsMap] = {
val packageRepository = compiler.context.getPackageRepository
val packageRepository = compiler.getPackageRepository()
this.toConcrete(packageRepository.getModuleMap)
}
@ -992,7 +992,7 @@ object BindingsMap {
override def restoreFromSerialization(
compiler: Compiler
): Option[Resolution] = {
val moduleMap = compiler.context.getPackageRepository.getModuleMap
val moduleMap = compiler.getPackageRepository().getModuleMap
this.target.toConcrete(moduleMap).map(t => this.copy(target = t))
}

View File

@ -427,7 +427,7 @@ case object FullyQualifiedNames extends IRPass {
override def restoreFromSerialization(
compiler: Compiler
): Option[PartiallyResolvedFQN] = {
val packageRepository = compiler.context.getPackageRepository
val packageRepository = compiler.getPackageRepository()
moduleRef
.toConcrete(packageRepository.getModuleMap)
.map(ResolvedModule(_))

View File

@ -2,10 +2,14 @@ package org.enso.compiler.phase
import org.enso.compiler.core.EnsoParser
import org.enso.compiler.Passes
import org.enso.compiler.context.{FreshNameSupply, ModuleContext}
import org.enso.compiler.context.{
CompilerContext,
FreshNameSupply,
ModuleContext
}
import org.enso.compiler.data.CompilerConfig
import org.enso.interpreter.runtime.Module
import org.enso.interpreter.runtime.Module.CompilationStage
import org.enso.polyglot.CompilationStage
import scala.util.Using
/** A phase responsible for initializing the builtins' IR from the provided
@ -28,6 +32,7 @@ object BuiltinsIrBuilder {
* @param passes the compiler's pass manager
*/
def build(
context: CompilerContext,
module: Module,
freshNameSupply: FreshNameSupply,
passes: Passes
@ -46,8 +51,13 @@ object BuiltinsIrBuilder {
moduleContext,
passes.moduleDiscoveryPasses
)
module.unsafeSetIr(irAfterModDiscovery)
module.unsafeSetCompilationStage(Module.CompilationStage.AFTER_PARSING)
context.updateModule(
module,
{ u =>
u.ir(irAfterModDiscovery)
u.compilationStage(CompilationStage.AFTER_PARSING)
}
)
new ExportsResolution().run(List(module))
val irAfterTypes = passManager.runPassesOnModule(
@ -60,7 +70,12 @@ object BuiltinsIrBuilder {
moduleContext,
passes.functionBodyPasses
)
module.unsafeSetIr(irAfterCompilation)
module.unsafeSetCompilationStage(CompilationStage.AFTER_CODEGEN)
context.updateModule(
module,
{ u =>
u.ir(irAfterCompilation)
u.compilationStage(CompilationStage.AFTER_CODEGEN)
}
)
}
}

View File

@ -14,7 +14,7 @@ import org.enso.compiler.core.CompilerError
import org.enso.compiler.pass.analyse.BindingAnalysis
import org.enso.editions.LibraryName
import org.enso.interpreter.runtime.Module
import org.enso.polyglot.CompilationStage
import scala.collection.mutable
/** Runs imports resolution. Starts from a given module and then recursively
@ -23,7 +23,7 @@ import scala.collection.mutable
* Each of the reachable modules will be parsed and will have imported modules
* injected into its metadata. In effect, running this will bring every module
* that could ever be necessary for the entry point compilation to at least
* the [[Module.CompilationStage.AFTER_IMPORT_RESOLUTION]] stage.
* the [[CompilationStage.AFTER_IMPORT_RESOLUTION]] stage.
*
* @param compiler the compiler instance for the compiling context.
*/
@ -42,16 +42,18 @@ class ImportResolver(compiler: Compiler) {
): (List[Module], List[Module]) = {
def analyzeModule(current: Module): List[Module] = {
val ir = current.getIr
val context = compiler.context
val ir = context.getIr(current)
val currentLocal = ir.unsafeGetMetadata(
BindingAnalysis,
"Non-parsed module used in ImportResolver"
)
// put the list of resolved imports in the module metadata
if (
current.getCompilationStage
context
.getCompilationStage(current)
.isBefore(
Module.CompilationStage.AFTER_IMPORT_RESOLUTION
CompilationStage.AFTER_IMPORT_RESOLUTION
) || !current.hasCrossModuleLinks
) {
val importedModules: List[
@ -64,12 +66,17 @@ class ImportResolver(compiler: Compiler) {
}
currentLocal.resolvedImports = importedModules.flatMap(_._2)
val newIr = ir.copy(imports = importedModules.map(_._1))
current.unsafeSetIr(newIr)
if (!current.wasLoadedFromCache()) {
current.unsafeSetCompilationStage(
Module.CompilationStage.AFTER_IMPORT_RESOLUTION
)
}
context.updateModule(
current,
{ u =>
u.ir(newIr)
if (!context.wasLoadedFromCache(current)) {
u.compilationStage(
CompilationStage.AFTER_IMPORT_RESOLUTION
)
}
}
)
}
currentLocal.resolvedImports
.map(_.target.module.unsafeAsModule())

View File

@ -55,7 +55,7 @@ public class SerializerTest {
var result = compiler.run(module);
assertEquals(result.compiledModules().exists(m -> m == module), true);
var serializationManager = new SerializationManager(ensoContext.getCompiler());
var useThreadPool = compiler.context().getEnvironment().isCreateThreadAllowed();
var useThreadPool = compiler.context().isCreateThreadAllowed();
var future = serializationManager.serializeModule(module, true, useThreadPool);
var serialized = future.get(5, TimeUnit.SECONDS);
assertEquals(serialized, true);

View File

@ -0,0 +1,16 @@
package org.enso.interpreter.runtime;
import org.enso.compiler.core.IR;
import org.enso.polyglot.CompilationStage;
public final class ModuleTestUtils {
private ModuleTestUtils() {}
public static void unsafeSetIr(Module m, IR.Module ir) {
m.unsafeSetIr(ir);
}
public static void unsafeSetCompilationStage(Module m, CompilationStage s) {
m.unsafeSetCompilationStage(s);
}
}

View File

@ -11,8 +11,10 @@ import org.enso.compiler.pass.{PassConfiguration, PassManager}
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpecLike
import org.enso.interpreter.runtime.Module
import org.enso.interpreter.runtime.ModuleTestUtils
import org.enso.interpreter.runtime.scope.LocalScope
import org.enso.pkg.QualifiedName
import org.enso.polyglot.CompilationStage
trait CompilerTest extends AnyWordSpecLike with Matchers with CompilerRunner
trait CompilerRunner {
@ -227,7 +229,8 @@ trait CompilerRunner {
compilerConfig: CompilerConfig = defaultConfig
): InlineContext = {
val mod = Module.empty(QualifiedName.simpleName("Test_Module"), null)
mod.unsafeSetIr(
ModuleTestUtils.unsafeSetIr(
mod,
IR.Module(List(), List(), List(), None)
.updateMetadata(
BindingAnalysis -->> BindingsMap(
@ -236,7 +239,10 @@ trait CompilerRunner {
)
)
)
mod.unsafeSetCompilationStage(Module.CompilationStage.AFTER_CODEGEN)
ModuleTestUtils.unsafeSetCompilationStage(
mod,
CompilationStage.AFTER_CODEGEN
)
InlineContext(
module = mod,
freshNameSupply = freshNameSupply,

View File

@ -14,6 +14,7 @@ import org.enso.compiler.pass.resolve.GlobalNames
import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager}
import org.enso.compiler.phase.ExportsResolution
import org.enso.compiler.test.CompilerTest
import org.enso.interpreter.runtime.ModuleTestUtils
class GlobalNamesTest extends CompilerTest {
@ -81,7 +82,7 @@ class GlobalNamesTest extends CompilerTest {
|""".stripMargin
val parsed = code.toIrModule
val moduleMapped = passManager.runPassesOnModule(parsed, ctx, group1)
ctx.module.unsafeSetIr(moduleMapped)
ModuleTestUtils.unsafeSetIr(ctx.module, moduleMapped)
new ExportsResolution().run(List(ctx.module))
val allPrecursors = passManager.runPassesOnModule(moduleMapped, ctx, group2)