mirror of
https://github.com/enso-org/enso.git
synced 2024-11-26 08:52:58 +03:00
More robust work with caches (#8393)
This commit is contained in:
parent
dd28517d9e
commit
c889c8e83f
@ -18,6 +18,7 @@ import org.enso.compiler.core.ir.{
|
|||||||
Warning,
|
Warning,
|
||||||
Module => IRModule
|
Module => IRModule
|
||||||
}
|
}
|
||||||
|
import org.enso.compiler.core.ir.MetadataStorage.MetadataPair
|
||||||
import org.enso.compiler.core.ir.expression.Error
|
import org.enso.compiler.core.ir.expression.Error
|
||||||
import org.enso.compiler.core.ir.module.scope.Export
|
import org.enso.compiler.core.ir.module.scope.Export
|
||||||
import org.enso.compiler.core.ir.module.scope.Import
|
import org.enso.compiler.core.ir.module.scope.Import
|
||||||
@ -587,9 +588,17 @@ class Compiler(
|
|||||||
injectSyntheticModuleExports(expr, module.getDirectModulesRefs)
|
injectSyntheticModuleExports(expr, module.getDirectModulesRefs)
|
||||||
val discoveredModule =
|
val discoveredModule =
|
||||||
recognizeBindings(exprWithModuleExports, moduleContext)
|
recognizeBindings(exprWithModuleExports, moduleContext)
|
||||||
|
if (context.wasLoadedFromCache(module)) {
|
||||||
|
if (module.getBindingsMap() != null) {
|
||||||
|
discoveredModule.passData.update(
|
||||||
|
new MetadataPair(BindingAnalysis, module.getBindingsMap())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
context.updateModule(
|
context.updateModule(
|
||||||
module,
|
module,
|
||||||
{ u =>
|
{ u =>
|
||||||
|
u.bindingsMap(null);
|
||||||
u.ir(discoveredModule)
|
u.ir(discoveredModule)
|
||||||
u.compilationStage(CompilationStage.AFTER_PARSING)
|
u.compilationStage(CompilationStage.AFTER_PARSING)
|
||||||
u.loadedFromCache(false)
|
u.loadedFromCache(false)
|
||||||
|
@ -61,6 +61,10 @@ import scala.collection.immutable.Seq;
|
|||||||
@Persistable(clazz = Name.BuiltinAnnotation.class, id = 783)
|
@Persistable(clazz = Name.BuiltinAnnotation.class, id = 783)
|
||||||
@Persistable(clazz = Type.Error.class, id = 784)
|
@Persistable(clazz = Type.Error.class, id = 784)
|
||||||
@Persistable(clazz = Unused.Binding.class, id = 785)
|
@Persistable(clazz = Unused.Binding.class, id = 785)
|
||||||
|
@Persistable(clazz = Unused.PatternBinding.class, id = 786)
|
||||||
|
@Persistable(clazz = Unused.FunctionArgument.class, id = 787)
|
||||||
|
@Persistable(clazz = Warning.DuplicatedImport.class, id = 788)
|
||||||
|
@Persistable(clazz = Warning.WrongBuiltinMethod.class, id = 789)
|
||||||
public final class IrPersistance {
|
public final class IrPersistance {
|
||||||
private IrPersistance() {}
|
private IrPersistance() {}
|
||||||
|
|
||||||
@ -389,23 +393,15 @@ public final class IrPersistance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void writeObject(DiagnosticStorage obj, Output out) throws IOException {}
|
protected void writeObject(DiagnosticStorage obj, Output out) throws IOException {
|
||||||
|
out.writeInline(List.class, obj.toList());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected DiagnosticStorage readObject(Input in) throws IOException, ClassNotFoundException {
|
protected DiagnosticStorage readObject(Input in) throws IOException, ClassNotFoundException {
|
||||||
return new DiagnosticStorage(
|
var diags = in.readInline(List.class);
|
||||||
(scala.collection.immutable.List) scala.collection.immutable.Nil$.MODULE$);
|
return new DiagnosticStorage(diags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T> scala.collection.immutable.List<T> join(
|
|
||||||
T head, scala.collection.immutable.List<T> tail) {
|
|
||||||
return scala.collection.immutable.$colon$colon$.MODULE$.apply(head, tail);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private static <E extends Throwable> E raise(Class<E> clazz, Throwable t) throws E {
|
|
||||||
throw (E) t;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -276,7 +276,7 @@ final class TruffleCompilerContext implements CompilerContext {
|
|||||||
|
|
||||||
private final class ModuleUpdater implements Updater, AutoCloseable {
|
private final class ModuleUpdater implements Updater, AutoCloseable {
|
||||||
private final Module module;
|
private final Module module;
|
||||||
private BindingsMap map;
|
private BindingsMap[] map;
|
||||||
private org.enso.compiler.core.ir.Module[] ir;
|
private org.enso.compiler.core.ir.Module[] ir;
|
||||||
private CompilationStage stage;
|
private CompilationStage stage;
|
||||||
private Boolean loadedFromCache;
|
private Boolean loadedFromCache;
|
||||||
@ -289,7 +289,7 @@ final class TruffleCompilerContext implements CompilerContext {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void bindingsMap(BindingsMap map) {
|
public void bindingsMap(BindingsMap map) {
|
||||||
this.map = map;
|
this.map = new BindingsMap[] { map };
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -320,10 +320,10 @@ final class TruffleCompilerContext implements CompilerContext {
|
|||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
if (map != null) {
|
if (map != null) {
|
||||||
if (module.bindings != null) {
|
if (module.bindings != null && map[0] != null) {
|
||||||
loggerCompiler.log(Level.FINEST, "Reassigining bindings to {0}", module);
|
loggerCompiler.log(Level.FINEST, "Reassigining bindings to {0}", module);
|
||||||
}
|
}
|
||||||
module.bindings = map;
|
module.bindings = map[0];
|
||||||
}
|
}
|
||||||
if (ir != null) {
|
if (ir != null) {
|
||||||
module.module.unsafeSetIr(ir[0]);
|
module.module.unsafeSetIr(ir[0]);
|
||||||
|
@ -102,7 +102,7 @@ private class DefaultPackageRepository(
|
|||||||
/** The mapping between the library and its cached bindings, if already laoded. */
|
/** The mapping between the library and its cached bindings, if already laoded. */
|
||||||
private val loadedLibraryBindings: collection.mutable.Map[
|
private val loadedLibraryBindings: collection.mutable.Map[
|
||||||
LibraryName,
|
LibraryName,
|
||||||
ImportExportCache.CachedBindings
|
Option[ImportExportCache.CachedBindings]
|
||||||
] =
|
] =
|
||||||
collection.mutable.LinkedHashMap()
|
collection.mutable.LinkedHashMap()
|
||||||
|
|
||||||
@ -578,15 +578,15 @@ private class DefaultPackageRepository(
|
|||||||
val cache = ensurePackageIsLoaded(libraryName).toOption.flatMap { _ =>
|
val cache = ensurePackageIsLoaded(libraryName).toOption.flatMap { _ =>
|
||||||
if (!loadedLibraryBindings.contains(libraryName)) {
|
if (!loadedLibraryBindings.contains(libraryName)) {
|
||||||
loadedPackages.get(libraryName).flatten.foreach(loadDependencies(_))
|
loadedPackages.get(libraryName).flatten.foreach(loadDependencies(_))
|
||||||
context
|
val cachedBindingOption = context
|
||||||
.asInstanceOf[TruffleCompilerContext]
|
.asInstanceOf[TruffleCompilerContext]
|
||||||
.getSerializationManager()
|
.getSerializationManager()
|
||||||
.deserializeLibraryBindings(libraryName)
|
.deserializeLibraryBindings(libraryName)
|
||||||
.foreach(cache => loadedLibraryBindings.addOne((libraryName, cache)))
|
loadedLibraryBindings.addOne((libraryName, cachedBindingOption))
|
||||||
}
|
}
|
||||||
loadedLibraryBindings.get(libraryName)
|
loadedLibraryBindings.get(libraryName)
|
||||||
}
|
}
|
||||||
cache.flatMap(_.bindings.findForModule(moduleName))
|
cache.flatMap(_.flatMap(_.bindings.findForModule(moduleName)))
|
||||||
}
|
}
|
||||||
|
|
||||||
private def loadDependencies(pkg: Package[TruffleFile]): Unit = {
|
private def loadDependencies(pkg: Package[TruffleFile]): Unit = {
|
||||||
|
@ -1,22 +1,19 @@
|
|||||||
package org.enso.interpreter.caches;
|
package org.enso.interpreter.caches;
|
||||||
|
|
||||||
import org.enso.compiler.CompilerTest;
|
import org.enso.compiler.CompilerTest;
|
||||||
import org.enso.compiler.core.IR;
|
|
||||||
import org.enso.interpreter.Constants;
|
|
||||||
import org.enso.interpreter.runtime.EnsoContext;
|
import org.enso.interpreter.runtime.EnsoContext;
|
||||||
import org.enso.interpreter.runtime.builtin.Builtins;
|
|
||||||
import org.enso.interpreter.test.TestBase;
|
import org.enso.interpreter.test.TestBase;
|
||||||
import org.enso.interpreter.util.ScalaConversions;
|
|
||||||
import org.enso.polyglot.CompilationStage;
|
import org.enso.polyglot.CompilationStage;
|
||||||
import org.enso.polyglot.LanguageInfo;
|
import org.enso.polyglot.LanguageInfo;
|
||||||
import org.enso.polyglot.MethodNames;
|
import org.enso.polyglot.MethodNames;
|
||||||
import org.enso.polyglot.RuntimeOptions;
|
import org.enso.polyglot.RuntimeOptions;
|
||||||
import org.graalvm.polyglot.Context;
|
import org.graalvm.polyglot.Context;
|
||||||
import org.junit.Test;
|
import org.graalvm.polyglot.Source;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
public class ModuleCacheTest extends TestBase {
|
public class ModuleCacheTest extends TestBase {
|
||||||
private static Context ctx;
|
private static Context ctx;
|
||||||
@ -55,4 +52,30 @@ public class ModuleCacheTest extends TestBase {
|
|||||||
assertNotNull("IR read", cachedIr);
|
assertNotNull("IR read", cachedIr);
|
||||||
CompilerTest.assertIR(name, ir, cachedIr.moduleIR());
|
CompilerTest.assertIR(name, ir, cachedIr.moduleIR());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCompareWithWarning() throws Exception {
|
||||||
|
var ensoCtx = (EnsoContext) ctx.getBindings(LanguageInfo.ID).invokeMember(MethodNames.TopScope.LEAK_CONTEXT).asHostObject();
|
||||||
|
var name = "TestWarning";
|
||||||
|
var code = Source.newBuilder("enso", """
|
||||||
|
empty x = 42
|
||||||
|
""", "TestWarning.enso")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
var v = ctx.eval(code).invokeMember(MethodNames.Module.EVAL_EXPRESSION, "empty").execute(-1);
|
||||||
|
assertEquals(42, v.asInt());
|
||||||
|
|
||||||
|
var option = ensoCtx.findModule(name);
|
||||||
|
assertTrue("Module found", option.isPresent());
|
||||||
|
var module = option.get();
|
||||||
|
var ir = module.getIr().duplicate(true, true, true, true);
|
||||||
|
var cm = new ModuleCache.CachedModule(ir, CompilationStage.AFTER_CODEGEN, module.getSource());
|
||||||
|
byte[] arr = module.getCache().serialize(ensoCtx, cm);
|
||||||
|
|
||||||
|
var meta = new ModuleCache.Metadata("hash", "code", CompilationStage.AFTER_CODEGEN.toString());
|
||||||
|
var cachedIr = module.getCache().deserialize(ensoCtx, arr, meta, null);
|
||||||
|
assertNotNull("IR read", cachedIr);
|
||||||
|
CompilerTest.assertIR(name, ir, cachedIr.moduleIR());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,31 @@
|
|||||||
package org.enso.interpreter.runtime;
|
package org.enso.interpreter.runtime;
|
||||||
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import org.enso.compiler.data.BindingsMap;
|
||||||
|
import org.enso.compiler.data.BindingsMap$ModuleReference$Concrete;
|
||||||
|
import org.enso.interpreter.runtime.Module;
|
||||||
|
import static org.enso.interpreter.util.ScalaConversions.nil;
|
||||||
import org.enso.pkg.QualifiedName;
|
import org.enso.pkg.QualifiedName;
|
||||||
import org.enso.polyglot.LanguageInfo;
|
import org.enso.polyglot.LanguageInfo;
|
||||||
import org.enso.polyglot.MethodNames;
|
import org.enso.polyglot.MethodNames;
|
||||||
import org.enso.polyglot.RuntimeOptions;
|
import org.enso.polyglot.RuntimeOptions;
|
||||||
import org.graalvm.polyglot.Context;
|
import org.graalvm.polyglot.Context;
|
||||||
import org.graalvm.polyglot.Engine;
|
import org.graalvm.polyglot.Engine;
|
||||||
|
import org.graalvm.polyglot.Source;
|
||||||
import org.graalvm.polyglot.io.IOAccess;
|
import org.graalvm.polyglot.io.IOAccess;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import scala.Option;
|
||||||
|
|
||||||
public class ModuleTest {
|
public class ModuleTest {
|
||||||
|
|
||||||
private File f;
|
private File f;
|
||||||
@ -60,4 +69,70 @@ public class ModuleTest {
|
|||||||
assertTrue(
|
assertTrue(
|
||||||
"getPath is non-null", tFile.getPath() != null && module.getPath() == tFile.getPath());
|
"getPath is non-null", tFile.getPath() != null && module.getPath() == tFile.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void updaterCanNullTheBindings() throws Exception {
|
||||||
|
var name = QualifiedName.simpleName("SimpleExample");
|
||||||
|
var ensoContext =
|
||||||
|
(EnsoContext)
|
||||||
|
ctx.getBindings(LanguageInfo.ID)
|
||||||
|
.invokeMember(MethodNames.TopScope.LEAK_CONTEXT)
|
||||||
|
.asHostObject();
|
||||||
|
var tFile = ensoContext.getTruffleFile(f);
|
||||||
|
|
||||||
|
var code = Source.newBuilder("enso", """
|
||||||
|
main = 42
|
||||||
|
""", name.toString()).build();
|
||||||
|
|
||||||
|
ctx.eval(code);
|
||||||
|
var module = ensoContext.getTopScope().getModule(name.toString()).get().asCompilerModule();
|
||||||
|
ctx.enter();
|
||||||
|
var compilerContext = ensoContext.getCompiler().context();
|
||||||
|
|
||||||
|
assertNull("No bindings map by default", module.getBindingsMap());
|
||||||
|
|
||||||
|
var bindings = new BindingsMap(nil(), new BindingsMap$ModuleReference$Concrete(module));
|
||||||
|
compilerContext.updateModule(module, (u) -> {
|
||||||
|
u.bindingsMap(bindings);
|
||||||
|
});
|
||||||
|
assertEquals("Bindings map has changed", bindings, module.getBindingsMap());
|
||||||
|
|
||||||
|
compilerContext.updateModule(module, (u) -> {
|
||||||
|
u.bindingsMap(null);
|
||||||
|
});
|
||||||
|
assertNull("No bindings map again", module.getBindingsMap());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void updaterCanNullTheIR() throws Exception {
|
||||||
|
var name = QualifiedName.simpleName("AnotherSimpleExample");
|
||||||
|
var ensoContext =
|
||||||
|
(EnsoContext)
|
||||||
|
ctx.getBindings(LanguageInfo.ID)
|
||||||
|
.invokeMember(MethodNames.TopScope.LEAK_CONTEXT)
|
||||||
|
.asHostObject();
|
||||||
|
var tFile = ensoContext.getTruffleFile(f);
|
||||||
|
|
||||||
|
var code = Source.newBuilder("enso", """
|
||||||
|
main = 42
|
||||||
|
""", name.toString()).build();
|
||||||
|
|
||||||
|
ctx.eval(code);
|
||||||
|
var module = ensoContext.getTopScope().getModule(name.toString()).get().asCompilerModule();
|
||||||
|
ctx.enter();
|
||||||
|
var compilerContext = ensoContext.getCompiler().context();
|
||||||
|
|
||||||
|
assertNull("No IR by default", module.getIr());
|
||||||
|
|
||||||
|
var ir = new org.enso.compiler.core.ir.Module(nil(), nil(), nil(), false, Option.empty(), null, null);
|
||||||
|
compilerContext.updateModule(module, (u) -> {
|
||||||
|
u.ir(ir);
|
||||||
|
});
|
||||||
|
assertEquals("IR has changed", ir, module.getIr());
|
||||||
|
|
||||||
|
compilerContext.updateModule(module, (u) -> {
|
||||||
|
u.ir(null);
|
||||||
|
});
|
||||||
|
assertNull("No IR again", module.getIr());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user