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 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.invokeToplevel
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
@@ -54,6 +55,7 @@ fun compile(
|
||||
propertyLazyInitialization: Boolean,
|
||||
legacyPropertyAccess: Boolean = false,
|
||||
baseClassIntoMetadata: Boolean = false,
|
||||
lowerPerModule: Boolean = false,
|
||||
): CompilerResult {
|
||||
val (moduleFragment: IrModuleFragment, dependencyModules, irBuiltIns, symbolTable, deserializer, moduleToName) =
|
||||
loadIr(project, mainModule, analyzer, configuration, allDependencies, friendDependencies, irFactory)
|
||||
@@ -116,7 +118,17 @@ fun compile(
|
||||
)
|
||||
return transformer.generateModule(allModules)
|
||||
} 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(
|
||||
context,
|
||||
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(
|
||||
context: JsIrBackendContext,
|
||||
moduleFragment: IrModuleFragment,
|
||||
|
||||
+7
@@ -439,6 +439,13 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
|
||||
|
||||
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
|
||||
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 val lowerPerModule: Boolean = getBoolean("kotlin.js.ir.lowerPerModule")
|
||||
|
||||
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)
|
||||
|
||||
@@ -131,13 +133,14 @@ abstract class BasicIrBoxTest(
|
||||
}
|
||||
|
||||
if (!skipRegularMode) {
|
||||
val irFactory = if (lowerPerModule) PersistentIrFactory() else IrFactoryImpl
|
||||
val compiledModule = compile(
|
||||
project = config.project,
|
||||
mainModule = MainModule.SourceFiles(filesToCompile),
|
||||
analyzer = AnalyzerWithCompilerReport(config.configuration),
|
||||
configuration = config.configuration,
|
||||
phaseConfig = phaseConfig,
|
||||
irFactory = IrFactoryImpl,
|
||||
irFactory = irFactory,
|
||||
allDependencies = resolvedLibraries,
|
||||
friendDependencies = emptyList(),
|
||||
mainArguments = mainCallParameters.run { if (shouldBeGenerated()) arguments() else null },
|
||||
@@ -147,6 +150,7 @@ abstract class BasicIrBoxTest(
|
||||
es6mode = runEs6Mode,
|
||||
multiModule = splitPerModule || perModule,
|
||||
propertyLazyInitialization = propertyLazyInitialization,
|
||||
lowerPerModule = lowerPerModule
|
||||
)
|
||||
|
||||
compiledModule.jsCode!!.writeTo(outputFile, config)
|
||||
|
||||
Reference in New Issue
Block a user