Move caching to after all configuration refinements and ...
move compilation cache setting to the scripting host configuration The cache implementation can now take into account all external dependencies that may appear during refinement. Also change initial refinement location accordingly and rearrange caching interfaces to make it available in scripting plugin.
This commit is contained in:
+4
-5
@@ -18,12 +18,10 @@ import kotlin.script.experimental.api.*
|
|||||||
import kotlin.script.experimental.host.toScriptSource
|
import kotlin.script.experimental.host.toScriptSource
|
||||||
import kotlin.script.experimental.host.with
|
import kotlin.script.experimental.host.with
|
||||||
import kotlin.script.experimental.jvm.*
|
import kotlin.script.experimental.jvm.*
|
||||||
|
import kotlin.script.experimental.jvm.BasicJvmScriptEvaluator
|
||||||
import kotlin.script.experimental.jvm.impl.KJvmCompiledScript
|
import kotlin.script.experimental.jvm.impl.KJvmCompiledScript
|
||||||
import kotlin.script.experimental.jvm.util.KotlinJars
|
import kotlin.script.experimental.jvm.util.KotlinJars
|
||||||
import kotlin.script.experimental.jvmhost.BasicJvmScriptingHost
|
import kotlin.script.experimental.jvmhost.*
|
||||||
import kotlin.script.experimental.jvmhost.CompiledJvmScriptsCache
|
|
||||||
import kotlin.script.experimental.jvmhost.CompiledScriptJarsCache
|
|
||||||
import kotlin.script.experimental.jvmhost.JvmScriptCompiler
|
|
||||||
|
|
||||||
class CachingTest : TestCase() {
|
class CachingTest : TestCase() {
|
||||||
|
|
||||||
@@ -104,9 +102,10 @@ class CachingTest : TestCase() {
|
|||||||
val hostConfiguration = defaultJvmScriptingHostConfiguration.with {
|
val hostConfiguration = defaultJvmScriptingHostConfiguration.with {
|
||||||
jvm {
|
jvm {
|
||||||
baseClassLoader.replaceOnlyDefault(null)
|
baseClassLoader.replaceOnlyDefault(null)
|
||||||
|
compilationCache(cache)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val compiler = JvmScriptCompiler(hostConfiguration, cache = cache)
|
val compiler = JvmScriptCompiler(hostConfiguration)
|
||||||
val evaluator = BasicJvmScriptEvaluator()
|
val evaluator = BasicJvmScriptEvaluator()
|
||||||
val host = BasicJvmScriptingHost(compiler = compiler, evaluator = evaluator)
|
val host = BasicJvmScriptingHost(compiler = compiler, evaluator = evaluator)
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -13,12 +13,14 @@ import kotlin.script.experimental.api.ScriptCompilationConfiguration
|
|||||||
import kotlin.script.experimental.api.SourceCode
|
import kotlin.script.experimental.api.SourceCode
|
||||||
import kotlin.script.experimental.api.hostConfiguration
|
import kotlin.script.experimental.api.hostConfiguration
|
||||||
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
||||||
|
import kotlin.script.experimental.jvm.CompiledJvmScriptsCache
|
||||||
import kotlin.script.experimental.jvm.baseClassLoader
|
import kotlin.script.experimental.jvm.baseClassLoader
|
||||||
import kotlin.script.experimental.jvm.impl.KJvmCompiledScript
|
import kotlin.script.experimental.jvm.impl.KJvmCompiledScript
|
||||||
import kotlin.script.experimental.jvm.impl.createScriptFromClassLoader
|
import kotlin.script.experimental.jvm.impl.createScriptFromClassLoader
|
||||||
import kotlin.script.experimental.jvm.jvm
|
import kotlin.script.experimental.jvm.jvm
|
||||||
|
|
||||||
open class CompiledScriptJarsCache(val scriptToFile: (SourceCode, ScriptCompilationConfiguration) -> File?) : CompiledJvmScriptsCache {
|
open class CompiledScriptJarsCache(val scriptToFile: (SourceCode, ScriptCompilationConfiguration) -> File?) :
|
||||||
|
CompiledJvmScriptsCache {
|
||||||
|
|
||||||
override fun get(script: SourceCode, scriptCompilationConfiguration: ScriptCompilationConfiguration): CompiledScript<*>? {
|
override fun get(script: SourceCode, scriptCompilationConfiguration: ScriptCompilationConfiguration): CompiledScript<*>? {
|
||||||
val file = scriptToFile(script, scriptCompilationConfiguration)
|
val file = scriptToFile(script, scriptCompilationConfiguration)
|
||||||
+7
-36
@@ -14,26 +14,9 @@ import kotlin.script.experimental.host.ScriptingHostConfiguration
|
|||||||
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||||
import kotlin.script.experimental.jvmhost.impl.withDefaults
|
import kotlin.script.experimental.jvmhost.impl.withDefaults
|
||||||
|
|
||||||
interface CompiledJvmScriptsCache {
|
|
||||||
fun get(script: SourceCode, scriptCompilationConfiguration: ScriptCompilationConfiguration): CompiledScript<*>?
|
|
||||||
fun store(compiledScript: CompiledScript<*>, script: SourceCode, scriptCompilationConfiguration: ScriptCompilationConfiguration)
|
|
||||||
|
|
||||||
object NoCache : CompiledJvmScriptsCache {
|
|
||||||
override fun get(
|
|
||||||
script: SourceCode, scriptCompilationConfiguration: ScriptCompilationConfiguration
|
|
||||||
): CompiledScript<*>? = null
|
|
||||||
|
|
||||||
override fun store(
|
|
||||||
compiledScript: CompiledScript<*>, script: SourceCode, scriptCompilationConfiguration: ScriptCompilationConfiguration
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
open class JvmScriptCompiler(
|
open class JvmScriptCompiler(
|
||||||
baseHostConfiguration: ScriptingHostConfiguration = defaultJvmScriptingHostConfiguration,
|
baseHostConfiguration: ScriptingHostConfiguration = defaultJvmScriptingHostConfiguration,
|
||||||
compilerProxy: ScriptJvmCompilerProxy? = null,
|
compilerProxy: ScriptJvmCompilerProxy? = null
|
||||||
val cache: CompiledJvmScriptsCache = CompiledJvmScriptsCache.NoCache
|
|
||||||
) : ScriptCompiler {
|
) : ScriptCompiler {
|
||||||
|
|
||||||
val hostConfiguration = baseHostConfiguration.withDefaults()
|
val hostConfiguration = baseHostConfiguration.withDefaults()
|
||||||
@@ -43,24 +26,12 @@ open class JvmScriptCompiler(
|
|||||||
override suspend operator fun invoke(
|
override suspend operator fun invoke(
|
||||||
script: SourceCode,
|
script: SourceCode,
|
||||||
scriptCompilationConfiguration: ScriptCompilationConfiguration
|
scriptCompilationConfiguration: ScriptCompilationConfiguration
|
||||||
): ResultWithDiagnostics<CompiledScript<*>> {
|
): ResultWithDiagnostics<CompiledScript<*>> =
|
||||||
|
compilerProxy.compile(
|
||||||
// TODO: implement caching deeper in the compilation pipeline - the actual configuration should be calculated first, with dependencies and imported scripts
|
script,
|
||||||
// Note that previous implementation wasn't a solution for that and added problems with cache usage. Now it is consistent although shallow.
|
scriptCompilationConfiguration.with {
|
||||||
|
hostConfiguration(this@JvmScriptCompiler.hostConfiguration)
|
||||||
val cached = cache.get(script, scriptCompilationConfiguration)
|
|
||||||
if (cached != null) return cached.asSuccess()
|
|
||||||
|
|
||||||
return scriptCompilationConfiguration.with {
|
|
||||||
hostConfiguration(this@JvmScriptCompiler.hostConfiguration)
|
|
||||||
}.refineBeforeParsing(script).onSuccess { refinedConfiguration ->
|
|
||||||
|
|
||||||
compilerProxy.compile(script, refinedConfiguration).also {
|
|
||||||
if (it is ResultWithDiagnostics.Success) {
|
|
||||||
cache.store(it.value, script, scriptCompilationConfiguration)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package kotlin.script.experimental.jvm
|
||||||
|
|
||||||
|
import kotlin.script.experimental.api.CompiledScript
|
||||||
|
import kotlin.script.experimental.api.ScriptCompilationConfiguration
|
||||||
|
import kotlin.script.experimental.api.SourceCode
|
||||||
|
import kotlin.script.experimental.util.PropertiesCollection
|
||||||
|
|
||||||
|
interface CompiledJvmScriptsCache {
|
||||||
|
fun get(script: SourceCode, scriptCompilationConfiguration: ScriptCompilationConfiguration): CompiledScript<*>?
|
||||||
|
fun store(compiledScript: CompiledScript<*>, script: SourceCode, scriptCompilationConfiguration: ScriptCompilationConfiguration)
|
||||||
|
|
||||||
|
object NoCache : CompiledJvmScriptsCache {
|
||||||
|
override fun get(
|
||||||
|
script: SourceCode, scriptCompilationConfiguration: ScriptCompilationConfiguration
|
||||||
|
): CompiledScript<*>? = null
|
||||||
|
|
||||||
|
override fun store(
|
||||||
|
compiledScript: CompiledScript<*>, script: SourceCode, scriptCompilationConfiguration: ScriptCompilationConfiguration
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val JvmScriptingHostConfigurationKeys.compilationCache by PropertiesCollection.key<CompiledJvmScriptsCache>(isTransient = true)
|
||||||
|
|
||||||
+44
-7
@@ -18,9 +18,13 @@ import org.jetbrains.kotlin.config.CompilerConfiguration
|
|||||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.scripting.compiler.plugin.ScriptJvmCompilerProxy
|
import org.jetbrains.kotlin.scripting.compiler.plugin.ScriptJvmCompilerProxy
|
||||||
|
import org.jetbrains.kotlin.scripting.compiler.plugin.dependencies.ScriptsCompilationDependencies
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
|
||||||
import kotlin.script.experimental.api.*
|
import kotlin.script.experimental.api.*
|
||||||
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
||||||
|
import kotlin.script.experimental.jvm.compilationCache
|
||||||
|
import kotlin.script.experimental.jvm.impl.KJvmCompiledScript
|
||||||
|
import kotlin.script.experimental.jvm.jvm
|
||||||
|
|
||||||
class ScriptJvmCompilerIsolated(val hostConfiguration: ScriptingHostConfiguration) : ScriptJvmCompilerProxy {
|
class ScriptJvmCompilerIsolated(val hostConfiguration: ScriptingHostConfiguration) : ScriptJvmCompilerProxy {
|
||||||
|
|
||||||
@@ -30,8 +34,12 @@ class ScriptJvmCompilerIsolated(val hostConfiguration: ScriptingHostConfiguratio
|
|||||||
): ResultWithDiagnostics<CompiledScript<*>> =
|
): ResultWithDiagnostics<CompiledScript<*>> =
|
||||||
withMessageCollectorAndDisposable(script = script) { messageCollector, disposable ->
|
withMessageCollectorAndDisposable(script = script) { messageCollector, disposable ->
|
||||||
|
|
||||||
|
val initialConfiguration = scriptCompilationConfiguration.refineBeforeParsing(script).valueOr {
|
||||||
|
return it
|
||||||
|
}
|
||||||
|
|
||||||
val context = createIsolatedCompilationContext(
|
val context = createIsolatedCompilationContext(
|
||||||
scriptCompilationConfiguration, hostConfiguration, messageCollector, disposable
|
initialConfiguration, hostConfiguration, messageCollector, disposable
|
||||||
)
|
)
|
||||||
|
|
||||||
compileImpl(script, context, messageCollector)
|
compileImpl(script, context, messageCollector)
|
||||||
@@ -47,7 +55,11 @@ class ScriptJvmCompilerFromEnvironment(val environment: KotlinCoreEnvironment) :
|
|||||||
val parentMessageCollector = environment.configuration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY]
|
val parentMessageCollector = environment.configuration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY]
|
||||||
return withMessageCollector(script = script, parentMessageCollector = parentMessageCollector) { messageCollector ->
|
return withMessageCollector(script = script, parentMessageCollector = parentMessageCollector) { messageCollector ->
|
||||||
|
|
||||||
val context = createCompilationContextFromEnvironment(scriptCompilationConfiguration, environment, messageCollector)
|
val initialConfiguration = scriptCompilationConfiguration.refineBeforeParsing(script).valueOr {
|
||||||
|
return it
|
||||||
|
}
|
||||||
|
|
||||||
|
val context = createCompilationContextFromEnvironment(initialConfiguration, environment, messageCollector)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
environment.configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector)
|
environment.configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector)
|
||||||
@@ -83,6 +95,33 @@ private fun compileImpl(
|
|||||||
)
|
)
|
||||||
|
|
||||||
val dependenciesProvider = ScriptDependenciesProvider.getInstance(context.environment.project)
|
val dependenciesProvider = ScriptDependenciesProvider.getInstance(context.environment.project)
|
||||||
|
val getScriptConfiguration = { ktFile: KtFile ->
|
||||||
|
dependenciesProvider?.getScriptConfigurationResult(ktFile)?.valueOrNull()?.configuration
|
||||||
|
?: context.baseScriptCompilationConfiguration
|
||||||
|
}
|
||||||
|
|
||||||
|
val refinedConfiguration = getScriptConfiguration(mainKtFile)
|
||||||
|
|
||||||
|
val cache = refinedConfiguration[ScriptCompilationConfiguration.hostConfiguration]?.get(ScriptingHostConfiguration.jvm.compilationCache)
|
||||||
|
|
||||||
|
val cached = cache?.get(script, refinedConfiguration)
|
||||||
|
|
||||||
|
return cached?.asSuccess(messageCollector.diagnostics)
|
||||||
|
?: doCompile(context, script, sourceFiles, sourceDependencies, messageCollector, getScriptConfiguration).also {
|
||||||
|
if (cache != null && it is ResultWithDiagnostics.Success) {
|
||||||
|
cache.store(it.value, script, refinedConfiguration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun doCompile(
|
||||||
|
context: SharedScriptCompilationContext,
|
||||||
|
script: SourceCode,
|
||||||
|
sourceFiles: List<KtFile>,
|
||||||
|
sourceDependencies: List<ScriptsCompilationDependencies.SourceDependencies>,
|
||||||
|
messageCollector: ScriptDiagnosticsMessageCollector,
|
||||||
|
getScriptConfiguration: (KtFile) -> ScriptCompilationConfiguration
|
||||||
|
): ResultWithDiagnostics<KJvmCompiledScript<Any>> {
|
||||||
val analysisResult = analyze(sourceFiles, context.environment)
|
val analysisResult = analyze(sourceFiles, context.environment)
|
||||||
|
|
||||||
if (!analysisResult.shouldGenerateCode) return failure(
|
if (!analysisResult.shouldGenerateCode) return failure(
|
||||||
@@ -102,11 +141,9 @@ private fun compileImpl(
|
|||||||
generationState,
|
generationState,
|
||||||
script,
|
script,
|
||||||
sourceFiles.first(),
|
sourceFiles.first(),
|
||||||
sourceDependencies
|
sourceDependencies,
|
||||||
) { ktFile ->
|
getScriptConfiguration
|
||||||
dependenciesProvider?.getScriptConfigurationResult(ktFile)?.valueOrNull()?.configuration
|
)
|
||||||
?: context.baseScriptCompilationConfiguration
|
|
||||||
}
|
|
||||||
|
|
||||||
return ResultWithDiagnostics.Success(compiledScript, messageCollector.diagnostics)
|
return ResultWithDiagnostics.Success(compiledScript, messageCollector.diagnostics)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user