[JS IR] Memory consumption optimization

- Remove IR after JS AST generation
 - Remove JS AST after/during JS code generation
This commit is contained in:
Alexander Korepanov
2022-08-15 14:35:37 +02:00
committed by Space
parent 14b7db0187
commit 453faeaa45
8 changed files with 218 additions and 167 deletions
@@ -43,10 +43,7 @@ import org.jetbrains.kotlin.backend.wasm.dce.eliminateDeadDeclarations
import org.jetbrains.kotlin.ir.backend.js.*
import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationGranularity
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.backend.js.transformers.irToJs.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImplForJsIC
import org.jetbrains.kotlin.js.analyzer.JsAnalysisResult
@@ -55,7 +52,6 @@ import org.jetbrains.kotlin.library.KLIB_FILE_EXTENSION
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.CompilerEnvironment
import org.jetbrains.kotlin.serialization.js.ModuleKind
import org.jetbrains.kotlin.utils.KotlinPaths
import org.jetbrains.kotlin.utils.PathUtil
@@ -79,6 +75,78 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
return K2JSCompilerArguments()
}
private data class TransformResult(val out: CompilationOutputs, val dts: String)
private class Ir2JsTransformer(
val arguments: K2JSCompilerArguments,
val module: ModulesStructure,
val phaseConfig: PhaseConfig,
val messageCollector: MessageCollector,
val mainCallArguments: List<String>?
) {
private fun lowerIr(): LoweredIr {
val granularity = when {
arguments.irPerModule -> JsGenerationGranularity.PER_MODULE
arguments.irPerFile -> JsGenerationGranularity.PER_FILE
else -> JsGenerationGranularity.WHOLE_PROGRAM
}
val irFactory = when {
arguments.irNewIr2Js -> IrFactoryImplForJsIC(WholeWorldStageController())
else -> IrFactoryImpl
}
return compile(
module,
phaseConfig,
irFactory,
dceRuntimeDiagnostic = RuntimeDiagnostic.resolve(
arguments.irDceRuntimeDiagnostic,
messageCollector
),
baseClassIntoMetadata = arguments.irBaseClassInMetadata,
safeExternalBoolean = arguments.irSafeExternalBoolean,
safeExternalBooleanDiagnostic = RuntimeDiagnostic.resolve(
arguments.irSafeExternalBooleanDiagnostic,
messageCollector
),
granularity = granularity,
icCompatibleIr2Js = arguments.irNewIr2Js,
)
}
private fun makeJsCodeGeneratorAndDts(): Pair<JsCodeGenerator, String> {
val ir = lowerIr()
val transformer = IrModuleToJsTransformerTmp(ir.context, mainCallArguments, ir.moduleFragmentToUniqueName)
val mode = TranslationMode.fromFlags(arguments.irDce, arguments.irPerModule, arguments.irMinimizedMemberNames)
return transformer.makeJsCodeGeneratorAndDts(ir.allModules, mode)
}
fun compileAndTransformIrNew(): TransformResult {
val (generator, dts) = makeJsCodeGeneratorAndDts()
val out = generator.generateJsCode(relativeRequirePath = true, outJsProgram = false)
return TransformResult(out, dts)
}
fun compileAndTransformIrOld(): TransformResult {
val ir = lowerIr()
val transformer = IrModuleToJsTransformer(
ir.context,
mainCallArguments,
fullJs = !arguments.irDce,
dceJs = arguments.irDce,
multiModule = arguments.irPerModule,
relativeRequirePath = true,
moduleToName = ir.moduleFragmentToUniqueName
)
val result = transformer.generateModule(ir.allModules)
return TransformResult(result.outputs.values.single(), result.tsDefinitions ?: error("No ts definitions"))
}
}
override fun doExecute(
arguments: K2JSCompilerArguments,
configuration: CompilerConfiguration,
@@ -301,6 +369,7 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
val outputs = jsExecutableProducer.buildExecutable(
multiModule = arguments.irPerModule,
outJsProgram = false,
rebuildCallback = { rebuiltModule ->
messageCollector.report(INFO, "IC module builder rebuilt module [${File(rebuiltModule).name}]")
}
@@ -368,72 +437,23 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
val start = System.currentTimeMillis()
val granularity = when {
arguments.irPerModule -> JsGenerationGranularity.PER_MODULE
arguments.irPerFile -> JsGenerationGranularity.PER_FILE
else -> JsGenerationGranularity.WHOLE_PROGRAM
}
try {
val irFactory = when {
arguments.irNewIr2Js -> IrFactoryImplForJsIC(WholeWorldStageController())
else -> IrFactoryImpl
}
val ir = compile(
module,
phaseConfig,
irFactory,
dceRuntimeDiagnostic = RuntimeDiagnostic.resolve(
arguments.irDceRuntimeDiagnostic,
messageCollector
),
baseClassIntoMetadata = arguments.irBaseClassInMetadata,
safeExternalBoolean = arguments.irSafeExternalBoolean,
safeExternalBooleanDiagnostic = RuntimeDiagnostic.resolve(
arguments.irSafeExternalBooleanDiagnostic,
messageCollector
),
granularity = granularity,
icCompatibleIr2Js = arguments.irNewIr2Js,
)
val compiledModule: CompilerResult = if (arguments.irNewIr2Js) {
val transformer = IrModuleToJsTransformerTmp(
ir.context,
mainCallArguments,
relativeRequirePath = true,
moduleToName = ir.moduleFragmentToUniqueName
)
transformer.generateModule(
ir.allModules,
setOf(TranslationMode.fromFlags(arguments.irDce, arguments.irPerModule, arguments.irMinimizedMemberNames))
)
val (outputs, tsDefinitions) = if (arguments.irNewIr2Js) {
Ir2JsTransformer(arguments, module, phaseConfig, messageCollector, mainCallArguments).compileAndTransformIrNew()
} else {
val transformer = IrModuleToJsTransformer(
ir.context,
mainCallArguments,
fullJs = !arguments.irDce,
dceJs = arguments.irDce,
multiModule = arguments.irPerModule,
relativeRequirePath = true,
moduleToName = ir.moduleFragmentToUniqueName
)
transformer.generateModule(ir.allModules)
Ir2JsTransformer(arguments, module, phaseConfig, messageCollector, mainCallArguments).compileAndTransformIrOld()
}
messageCollector.report(INFO, "Executable production duration: ${System.currentTimeMillis() - start}ms")
val outputs = compiledModule.outputs.values.single()
outputFile.write(outputs)
outputs.dependencies.forEach { (name, content) ->
outputFile.resolveSibling("$name.js").write(content)
}
if (arguments.generateDts) {
val dtsFile = outputFile.withReplacedExtensionOrNull(outputFile.extension, "d.ts")!!
dtsFile.writeText(compiledModule.tsDefinitions ?: error("No ts definitions"))
dtsFile.writeText(tsDefinitions)
}
} catch (e: CompilationException) {
messageCollector.report(
@@ -38,7 +38,6 @@ fun compileWithIC(
dceRuntimeDiagnostic: RuntimeDiagnostic? = null,
es6mode: Boolean = false,
multiModule: Boolean = false,
relativeRequirePath: Boolean = false,
verifySignatures: Boolean = true,
baseClassIntoMetadata: Boolean = false,
lowerPerModule: Boolean = false,
@@ -79,12 +78,7 @@ fun compileWithIC(
lowerPreservingTags(allModules, context, PhaseConfig(jsPhases), symbolTable.irFactory.stageController as WholeWorldStageController)
val transformer = IrModuleToJsTransformerTmp(
context,
mainArguments,
relativeRequirePath = relativeRequirePath,
)
val transformer = IrModuleToJsTransformerTmp(context, mainArguments)
return transformer.generateBinaryAst(filesToLower, allModules)
}
@@ -16,27 +16,28 @@ class JsExecutableProducer(
private val caches: List<ModuleArtifact>,
private val relativeRequirePath: Boolean
) {
fun buildExecutable(multiModule: Boolean, rebuildCallback: (String) -> Unit = {}) = if (multiModule) {
buildMultiModuleExecutable(rebuildCallback)
fun buildExecutable(multiModule: Boolean, outJsProgram: Boolean, rebuildCallback: (String) -> Unit = {}) = if (multiModule) {
buildMultiModuleExecutable(outJsProgram, rebuildCallback)
} else {
buildSingleModuleExecutable(rebuildCallback)
buildSingleModuleExecutable(outJsProgram, rebuildCallback)
}
private fun buildSingleModuleExecutable(rebuildCallback: (String) -> Unit): CompilationOutputs {
val program = JsIrProgram(caches.map { cacheArtifact -> cacheArtifact.loadJsIrModule() })
private fun buildSingleModuleExecutable(outJsProgram: Boolean, rebuildCallback: (String) -> Unit): CompilationOutputs {
val modules = caches.map { cacheArtifact -> cacheArtifact.loadJsIrModule() }
val out = generateSingleWrappedModuleBody(
moduleName = mainModuleName,
moduleKind = moduleKind,
fragments = program.modules.flatMap { it.fragments },
fragments = modules.flatMap { it.fragments },
sourceMapsInfo = sourceMapsInfo,
generateScriptModule = false,
generateCallToMain = true
generateCallToMain = true,
outJsProgram = outJsProgram
)
rebuildCallback(mainModuleName)
return out
}
private fun buildMultiModuleExecutable(rebuildCallback: (String) -> Unit): CompilationOutputs {
private fun buildMultiModuleExecutable(outJsProgram: Boolean, rebuildCallback: (String) -> Unit): CompilationOutputs {
val jsMultiModuleCache = JsMultiModuleCache(caches)
val cachedProgram = jsMultiModuleCache.loadProgramHeadersFromCache()
@@ -64,7 +65,8 @@ class JsExecutableProducer(
sourceMapsInfo = sourceMapsInfo,
generateScriptModule = false,
generateCallToMain = generateCallToMain,
crossModuleReferences = crossRef
crossModuleReferences = crossRef,
outJsProgram = outJsProgram
)
jsMultiModuleCache.commitCompiledJsCode(artifact, compiledModule)
rebuildCallback(moduleName)
@@ -64,11 +64,30 @@ enum class TranslationMode(
class JsIrFragmentAndBinaryAst(val irFile: IrFile, val fragment: JsIrProgramFragment, val binaryAst: ByteArray)
class JsCodeGenerator(
private val program: JsIrProgram,
private val multiModule: Boolean,
private val mainModuleName: String,
private val moduleKind: ModuleKind,
private val sourceMapsInfo: SourceMapsInfo?
) {
fun generateJsCode(relativeRequirePath: Boolean, outJsProgram: Boolean): CompilationOutputs {
return generateWrappedModuleBody(
multiModule,
mainModuleName,
moduleKind,
program,
sourceMapsInfo,
relativeRequirePath,
false,
outJsProgram
)
}
}
class IrModuleToJsTransformerTmp(
private val backendContext: JsIrBackendContext,
private val mainArguments: List<String>?,
private val generateScriptModule: Boolean = false,
private val relativeRequirePath: Boolean = false,
private val moduleToName: Map<IrModuleFragment, String> = emptyMap(),
private val removeUnusedAssociatedObjects: Boolean = true,
) {
@@ -76,40 +95,40 @@ class IrModuleToJsTransformerTmp(
private val mainModuleName = backendContext.configuration[CommonConfigurationKeys.MODULE_NAME]!!
private val moduleKind = backendContext.configuration[JSConfigurationKeys.MODULE_KIND]!!
private val sourceMapInfo = SourceMapsInfo.from(backendContext.configuration)
fun generateModule(modules: Iterable<IrModuleFragment>, modes: Set<TranslationMode>): CompilerResult {
private class IrAndExportedDeclarations(val fragment: IrModuleFragment, val files: List<Pair<IrFile, List<ExportedDeclaration>>>)
private fun List<IrAndExportedDeclarations>.flatExportedDeclarations(): List<ExportedDeclaration> {
return this.flatMap { data -> data.files.flatMap { it.second } }
}
private fun associateIrAndExport(modules: Iterable<IrModuleFragment>): List<IrAndExportedDeclarations> {
val exportModelGenerator = ExportModelGenerator(backendContext, generateNamespacesForPackages = true)
val exportData = modules.associate { module ->
module to module.files.associate { file ->
return modules.map { module ->
val files = module.files.map { file ->
file to exportModelGenerator.generateExportWithExternals(file)
}
IrAndExportedDeclarations(module, files)
}
}
val dts = ExportedModule(mainModuleName, moduleKind, exportData.values.flatMap { it.values.flatten() }).toTypeScript()
private fun doStaticMembersLowering(modules: Iterable<IrModuleFragment>) {
modules.forEach { module ->
module.files.forEach { StaticMembersLowering(backendContext).lower(it) }
}
}
fun compilationOutput(multiModule: Boolean, minimizedMemberNames: Boolean) = generateWrappedModuleBody(
multiModule,
mainModuleName,
moduleKind,
generateProgramFragments(modules, exportData, minimizedMemberNames),
SourceMapsInfo.from(backendContext.configuration),
relativeRequirePath,
generateScriptModule,
)
fun generateModule(modules: Iterable<IrModuleFragment>, modes: Set<TranslationMode>, relativeRequirePath: Boolean): CompilerResult {
val exportData = associateIrAndExport(modules)
val dts = ExportedModule(mainModuleName, moduleKind, exportData.flatExportedDeclarations()).toTypeScript()
doStaticMembersLowering(modules)
val result = EnumMap<TranslationMode, CompilationOutputs>(TranslationMode::class.java)
modes.filter { !it.dce }.forEach {
if (it.minimizedMemberNames) {
backendContext.fieldDataCache.clear()
backendContext.minimizedNameGenerator.clear()
}
result[it] = compilationOutput(it.perModule, it.minimizedMemberNames)
result[it] = makeJsCodeGeneratorFromIr(exportData, it).generateJsCode(relativeRequirePath, true)
}
if (modes.any { it.dce }) {
@@ -117,26 +136,30 @@ class IrModuleToJsTransformerTmp(
}
modes.filter { it.dce }.forEach {
if (it.minimizedMemberNames) {
backendContext.fieldDataCache.clear()
backendContext.minimizedNameGenerator.clear()
}
result[it] = compilationOutput(it.perModule, it.minimizedMemberNames)
result[it] = makeJsCodeGeneratorFromIr(exportData, it).generateJsCode(relativeRequirePath, true)
}
return CompilerResult(result, dts)
}
fun makeJsCodeGeneratorAndDts(modules: Iterable<IrModuleFragment>, mode: TranslationMode): Pair<JsCodeGenerator, String> {
val exportData = associateIrAndExport(modules)
val dts = ExportedModule(mainModuleName, moduleKind, exportData.flatExportedDeclarations()).toTypeScript()
doStaticMembersLowering(modules)
if (mode.dce) {
eliminateDeadDeclarations(modules, backendContext, removeUnusedAssociatedObjects)
}
return makeJsCodeGeneratorFromIr(exportData, mode) to dts
}
fun generateBinaryAst(files: Collection<IrFile>, allModules: Collection<IrModuleFragment>): List<JsIrFragmentAndBinaryAst> {
val exportModelGenerator = ExportModelGenerator(backendContext, generateNamespacesForPackages = true)
val exportData = files.map { it to exportModelGenerator.generateExportWithExternals(it) }
allModules.forEach {
it.files.forEach {
StaticMembersLowering(backendContext).lower(it)
}
}
doStaticMembersLowering(allModules)
val serializer = JsIrAstSerializer()
return exportData.map { (file, exports) ->
@@ -158,29 +181,35 @@ class IrModuleToJsTransformerTmp(
return moduleToName[this] ?: sanitizeName(safeName)
}
private fun generateProgramFragments(
modules: Iterable<IrModuleFragment>,
exportData: Map<IrModuleFragment, Map<IrFile, List<ExportedDeclaration>>>,
minimizedMemberNames: Boolean
): JsIrProgram {
return JsIrProgram(
modules.map { m ->
private fun makeJsCodeGeneratorFromIr(exportData: List<IrAndExportedDeclarations>, mode: TranslationMode): JsCodeGenerator {
if (mode.minimizedMemberNames) {
backendContext.fieldDataCache.clear()
backendContext.minimizedNameGenerator.clear()
}
val program = JsIrProgram(
exportData.map { data ->
JsIrModule(
m.safeName,
m.externalModuleName(),
m.files.map {
val exports = exportData[m]!![it]!!
generateProgramFragment(it, exports, minimizedMemberNames)
},
data.fragment.safeName,
data.fragment.externalModuleName(),
data.files.map { (file, exports) ->
generateProgramFragment(file, exports, mode.minimizedMemberNames)
}
)
}
)
return JsCodeGenerator(program, mode.perModule, mainModuleName, moduleKind, sourceMapInfo)
}
private val generateFilePaths = backendContext.configuration.getBoolean(JSConfigurationKeys.GENERATE_COMMENTS_WITH_FILE_PATH)
private val pathPrefixMap = backendContext.configuration.getMap(JSConfigurationKeys.FILE_PATHS_PREFIX_MAP)
private fun generateProgramFragment(file: IrFile, exports: List<ExportedDeclaration>, minimizedMemberNames: Boolean): JsIrProgramFragment {
private fun generateProgramFragment(
file: IrFile,
exports: List<ExportedDeclaration>,
minimizedMemberNames: Boolean
): JsIrProgramFragment {
val nameGenerator = JsNameLinkingNamer(backendContext, minimizedMemberNames)
val globalNameScope = NameTable<IrDeclaration>()
@@ -332,48 +361,56 @@ private fun generateWrappedModuleBody(
program: JsIrProgram,
sourceMapsInfo: SourceMapsInfo?,
relativeRequirePath: Boolean,
generateScriptModule: Boolean
generateScriptModule: Boolean,
outJsProgram: Boolean
): CompilationOutputs {
if (multiModule) {
val moduleToRef = program.crossModuleDependencies(relativeRequirePath)
val main = program.mainModule
val others = program.otherModules
val mainModule = generateSingleWrappedModuleBody(
mainModuleName,
moduleKind,
main.fragments,
sourceMapsInfo,
generateScriptModule,
generateCallToMain = true,
moduleToRef[main]!!,
)
val dependencies = others.map { module ->
val moduleName = module.externalModuleName
moduleName to generateSingleWrappedModuleBody(
moduleName,
// mutable container allows explicitly remove elements from itself,
// so we are able to help GC to free heavy JsIrModule objects
// TODO: It makes sense to invent something better, because this logic can be easily broken
val moduleToRef = program.asCrossModuleDependencies(relativeRequirePath).toMutableList()
val mainModule = moduleToRef.removeLast().let { (main, mainRef) ->
generateSingleWrappedModuleBody(
mainModuleName,
moduleKind,
module.fragments,
main.fragments,
sourceMapsInfo,
generateScriptModule,
generateCallToMain = false,
moduleToRef[module]!!,
generateCallToMain = true,
mainRef,
outJsProgram
)
}
val dependencies = buildList(moduleToRef.size) {
while (moduleToRef.isNotEmpty()) {
moduleToRef.removeFirst().let { (module, moduleRef) ->
val moduleName = module.externalModuleName
val moduleCompilationOutput = generateSingleWrappedModuleBody(
moduleName,
moduleKind,
module.fragments,
sourceMapsInfo,
generateScriptModule,
generateCallToMain = false,
moduleRef,
outJsProgram
)
add(moduleName to moduleCompilationOutput)
}
}
}
return CompilationOutputs(mainModule.jsCode, mainModule.jsProgram, mainModule.sourceMap, dependencies)
} else {
return generateSingleWrappedModuleBody(
mainModuleName,
moduleKind,
program.modules.flatMap { it.fragments },
program.asFragments(),
sourceMapsInfo,
generateScriptModule,
generateCallToMain = true,
outJsProgram = outJsProgram
)
}
}
@@ -386,6 +423,7 @@ fun generateSingleWrappedModuleBody(
generateScriptModule: Boolean,
generateCallToMain: Boolean,
crossModuleReferences: CrossModuleReferences = CrossModuleReferences.Empty,
outJsProgram: Boolean = true
): CompilationOutputs {
val program = Merger(
moduleName,
@@ -428,7 +466,7 @@ fun generateSingleWrappedModuleBody(
return CompilationOutputs(
jsCode.toString(),
program,
program.takeIf { outJsProgram },
sourceMapBuilder?.build()
)
}
@@ -55,19 +55,23 @@ class JsIrModuleHeader(
val externalNames: Set<String> by lazy { nameBindings.keys - definitions }
}
class JsIrProgram(val modules: List<JsIrModule>) {
val mainModule = modules.last()
val otherModules = modules.dropLast(1)
fun crossModuleDependencies(relativeRequirePath: Boolean): Map<JsIrModule, CrossModuleReferences> {
class JsIrProgram(private var modules: List<JsIrModule>) {
fun asCrossModuleDependencies(relativeRequirePath: Boolean): List<Pair<JsIrModule, CrossModuleReferences>> {
val resolver = CrossModuleDependenciesResolver(modules.map { it.makeModuleHeader() })
modules = emptyList()
val crossModuleReferences = resolver.resolveCrossModuleDependencies(relativeRequirePath)
return crossModuleReferences.entries.associate {
return crossModuleReferences.entries.map {
val module = it.key.associatedModule ?: error("Internal error: module ${it.key.moduleName} is not loaded")
it.value.initJsImportsForModule(module)
module to it.value
}
}
fun asFragments(): List<JsIrProgramFragment> {
val fragments = modules.flatMap { it.fragments }
modules = emptyList()
return fragments
}
}
class CrossModuleDependenciesResolver(private val headers: List<JsIrModuleHeader>) {
@@ -258,7 +258,7 @@ abstract class AbstractInvalidationTest : KotlinTestWithEnvironment() {
)
val rebuiltModules = mutableSetOf<String>()
val jsOutput = jsExecutableProducer.buildExecutable(true) { rebuiltModules += it }
val jsOutput = jsExecutableProducer.buildExecutable(multiModule = true, outJsProgram = true) { rebuiltModules += it }
verifyJsExecutableProducerBuildModules(projStep.id, rebuiltModules, projStep.dirtyJS)
verifyJsCode(projStep.id, testInfo.last().moduleName, jsOutput)
}
@@ -70,13 +70,9 @@ abstract class AbstractJsKLibABITestCase : AbstractKlibABITestCase() {
icCompatibleIr2Js = true
)
val transformer = IrModuleToJsTransformerTmp(
ir.context,
emptyList(),
relativeRequirePath = false
)
val transformer = IrModuleToJsTransformerTmp(ir.context, emptyList())
val compiledResult = transformer.generateModule(ir.allModules, setOf(TranslationMode.FULL_DCE_MINIMIZED_NAMES))
val compiledResult = transformer.generateModule(ir.allModules, setOf(TranslationMode.FULL_DCE_MINIMIZED_NAMES), false)
val dceOutput = compiledResult.outputs[TranslationMode.FULL_DCE_MINIMIZED_NAMES] ?: error("No DCE output")
@@ -122,4 +118,4 @@ abstract class AbstractJsKLibABITestCase : AbstractKlibABITestCase() {
companion object {
private const val BIN_DIR_NAME = "_bins_js"
}
}
}
@@ -109,7 +109,7 @@ class JsIrBackendFacade(
caches = testServices.jsIrIncrementalDataProvider.getCaches(),
relativeRequirePath = false
)
jsExecutableProducer.buildExecutable(it.perModule)
jsExecutableProducer.buildExecutable(it.perModule, true)
},
tsDefinitions = null
)
@@ -173,11 +173,7 @@ class JsIrBackendFacade(
val dceOutputFile = File(JsEnvironmentConfigurator.getJsModuleArtifactPath(testServices, module.name, TranslationMode.FULL_DCE_MINIMIZED_NAMES) + ".js")
if (!esModules) {
if (runNewIr2Js) {
val transformer = IrModuleToJsTransformerTmp(
loweredIr.context,
mainArguments,
relativeRequirePath = false
)
val transformer = IrModuleToJsTransformerTmp(loweredIr.context, mainArguments)
// If runIrDce then include DCE results
// If perModuleOnly then skip whole program
@@ -186,7 +182,8 @@ class JsIrBackendFacade(
.filter { (!it.dce || runIrDce) && (!perModuleOnly || it.perModule) }
.filter { it.dce == it.minimizedMemberNames }
.toSet()
return BinaryArtifacts.Js.JsIrArtifact(outputFile, transformer.generateModule(loweredIr.allModules, translationModes)).dump(module)
val compilationOut = transformer.generateModule(loweredIr.allModules, translationModes, false)
return BinaryArtifacts.Js.JsIrArtifact(outputFile, compilationOut).dump(module)
} else {
val transformer = IrModuleToJsTransformer(
loweredIr.context,