Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Store whole IR.Module in .bindings cache #8924

Merged
merged 42 commits into from
Feb 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
6803429
Store whole IR.Module in .bindings cache
JaroslavTulach Feb 1, 2024
20416bf
Shield against NPE
JaroslavTulach Feb 1, 2024
3331219
Nicer formatting
JaroslavTulach Feb 1, 2024
8dfcac9
Using ByteBuffer instead of byte[] in caches
JaroslavTulach Feb 1, 2024
05858a6
Let Persistace.read accept ByteBuffer
JaroslavTulach Feb 1, 2024
7be0865
Reading the cache in as MappedByteBuffer
JaroslavTulach Feb 1, 2024
ba07db8
Clarity: Splitting Cache API and SPI into separate classes
JaroslavTulach Feb 2, 2024
6a10a20
Single throws ClassNotFoundException is enough
JaroslavTulach Feb 2, 2024
b7fd968
Replace writable Cache fields with methods in Spi
JaroslavTulach Feb 2, 2024
e570e37
Cache is a final class
JaroslavTulach Feb 2, 2024
667260c
No need for special Impl inner classes
JaroslavTulach Feb 2, 2024
22ac510
No need for Cache.Metadata interface
JaroslavTulach Feb 2, 2024
c40bc2f
Eliminate one need for SerializationManager.apply
JaroslavTulach Feb 2, 2024
09abdc0
Less calls to serializationManager.deserialize
JaroslavTulach Feb 2, 2024
300972d
Introducing SerializationPool to deal with threading of Serialization…
JaroslavTulach Feb 3, 2024
0f53896
Let SerializationPool use QualifiedName as key
JaroslavTulach Feb 3, 2024
bb1272d
Removing Thread.sleep from Serialization manager code
JaroslavTulach Feb 3, 2024
570cfcd
Moving implementation of serializeModule to TruffleCompilerContext
JaroslavTulach Feb 3, 2024
fdfa387
Moving serializeLibrary into TruffleCompilerContext
JaroslavTulach Feb 3, 2024
9efb654
Moving doSerializeModule into TruffleCompilerContext
JaroslavTulach Feb 3, 2024
3d3b453
deserializeModule moved to TruffleCompilerContext
JaroslavTulach Feb 3, 2024
a960069
Rewriting doSerializeLibrary & co. to Java
JaroslavTulach Feb 3, 2024
4b75e45
Removing remaining methods from SerializationManager.scala
JaroslavTulach Feb 3, 2024
f9982cf
Removing SerializationManager
JaroslavTulach Feb 3, 2024
47c28da
Adjusting tests to removed SerializationManager
JaroslavTulach Feb 4, 2024
d663e06
Use asSpi to extract cache implementation in tests
JaroslavTulach Feb 4, 2024
44471d2
Merging with DiagnosticFormatter
JaroslavTulach Feb 4, 2024
a471e6a
Only log when Standard library IR file is loaded
JaroslavTulach Feb 4, 2024
8b26678
Thread.join to ensure threads are gone
JaroslavTulach Feb 4, 2024
ba32efb
Thread.join all threads before closing the context
JaroslavTulach Feb 4, 2024
5a99f95
SuggestionsCache needs InputStream over buffer
JaroslavTulach Feb 4, 2024
58b5078
Compose the results
JaroslavTulach Feb 4, 2024
77b1369
Merge branch 'develop' into wip/jtulach/CachePerLibrary_8639
mergify[bot] Feb 4, 2024
1577744
Use underscore
JaroslavTulach Feb 6, 2024
c729c74
There is no library name anymore as deserializeSuggestions method cha…
JaroslavTulach Feb 6, 2024
947824e
When recovering from deserialization IOException, don't useCaches whe…
JaroslavTulach Feb 6, 2024
c061494
Only mmap files larget than 3MB - e.g. mostly .bindings files
JaroslavTulach Feb 7, 2024
bbd6d99
Don't generate .ir files when compiling a library. They are stored in…
JaroslavTulach Feb 7, 2024
76f47a7
Make sure the stacktrace isn't lost
JaroslavTulach Feb 7, 2024
11776a6
Compute suggestions first before (possibly) overriding .bindings file
JaroslavTulach Feb 7, 2024
5a4bfa9
Improving javadoc & co.
JaroslavTulach Feb 8, 2024
a2b2945
Avoid using caches when reparsing
JaroslavTulach Feb 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,13 @@ Future<Boolean> serializeLibrary(
Compiler compiler, LibraryName libraryName, boolean useGlobalCacheLocations);

Future<Boolean> serializeModule(
Compiler compiler, Module module, boolean useGlobalCacheLocations);
Compiler compiler, Module module, boolean useGlobalCacheLocations, boolean usePool);

boolean deserializeModule(Compiler compiler, Module module);

scala.Option<List<org.enso.polyglot.Suggestion>> deserializeSuggestions(LibraryName libraryName)
throws InterruptedException;

void shutdown(boolean waitForPendingJobCompletion);

public static interface Updater {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ 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.imports
import org.enso.compiler.core.EnsoParser
import org.enso.compiler.data.{BindingsMap, CompilerConfig}
import org.enso.compiler.data.CompilerConfig
import org.enso.compiler.exception.CompilationAbortedException
import org.enso.compiler.pass.PassManager
import org.enso.compiler.pass.analyse._
Expand Down Expand Up @@ -200,7 +200,11 @@ class Compiler(
*/
def generateDocs(module: Module): Module = {
initialize()
parseModule(module, isGenDocs = true)
parseModule(
module,
irCachingEnabled && !context.isInteractive(module),
isGenDocs = true
)
module
}

Expand Down Expand Up @@ -244,7 +248,7 @@ class Compiler(
initialize()
modules.foreach(m =>
try {
parseModule(m)
parseModule(m, irCachingEnabled && !context.isInteractive(m))
} catch {
case e: Throwable =>
context.log(
Expand Down Expand Up @@ -286,12 +290,12 @@ class Compiler(
)
)
context.updateModule(module, _.invalidateCache())
parseModule(module)
parseModule(module, irCachingEnabled && !context.isInteractive(module))
importedModules
.filter(isLoadedFromSource)
.map(m => {
if (m.getBindingsMap() == null) {
parseModule(m)
parseModule(m, irCachingEnabled && !context.isInteractive(module))
}
})
runImportsAndExportsResolution(module, generateCode)
Expand All @@ -302,7 +306,7 @@ class Compiler(

if (irCachingEnabled) {
requiredModules.foreach { module =>
ensureParsed(module)
ensureParsed(module, !context.isInteractive(module))
}
}
requiredModules.foreach { module =>
Expand Down Expand Up @@ -404,6 +408,7 @@ class Compiler(

if (shouldCompileDependencies || isModuleInRootPackage(module)) {
val shouldStoreCache =
generateCode &&
irCachingEnabled && !context.wasLoadedFromCache(module)
if (
shouldStoreCache && !hasErrors(module) &&
Expand All @@ -415,7 +420,8 @@ class Compiler(
context.serializeModule(
this,
module,
useGlobalCacheLocations
useGlobalCacheLocations,
true
)
}
}
Expand Down Expand Up @@ -481,7 +487,7 @@ class Compiler(

private def ensureParsedAndAnalyzed(module: Module): Unit = {
if (module.getBindingsMap() == null) {
ensureParsed(module)
ensureParsed(module, irCachingEnabled && !context.isInteractive(module))
}
if (context.isSynthetic(module)) {
// Synthetic modules need to be import-analyzed
Expand All @@ -490,19 +496,10 @@ class Compiler(
// TODO: consider generating IR for synthetic modules, if possible.
importExportBindings(module) match {
case Some(bindings) =>
val converted = bindings
.toConcrete(packageRepository.getModuleMap)
.map { concreteBindings =>
concreteBindings
}
ensureParsed(module)
val currentLocal = module.getBindingsMap()
currentLocal.resolvedImports =
converted.map(_.resolvedImports).getOrElse(Nil)
currentLocal.resolvedExports =
converted.map(_.resolvedExports).getOrElse(Nil)
currentLocal.exportedSymbols =
converted.map(_.exportedSymbols).getOrElse(Map.empty)
context.updateModule(
module,
_.ir(bindings)
)
case _ =>
}
}
Expand All @@ -520,7 +517,7 @@ class Compiler(
* @param module - the scope from which docs are generated.
*/
def gatherImportStatements(module: Module): Array[String] = {
ensureParsed(module)
ensureParsed(module, irCachingEnabled && !context.isInteractive(module))
val importedModules = context.getIr(module).imports.flatMap {
case imp: Import.Module =>
imp.name.parts.take(2).map(_.name) match {
Expand All @@ -543,6 +540,7 @@ class Compiler(

private def parseModule(
module: Module,
useCaches: Boolean,
isGenDocs: Boolean = false
): Unit = {
context.log(
Expand All @@ -552,7 +550,7 @@ class Compiler(
)
context.updateModule(module, _.resetScope())

if (irCachingEnabled && !context.isInteractive(module)) {
if (useCaches) {
if (context.deserializeModule(this, module)) {
return
}
Expand All @@ -566,7 +564,7 @@ class Compiler(
* @param module module which is conssidered
* @return module's bindings, if available in libraries' bindings cache
*/
def importExportBindings(module: Module): Option[BindingsMap] = {
def importExportBindings(module: Module): Option[IRModule] = {
if (irCachingEnabled && !context.isInteractive(module)) {
val libraryName = Option(module.getPackage).map(_.libraryName)
libraryName.flatMap(
Expand Down Expand Up @@ -646,14 +644,19 @@ class Compiler(
* @param module the module to ensure is parsed.
*/
def ensureParsed(module: Module): Unit = {
val useCaches = irCachingEnabled && !context.isInteractive(module)
ensureParsed(module, useCaches)
}

def ensureParsed(module: Module, useCaches: Boolean): Unit = {
if (
!context
.getCompilationStage(module)
.isAtLeast(
CompilationStage.AFTER_PARSING
)
) {
parseModule(module)
parseModule(module, useCaches)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package org.enso.compiler
import com.oracle.truffle.api.TruffleFile
import org.enso.editions.LibraryName
import org.enso.compiler.context.CompilerContext
import org.enso.compiler.data.BindingsMap
import org.enso.compiler.core.ir.{Module => IRModule}
import org.enso.pkg.{ComponentGroups, Package, QualifiedName}

import scala.collection.immutable.ListSet
Expand Down Expand Up @@ -113,7 +113,7 @@ trait PackageRepository {
libraryName: LibraryName,
moduleName: QualifiedName,
context: CompilerContext
): Option[BindingsMap]
): Option[IRModule]

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class ImportResolver(compiler: Compiler) {
u.invalidateCache()
}
)
compiler.ensureParsed(current)
compiler.ensureParsed(current, false)
return analyzeModule(current)
}
// put the list of resolved imports in the module metadata
Expand Down Expand Up @@ -123,18 +123,14 @@ class ImportResolver(compiler: Compiler) {
// - no - ensure they are parsed (load them from cache) and add them to the import/export resolution
compiler.importExportBindings(current) match {
case Some(bindings) =>
val converted = bindings
.toConcrete(compiler.packageRepository.getModuleMap)
.map { concreteBindings =>
compiler.context.updateModule(
current,
{ u =>
u.bindingsMap(concreteBindings)
u.loadedFromCache(true)
}
)
concreteBindings
compiler.context.updateModule(
current,
u => {
u.ir(bindings)
u.loadedFromCache(true)
}
)
val converted = Option(current.getBindingsMap())
(
converted
.map(
Expand Down Expand Up @@ -183,7 +179,7 @@ class ImportResolver(compiler: Compiler) {
u.compilationStage(CompilationStage.INITIAL)
}
)
compiler.ensureParsed(mod)
compiler.ensureParsed(mod, false)
Copy link
Member Author

Choose a reason for hiding this comment

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

Don't use caches to avoid this NPE.

b = mod.getBindingsMap()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import java.util.logging.Level;
import org.enso.interpreter.instrument.execution.RuntimeContext;
import org.enso.interpreter.runtime.SerializationManager;
import org.enso.pkg.QualifiedName;
import org.enso.polyglot.CompilationStage;

Expand All @@ -22,7 +21,6 @@ public SerializeModuleJob(QualifiedName moduleName) {
public Void run(RuntimeContext ctx) {
var ensoContext = ctx.executionService().getContext();
var compiler = ensoContext.getCompiler();
SerializationManager serializationManager = SerializationManager.apply(compiler.context());
boolean useGlobalCacheLocations = ensoContext.isUseGlobalCache();
var writeLockTimestamp = ctx.locking().acquireWriteCompilationLock();
try {
Expand All @@ -40,9 +38,10 @@ public Void run(RuntimeContext ctx) {
new Object[] {module.getName(), module.getCompilationStage()});
return;
}

serializationManager.serializeModule(
compiler, module.asCompilerModule(), useGlobalCacheLocations, false);
compiler
.context()
.serializeModule(
compiler, module.asCompilerModule(), useGlobalCacheLocations, false);
});
} finally {
ctx.locking().releaseWriteCompilationLock();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.enso.interpreter.instrument.job

import org.enso.editions.LibraryName
import org.enso.interpreter.runtime.SerializationManager
import org.enso.interpreter.instrument.execution.RuntimeContext
import org.enso.polyglot.runtime.Runtime.Api

Expand Down Expand Up @@ -33,17 +32,14 @@ final class DeserializeLibrarySuggestionsJob(
"Deserializing suggestions for library [{}].",
libraryName
)
val serializationManager = SerializationManager(
ctx.executionService.getContext.getCompiler.context
)
serializationManager
ctx.executionService.getContext.getCompiler.context
.deserializeSuggestions(libraryName)
.foreach { cachedSuggestions =>
ctx.endpoint.sendToClient(
Api.Response(
Api.SuggestionsDatabaseSuggestionsLoadedNotification(
libraryName,
cachedSuggestions.getSuggestions.asScala.toVector
cachedSuggestions.asScala.toVector
)
)
)
Expand Down
Loading
Loading