JS IR: introduce 'lower per module' mode
This mode is closer to how IC supposed to work - reusing work from dependencies, not re-lowering them.
This commit is contained in:
committed by
TeamCityServer
parent
a4cb70af31
commit
eb0c13793b
+65
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 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 org.jetbrains.kotlin.ir.backend.js
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.StageController
|
||||||
|
|
||||||
|
// Only allows to apply a lowering to the whole world and save the result
|
||||||
|
class WholeWorldStageController : StageController() {
|
||||||
|
override var currentStage: Int = 0
|
||||||
|
|
||||||
|
// TODO assert lowered
|
||||||
|
|
||||||
|
var declarationListsRestricted: Boolean = false
|
||||||
|
|
||||||
|
override fun <T> withStage(stage: Int, fn: () -> T): T {
|
||||||
|
val oldStage = currentStage
|
||||||
|
currentStage = stage
|
||||||
|
return try {
|
||||||
|
fn()
|
||||||
|
} finally {
|
||||||
|
currentStage = oldStage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <T> withInitialIr(block: () -> T): T {
|
||||||
|
return withStage(0) {
|
||||||
|
declarationRestriction(true, block)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <T> bodyLowering(fn: () -> T): T {
|
||||||
|
val wasRestricted = declarationListsRestricted
|
||||||
|
declarationListsRestricted = true
|
||||||
|
|
||||||
|
return try {
|
||||||
|
fn()
|
||||||
|
} finally {
|
||||||
|
declarationListsRestricted = wasRestricted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <T> unrestrictDeclarationListsAccess(fn: () -> T): T {
|
||||||
|
return declarationRestriction(false, fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <T> declarationRestriction(value: Boolean, fn: () -> T): T{
|
||||||
|
val wasRestricted = declarationListsRestricted
|
||||||
|
declarationListsRestricted = value
|
||||||
|
|
||||||
|
return try {
|
||||||
|
fn()
|
||||||
|
} finally {
|
||||||
|
declarationListsRestricted = wasRestricted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canAccessDeclarationsOf(irClass: IrClass): Boolean {
|
||||||
|
return !declarationListsRestricted || irClass.visibility == DescriptorVisibilities.LOCAL/* && irClass !in context.extractedLocalClasses*/
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.ir.backend.js
|
|||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import org.jetbrains.kotlin.analyzer.AbstractAnalyzerWithCompilerReport
|
import org.jetbrains.kotlin.analyzer.AbstractAnalyzerWithCompilerReport
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
|
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel
|
import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
@@ -54,6 +55,7 @@ fun compile(
|
|||||||
propertyLazyInitialization: Boolean,
|
propertyLazyInitialization: Boolean,
|
||||||
legacyPropertyAccess: Boolean = false,
|
legacyPropertyAccess: Boolean = false,
|
||||||
baseClassIntoMetadata: Boolean = false,
|
baseClassIntoMetadata: Boolean = false,
|
||||||
|
lowerPerModule: Boolean = false,
|
||||||
): CompilerResult {
|
): CompilerResult {
|
||||||
val (moduleFragment: IrModuleFragment, dependencyModules, irBuiltIns, symbolTable, deserializer, moduleToName) =
|
val (moduleFragment: IrModuleFragment, dependencyModules, irBuiltIns, symbolTable, deserializer, moduleToName) =
|
||||||
loadIr(project, mainModule, analyzer, configuration, allDependencies, friendDependencies, irFactory)
|
loadIr(project, mainModule, analyzer, configuration, allDependencies, friendDependencies, irFactory)
|
||||||
@@ -116,7 +118,17 @@ fun compile(
|
|||||||
)
|
)
|
||||||
return transformer.generateModule(allModules)
|
return transformer.generateModule(allModules)
|
||||||
} else {
|
} else {
|
||||||
jsPhases.invokeToplevel(phaseConfig, context, allModules)
|
if (lowerPerModule) {
|
||||||
|
val controller = WholeWorldStageController()
|
||||||
|
check(irFactory is PersistentIrFactory)
|
||||||
|
irFactory.stageController = controller
|
||||||
|
allModules.forEach {
|
||||||
|
lowerPreservingIcData(it, context, controller)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
jsPhases.invokeToplevel(phaseConfig, context, allModules)
|
||||||
|
}
|
||||||
|
|
||||||
val transformer = IrModuleToJsTransformer(
|
val transformer = IrModuleToJsTransformer(
|
||||||
context,
|
context,
|
||||||
mainArguments,
|
mainArguments,
|
||||||
@@ -130,6 +142,24 @@ fun compile(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun lowerPreservingIcData(module: IrModuleFragment, context: JsIrBackendContext, controller: WholeWorldStageController) {
|
||||||
|
// Lower all the things
|
||||||
|
controller.currentStage = 0
|
||||||
|
|
||||||
|
pirLowerings.forEachIndexed { i, lowering ->
|
||||||
|
controller.currentStage = i + 1
|
||||||
|
when (lowering) {
|
||||||
|
is DeclarationLowering ->
|
||||||
|
lowering.declarationTransformer(context).lower(module)
|
||||||
|
is BodyLowering ->
|
||||||
|
lowering.bodyLowering(context).lower(module)
|
||||||
|
// else -> TODO what about other lowerings?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
controller.currentStage = pirLowerings.size + 1
|
||||||
|
}
|
||||||
|
|
||||||
fun generateJsCode(
|
fun generateJsCode(
|
||||||
context: JsIrBackendContext,
|
context: JsIrBackendContext,
|
||||||
moduleFragment: IrModuleFragment,
|
moduleFragment: IrModuleFragment,
|
||||||
|
|||||||
+7
@@ -439,6 +439,13 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
|
|||||||
|
|
||||||
coroutineClass.addFakeOverrides(context.irBuiltIns, implementedMembers)
|
coroutineClass.addFakeOverrides(context.irBuiltIns, implementedMembers)
|
||||||
|
|
||||||
|
// TODO constructing fake overrides on lowered declaration is tricky.
|
||||||
|
coroutineClass.declarations.transformFlat {
|
||||||
|
if (it is IrProperty && it.isFakeOverride) {
|
||||||
|
listOfNotNull(it.getter, it.setter)
|
||||||
|
} else null
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: find out whether Kotlin/Native needs this call
|
// TODO: find out whether Kotlin/Native needs this call
|
||||||
initializeStateMachine(listOf(coroutineConstructor), coroutineClassThis)
|
initializeStateMachine(listOf(coroutineConstructor), coroutineClassThis)
|
||||||
|
|
||||||
|
|||||||
@@ -49,11 +49,13 @@ abstract class BasicIrBoxTest(
|
|||||||
|
|
||||||
private fun getBoolean(s: String, default: Boolean) = System.getProperty(s)?.let { parseBoolean(it) } ?: default
|
private fun getBoolean(s: String, default: Boolean) = System.getProperty(s)?.let { parseBoolean(it) } ?: default
|
||||||
|
|
||||||
|
private val lowerPerModule: Boolean = getBoolean("kotlin.js.ir.lowerPerModule")
|
||||||
|
|
||||||
override val skipRegularMode: Boolean = getBoolean("kotlin.js.ir.skipRegularMode")
|
override val skipRegularMode: Boolean = getBoolean("kotlin.js.ir.skipRegularMode")
|
||||||
|
|
||||||
override val runIrDce: Boolean = getBoolean("kotlin.js.ir.dce", true)
|
override val runIrDce: Boolean = !lowerPerModule && getBoolean("kotlin.js.ir.dce", true)
|
||||||
|
|
||||||
override val runIrPir: Boolean = getBoolean("kotlin.js.ir.pir", true)
|
override val runIrPir: Boolean = !lowerPerModule && getBoolean("kotlin.js.ir.pir", true)
|
||||||
|
|
||||||
val runEs6Mode: Boolean = getBoolean("kotlin.js.ir.es6", false)
|
val runEs6Mode: Boolean = getBoolean("kotlin.js.ir.es6", false)
|
||||||
|
|
||||||
@@ -131,13 +133,14 @@ abstract class BasicIrBoxTest(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!skipRegularMode) {
|
if (!skipRegularMode) {
|
||||||
|
val irFactory = if (lowerPerModule) PersistentIrFactory() else IrFactoryImpl
|
||||||
val compiledModule = compile(
|
val compiledModule = compile(
|
||||||
project = config.project,
|
project = config.project,
|
||||||
mainModule = MainModule.SourceFiles(filesToCompile),
|
mainModule = MainModule.SourceFiles(filesToCompile),
|
||||||
analyzer = AnalyzerWithCompilerReport(config.configuration),
|
analyzer = AnalyzerWithCompilerReport(config.configuration),
|
||||||
configuration = config.configuration,
|
configuration = config.configuration,
|
||||||
phaseConfig = phaseConfig,
|
phaseConfig = phaseConfig,
|
||||||
irFactory = IrFactoryImpl,
|
irFactory = irFactory,
|
||||||
allDependencies = resolvedLibraries,
|
allDependencies = resolvedLibraries,
|
||||||
friendDependencies = emptyList(),
|
friendDependencies = emptyList(),
|
||||||
mainArguments = mainCallParameters.run { if (shouldBeGenerated()) arguments() else null },
|
mainArguments = mainCallParameters.run { if (shouldBeGenerated()) arguments() else null },
|
||||||
@@ -147,6 +150,7 @@ abstract class BasicIrBoxTest(
|
|||||||
es6mode = runEs6Mode,
|
es6mode = runEs6Mode,
|
||||||
multiModule = splitPerModule || perModule,
|
multiModule = splitPerModule || perModule,
|
||||||
propertyLazyInitialization = propertyLazyInitialization,
|
propertyLazyInitialization = propertyLazyInitialization,
|
||||||
|
lowerPerModule = lowerPerModule
|
||||||
)
|
)
|
||||||
|
|
||||||
compiledModule.jsCode!!.writeTo(outputFile, config)
|
compiledModule.jsCode!!.writeTo(outputFile, config)
|
||||||
|
|||||||
Reference in New Issue
Block a user