[JS IR] tests both per-module and regular mode
This commit is contained in:
@@ -44,6 +44,7 @@ import org.jetbrains.kotlin.ir.backend.js.ic.*
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformer
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformerTmp
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.SourceMapsInfo
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.TranslationMode
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImplForJsIC
|
||||
import org.jetbrains.kotlin.ir.declarations.persistent.PersistentIrFactory
|
||||
@@ -283,9 +284,11 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
||||
val caches = loadModuleCaches(icCaches)
|
||||
val moduleKind = configurationJs[JSConfigurationKeys.MODULE_KIND]!!
|
||||
|
||||
val compiledModule = generateJsFromAst(moduleName, moduleKind, SourceMapsInfo.from(configurationJs), caches)
|
||||
val translationMode = TranslationMode.fromFlags(false, arguments.irPerModule)
|
||||
|
||||
val outputs = compiledModule.outputs!!
|
||||
val compiledModule = generateJsFromAst(moduleName, moduleKind, SourceMapsInfo.from(configurationJs), setOf(translationMode), caches)
|
||||
|
||||
val outputs = compiledModule.outputs.values.single()
|
||||
|
||||
outputFile.write(outputs)
|
||||
outputs.dependencies.forEach { (name, content) ->
|
||||
@@ -408,18 +411,15 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
||||
val transformer = IrModuleToJsTransformerTmp(
|
||||
ir.context,
|
||||
mainCallArguments,
|
||||
fullJs = true,
|
||||
dceJs = arguments.irDce,
|
||||
multiModule = arguments.irPerModule,
|
||||
relativeRequirePath = true,
|
||||
)
|
||||
|
||||
transformer.generateModule(ir.allModules)
|
||||
transformer.generateModule(ir.allModules, setOf(TranslationMode.fromFlags(arguments.irDce, arguments.irPerModule)))
|
||||
} else {
|
||||
val transformer = IrModuleToJsTransformer(
|
||||
ir.context,
|
||||
mainCallArguments,
|
||||
fullJs = true,
|
||||
fullJs = !arguments.irDce,
|
||||
dceJs = arguments.irDce,
|
||||
multiModule = arguments.irPerModule,
|
||||
relativeRequirePath = true,
|
||||
@@ -430,11 +430,7 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
||||
|
||||
messageCollector.report(INFO, "Executable production duration: ${System.currentTimeMillis() - start}ms")
|
||||
|
||||
|
||||
val outputs = if (arguments.irDce && !arguments.irDceDriven)
|
||||
compiledModule.outputsAfterDce!!
|
||||
else
|
||||
compiledModule.outputs!!
|
||||
val outputs = compiledModule.outputs.values.single()
|
||||
|
||||
outputFile.write(outputs)
|
||||
outputs.dependencies.forEach { (name, content) ->
|
||||
|
||||
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.ir.backend.js.lower.generateJsTests
|
||||
import org.jetbrains.kotlin.ir.backend.js.lower.moveBodilessDeclarationsToSeparatePlace
|
||||
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrLinker
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformer
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.TranslationMode
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.NameTables
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFactory
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
@@ -30,8 +31,7 @@ import org.jetbrains.kotlin.js.config.RuntimeDiagnostic
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
class CompilerResult(
|
||||
val outputs: CompilationOutputs?,
|
||||
val outputsAfterDce: CompilationOutputs?,
|
||||
val outputs: Map<TranslationMode, CompilationOutputs>,
|
||||
val tsDefinitions: String? = null
|
||||
)
|
||||
|
||||
@@ -228,5 +228,5 @@ fun generateJsCode(
|
||||
jsPhases.invokeToplevel(PhaseConfig(jsPhases), context, listOf(moduleFragment))
|
||||
|
||||
val transformer = IrModuleToJsTransformer(context, null, true, nameTables)
|
||||
return transformer.generateModule(listOf(moduleFragment)).outputs!!.jsCode
|
||||
return transformer.generateModule(listOf(moduleFragment)).outputs[TranslationMode.FULL]!!.jsCode
|
||||
}
|
||||
@@ -92,9 +92,6 @@ fun compileWithIC(
|
||||
val transformer = IrModuleToJsTransformerTmp(
|
||||
context,
|
||||
mainArguments,
|
||||
fullJs = generateFullJs,
|
||||
dceJs = generateDceJs,
|
||||
multiModule = multiModule,
|
||||
relativeRequirePath = relativeRequirePath,
|
||||
)
|
||||
|
||||
@@ -129,24 +126,28 @@ fun generateJsFromAst(
|
||||
mainModuleName: String,
|
||||
moduleKind: ModuleKind,
|
||||
sourceMapsInfo: SourceMapsInfo?,
|
||||
translationModes: Set<TranslationMode>,
|
||||
caches: Map<String, ModuleCache>,
|
||||
): CompilerResult {
|
||||
val deserializer = JsIrAstDeserializer()
|
||||
val jsIrProgram = JsIrProgram(caches.values.map {
|
||||
JsIrModule(
|
||||
it.name.safeModuleName,
|
||||
sanitizeName(it.name.safeModuleName),
|
||||
it.asts.values.sortedBy { it.name }.mapNotNull { it.ast?.let { deserializer.deserialize(ByteArrayInputStream(it)) } })
|
||||
})
|
||||
return CompilerResult(
|
||||
generateWrappedModuleBody(
|
||||
multiModule = true,
|
||||
fun compilationOutput(multiModule: Boolean): CompilationOutputs {
|
||||
val deserializer = JsIrAstDeserializer()
|
||||
val jsIrProgram = JsIrProgram(caches.values.map {
|
||||
JsIrModule(
|
||||
it.name.safeModuleName,
|
||||
sanitizeName(it.name.safeModuleName),
|
||||
it.asts.values.sortedBy { it.name }.mapNotNull { it.ast?.let { deserializer.deserialize(ByteArrayInputStream(it)) } })
|
||||
})
|
||||
|
||||
return generateWrappedModuleBody(
|
||||
multiModule = multiModule,
|
||||
mainModuleName = mainModuleName,
|
||||
moduleKind = moduleKind,
|
||||
jsIrProgram,
|
||||
sourceMapsInfo = sourceMapsInfo,
|
||||
relativeRequirePath = false,
|
||||
generateScriptModule = false,
|
||||
), null
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
return CompilerResult(translationModes.associate { it to compilationOutput(it.perModule) }, null)
|
||||
}
|
||||
+8
-5
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.js.sourceMap.SourceMapBuilderConsumer
|
||||
import org.jetbrains.kotlin.js.util.TextOutputImpl
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
class IrModuleToJsTransformer(
|
||||
private val backendContext: JsIrBackendContext,
|
||||
@@ -65,18 +66,20 @@ class IrModuleToJsTransformer(
|
||||
namer.merge(module.files, additionalPackages)
|
||||
}
|
||||
|
||||
val jsCode = if (fullJs) generateWrappedModuleBody(modules, exportedModule, namer) else null
|
||||
val code = EnumMap<TranslationMode, CompilationOutputs>(TranslationMode::class.java)
|
||||
|
||||
val dceJsCode = if (dceJs) {
|
||||
if (fullJs) code[TranslationMode.fromFlags(false, multiModule)] = generateWrappedModuleBody(modules, exportedModule, namer)
|
||||
|
||||
if (dceJs) {
|
||||
eliminateDeadDeclarations(modules, backendContext, removeUnusedAssociatedObjects)
|
||||
// Use a fresh namer for DCE so that we could compare the result with DCE-driven
|
||||
// TODO: is this mode relevant for scripting? If yes, refactor so that the external name tables are used here when needed.
|
||||
val namer = NameTables(emptyList(), context = backendContext)
|
||||
namer.merge(modules.flatMap { it.files }, additionalPackages)
|
||||
generateWrappedModuleBody(modules, exportedModule, namer)
|
||||
} else null
|
||||
code[TranslationMode.fromFlags(true, multiModule)] = generateWrappedModuleBody(modules, exportedModule, namer)
|
||||
}
|
||||
|
||||
return CompilerResult(jsCode, dceJsCode, dts)
|
||||
return CompilerResult(code, dts)
|
||||
}
|
||||
|
||||
private fun generateWrappedModuleBody(modules: Iterable<IrModuleFragment>, exportedModule: ExportedModule, namer: NameTables): CompilationOutputs {
|
||||
|
||||
+33
-18
@@ -30,15 +30,30 @@ import org.jetbrains.kotlin.js.util.TextOutputImpl
|
||||
import org.jetbrains.kotlin.serialization.js.ModuleKind
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
enum class TranslationMode(val dce: Boolean, val perModule: Boolean) {
|
||||
FULL(dce = false, perModule = false),
|
||||
FULL_DCE(dce = true, perModule = false),
|
||||
PER_MODULE(dce = false, perModule = true),
|
||||
PER_MODULE_DCE(dce = true, perModule = true);
|
||||
|
||||
companion object {
|
||||
fun fromFlags(dce: Boolean, perModule: Boolean): TranslationMode {
|
||||
return if (perModule) {
|
||||
if (dce) PER_MODULE_DCE else PER_MODULE
|
||||
} else {
|
||||
if (dce) FULL_DCE else FULL
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class IrModuleToJsTransformerTmp(
|
||||
private val backendContext: JsIrBackendContext,
|
||||
private val mainArguments: List<String>?,
|
||||
private val generateScriptModule: Boolean = false,
|
||||
var namer: NameTables = NameTables(emptyList(), context = backendContext),
|
||||
private val fullJs: Boolean = true,
|
||||
private val dceJs: Boolean = false,
|
||||
private val multiModule: Boolean = false,
|
||||
private val relativeRequirePath: Boolean = false,
|
||||
private val moduleToName: Map<IrModuleFragment, String> = emptyMap(),
|
||||
private val removeUnusedAssociatedObjects: Boolean = true,
|
||||
@@ -48,7 +63,7 @@ class IrModuleToJsTransformerTmp(
|
||||
private val mainModuleName = backendContext.configuration[CommonConfigurationKeys.MODULE_NAME]!!
|
||||
private val moduleKind = backendContext.configuration[JSConfigurationKeys.MODULE_KIND]!!
|
||||
|
||||
fun generateModule(modules: Iterable<IrModuleFragment>): CompilerResult {
|
||||
fun generateModule(modules: Iterable<IrModuleFragment>, modes: Set<TranslationMode>): CompilerResult {
|
||||
val exportModelGenerator = ExportModelGenerator(backendContext, generateNamespacesForPackages = true)
|
||||
|
||||
val exportData = modules.associate { module ->
|
||||
@@ -63,7 +78,7 @@ class IrModuleToJsTransformerTmp(
|
||||
module.files.forEach { StaticMembersLowering(backendContext).lower(it) }
|
||||
}
|
||||
|
||||
val jsCode = if (fullJs) generateWrappedModuleBody(
|
||||
fun compilationOutput(multiModule: Boolean) = generateWrappedModuleBody(
|
||||
multiModule,
|
||||
mainModuleName,
|
||||
moduleKind,
|
||||
@@ -71,23 +86,23 @@ class IrModuleToJsTransformerTmp(
|
||||
SourceMapsInfo.from(backendContext.configuration),
|
||||
relativeRequirePath,
|
||||
generateScriptModule,
|
||||
) else null
|
||||
)
|
||||
|
||||
val dceJsCode = if (dceJs) {
|
||||
val result = EnumMap<TranslationMode, CompilationOutputs>(TranslationMode::class.java)
|
||||
|
||||
modes.filter { !it.dce }.forEach {
|
||||
result[it] = compilationOutput(it.perModule)
|
||||
}
|
||||
|
||||
if (modes.any { it.dce }) {
|
||||
eliminateDeadDeclarations(modules, backendContext, removeUnusedAssociatedObjects)
|
||||
}
|
||||
|
||||
generateWrappedModuleBody(
|
||||
multiModule,
|
||||
mainModuleName,
|
||||
moduleKind,
|
||||
generateProgramFragments(modules, exportData),
|
||||
SourceMapsInfo.from(backendContext.configuration),
|
||||
relativeRequirePath,
|
||||
generateScriptModule,
|
||||
)
|
||||
} else null
|
||||
modes.filter { it.dce }.forEach {
|
||||
result[it] = compilationOutput(it.perModule)
|
||||
}
|
||||
|
||||
return CompilerResult(jsCode, dceJsCode, dts)
|
||||
return CompilerResult(result, dts)
|
||||
}
|
||||
|
||||
fun generateBinaryAst(files: Iterable<IrFile>): Map<String, ByteArray> {
|
||||
|
||||
+16
-19
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.LanguageVersion
|
||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.TranslationMode
|
||||
import org.jetbrains.kotlin.js.config.*
|
||||
import org.jetbrains.kotlin.js.facade.MainCallParameters
|
||||
import org.jetbrains.kotlin.library.KotlinLibrary
|
||||
@@ -52,10 +53,14 @@ class JsEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfigu
|
||||
const val TEST_DATA_DIR_PATH = "js/js.translator/testData"
|
||||
const val OLD_MODULE_SUFFIX = "_old"
|
||||
|
||||
private const val OUTPUT_DIR_NAME = "outputDir"
|
||||
private const val RECOMPILED_OUTPUT_DIR_NAME = "outputDir-recompiled"
|
||||
private val outputDirByMode = mapOf(
|
||||
TranslationMode.FULL to "outputDir",
|
||||
TranslationMode.FULL_DCE to "dceOutputDir",
|
||||
TranslationMode.PER_MODULE to "perModuleOutputDir",
|
||||
TranslationMode.PER_MODULE_DCE to "perModuleDceOutputDir"
|
||||
)
|
||||
|
||||
private const val OUTPUT_KLIB_DIR_NAME = "outputKlibDir"
|
||||
private const val DCE_OUTPUT_DIR_NAME = "dceOutputDir"
|
||||
private const val MINIFICATION_OUTPUT_DIR_NAME = "minOutputDir"
|
||||
|
||||
object ExceptionThrowingReporter : JsConfig.Reporter() {
|
||||
@@ -77,38 +82,30 @@ class JsEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfigu
|
||||
return testName + outputFileSuffix
|
||||
}
|
||||
|
||||
fun getJsModuleArtifactPath(testServices: TestServices, moduleName: String): String {
|
||||
return getJsArtifactsOutputDir(testServices).absolutePath + File.separator + getJsArtifactSimpleName(testServices, moduleName) + "_v5"
|
||||
fun getJsModuleArtifactPath(testServices: TestServices, moduleName: String, translationMode: TranslationMode = TranslationMode.FULL): String {
|
||||
return getJsArtifactsOutputDir(testServices, translationMode).absolutePath + File.separator + getJsArtifactSimpleName(testServices, moduleName) + "_v5"
|
||||
}
|
||||
|
||||
fun getRecompiledJsModuleArtifactPath(testServices: TestServices, moduleName: String): String {
|
||||
return getJsArtifactsRecompiledOutputDir(testServices).absolutePath + File.separator + getJsArtifactSimpleName(testServices, moduleName) + "_v5"
|
||||
fun getRecompiledJsModuleArtifactPath(testServices: TestServices, moduleName: String, translationMode: TranslationMode = TranslationMode.FULL): String {
|
||||
return getJsArtifactsRecompiledOutputDir(testServices, translationMode).absolutePath + File.separator + getJsArtifactSimpleName(testServices, moduleName) + "_v5"
|
||||
}
|
||||
|
||||
fun getJsKlibArtifactPath(testServices: TestServices, moduleName: String): String {
|
||||
return getJsKlibOutputDir(testServices).absolutePath + File.separator + getJsArtifactSimpleName(testServices, moduleName)
|
||||
}
|
||||
|
||||
fun getDceJsArtifactPath(testServices: TestServices, moduleName: String): String {
|
||||
return getDceJsArtifactsOutputDir(testServices).absolutePath + File.separator + getJsArtifactSimpleName(testServices, moduleName) + "_v5"
|
||||
fun getJsArtifactsOutputDir(testServices: TestServices, translationMode: TranslationMode = TranslationMode.FULL): File {
|
||||
return testServices.temporaryDirectoryManager.getOrCreateTempDirectory(outputDirByMode[translationMode]!!)
|
||||
}
|
||||
|
||||
fun getJsArtifactsOutputDir(testServices: TestServices): File {
|
||||
return testServices.temporaryDirectoryManager.getOrCreateTempDirectory(OUTPUT_DIR_NAME)
|
||||
}
|
||||
|
||||
fun getJsArtifactsRecompiledOutputDir(testServices: TestServices): File {
|
||||
return testServices.temporaryDirectoryManager.getOrCreateTempDirectory(RECOMPILED_OUTPUT_DIR_NAME)
|
||||
fun getJsArtifactsRecompiledOutputDir(testServices: TestServices, translationMode: TranslationMode = TranslationMode.FULL): File {
|
||||
return testServices.temporaryDirectoryManager.getOrCreateTempDirectory(outputDirByMode[translationMode]!! + "-recompiled")
|
||||
}
|
||||
|
||||
fun getJsKlibOutputDir(testServices: TestServices): File {
|
||||
return testServices.temporaryDirectoryManager.getOrCreateTempDirectory(OUTPUT_KLIB_DIR_NAME)
|
||||
}
|
||||
|
||||
fun getDceJsArtifactsOutputDir(testServices: TestServices): File {
|
||||
return testServices.temporaryDirectoryManager.getOrCreateTempDirectory(DCE_OUTPUT_DIR_NAME)
|
||||
}
|
||||
|
||||
fun getMinificationJsArtifactsOutputDir(testServices: TestServices): File {
|
||||
return testServices.temporaryDirectoryManager.getOrCreateTempDirectory(MINIFICATION_OUTPUT_DIR_NAME)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user