[JS IR] - Remove file lowering declarations from lowering phases

- rename fileToPurenessInitializers onto fileToInitializerPureness
- remove redundant check on top-level property

[JS IR] Rename initialis* to initializ* for consistency

[JS IR] Move propertyLazyInitialization property to context from configuration

[JS IR] Add test on lazy initialization properties order

[JS IR] Add multi module for lazy initialization of properties

[JS IR] Move tests onto js.translator

[JS IR] Rename fileToInitializerPureness according to context name

^KT-43222 fixed
This commit is contained in:
Ilya Goncharov
2020-11-19 13:22:22 +03:00
parent 1b5ebd83de
commit efee3ea648
24 changed files with 221 additions and 134 deletions
@@ -125,8 +125,8 @@ class K2JSCompilerArguments : CommonCompilerArguments() {
@Argument(value = "-Xir-dce-print-reachability-info", description = "Print declarations' reachability info to stdout during performing DCE")
var irDcePrintReachabilityInfo: Boolean by FreezableVar(false)
@Argument(value = "-Xir-property-lazy-initialisation", description = "Perform lazy initialisation for properties")
var irPropertyLazyInitialisation: Boolean by FreezableVar(false)
@Argument(value = "-Xir-property-lazy-initialization", description = "Perform lazy initialization for properties")
var irPropertyLazyInitialization: Boolean by FreezableVar(false)
@Argument(value = "-Xir-only", description = "Disables pre-IR backend")
var irOnly: Boolean by FreezableVar(false)
@@ -159,11 +159,6 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
arguments.irModuleName ?: FileUtil.getNameWithoutExtension(outputFile)
)
configurationJs.put(
JSConfigurationKeys.PROPERTY_LAZY_INITIALISATION,
arguments.irPropertyLazyInitialisation
)
// TODO: in this method at least 3 different compiler configurations are used (original, env.configuration, jsConfig.configuration)
// Such situation seems a bit buggy...
val config = JsConfig(projectJs, configurationJs)
@@ -269,7 +264,8 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
generateDceJs = arguments.irDce,
dceDriven = arguments.irDceDriven,
multiModule = arguments.irPerModule,
relativeRequirePath = true
relativeRequirePath = true,
propertyLazyInitialization = arguments.irPropertyLazyInitialization,
)
} catch (e: JsIrCompilationError) {
return COMPILATION_ERROR
@@ -21373,11 +21373,6 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/properties/kt9603.kt");
}
@TestMetadata("lazyInitialization.kt")
public void testLazyInitialization() throws Exception {
runTest("compiler/testData/codegen/box/properties/lazyInitialization.kt");
}
@TestMetadata("primitiveOverrideDefaultAccessor.kt")
public void testPrimitiveOverrideDefaultAccessor() throws Exception {
runTest("compiler/testData/codegen/box/properties/primitiveOverrideDefaultAccessor.kt");
@@ -43,10 +43,11 @@ class JsIrBackendContext(
val additionalExportedDeclarationNames: Set<FqName>,
override val configuration: CompilerConfiguration, // TODO: remove configuration from backend context
override val scriptMode: Boolean = false,
override val es6mode: Boolean = false
override val es6mode: Boolean = false,
val propertyLazyInitialization: Boolean = false,
) : JsCommonBackendContext {
val fileToInitialisationFuns: MutableMap<IrFile, IrSimpleFunction?> = mutableMapOf()
val fileToPurenessInitializers: MutableMap<IrFile, Boolean> = mutableMapOf()
val fileToInitializationFuns: MutableMap<IrFile, IrSimpleFunction?> = mutableMapOf()
val fileToInitializerPureness: MutableMap<IrFile, Boolean> = mutableMapOf()
override val extractedLocalClasses: MutableSet<IrClass> = hashSetOf()
@@ -109,16 +109,6 @@ class ModuleLowering(
override val modulePhase: NamedCompilerPhase<JsIrBackendContext, Iterable<IrModuleFragment>>
) : Lowering(name)
class FileLowering(
name: String,
description: String,
prerequisite: Set<NamedCompilerPhase<JsIrBackendContext, *>> = emptySet(),
private val factory: (JsIrBackendContext) -> FileLoweringPass
) : Lowering(name) {
override val modulePhase: NamedCompilerPhase<JsIrBackendContext, Iterable<IrModuleFragment>> =
makeJsModulePhase(factory, name, description, prerequisite)
}
private fun makeDeclarationTransformerPhase(
lowering: (JsIrBackendContext) -> DeclarationTransformer,
name: String,
@@ -133,13 +123,6 @@ private fun makeBodyLoweringPhase(
prerequisite: Set<Lowering> = emptySet()
) = BodyLowering(name, description, prerequisite.map { it.modulePhase }.toSet(), lowering)
private fun makeFileLoweringPhase(
lowering: (JsIrBackendContext) -> FileLoweringPass,
name: String,
description: String,
prerequisite: Set<Lowering> = emptySet()
) = FileLowering(name, description, prerequisite.map { it.modulePhase }.toSet(), lowering)
fun NamedCompilerPhase<JsIrBackendContext, Iterable<IrModuleFragment>>.toModuleLowering() = ModuleLowering(this.name, this)
private val validateIrBeforeLowering = makeCustomJsModulePhase(
@@ -378,7 +361,7 @@ private val propertyLazyInitLoweringPhase = makeBodyLoweringPhase(
private val removeInitializersForLazyProperties = makeDeclarationTransformerPhase(
::RemoveInitializersForLazyProperties,
name = "RemoveInitializersForLazyProperties",
description = "Remove property initializers if they was initialised lazily"
description = "Remove property initializers if they was initialized lazily"
)
private val propertyAccessorInlinerLoweringPhase = makeBodyLoweringPhase(
@@ -48,7 +48,8 @@ fun compile(
dceDriven: Boolean = false,
es6mode: Boolean = false,
multiModule: Boolean = false,
relativeRequirePath: Boolean = false
relativeRequirePath: Boolean = false,
propertyLazyInitialization: Boolean,
): CompilerResult {
stageController = StageController()
@@ -62,7 +63,16 @@ fun compile(
is MainModule.Klib -> dependencyModules
}
val context = JsIrBackendContext(moduleDescriptor, irBuiltIns, symbolTable, allModules.first(), exportedDeclarations, configuration, es6mode = es6mode)
val context = JsIrBackendContext(
moduleDescriptor,
irBuiltIns,
symbolTable,
allModules.first(),
exportedDeclarations,
configuration,
es6mode = es6mode,
propertyLazyInitialization = propertyLazyInitialization,
)
// Load declarations referenced during `context` initialization
val irProviders = listOf(deserializer)
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.ir.builders.declarations.buildField
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.persistent.PersistentIrElementBase
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.js.config.JSConfigurationKeys.PROPERTY_LAZY_INITIALISATION
import org.jetbrains.kotlin.name.Name
import kotlin.collections.component1
import kotlin.collections.component2
@@ -37,43 +36,41 @@ class PropertyLazyInitLowering(
private val irFactory
get() = context.irFactory
val fileToInitialisationFuns
get() = context.fileToInitialisationFuns
private val fileToInitializationFuns
get() = context.fileToInitializationFuns
val fileToPurenessInitializers
get() = context.fileToPurenessInitializers
private val fileToInitializerPureness
get() = context.fileToInitializerPureness
override fun lower(irBody: IrBody, container: IrDeclaration) {
if (context.configuration[PROPERTY_LAZY_INITIALISATION] != true) {
if (!context.propertyLazyInitialization) {
return
}
if (container !is IrSimpleFunction && container !is IrField && container !is IrProperty)
return
if (!container.isTopLevel) return
val file = container.parent as? IrFile
?: return
val initFun = (when {
file in fileToInitialisationFuns -> fileToInitialisationFuns[file]
fileToPurenessInitializers[file] == true -> null
file in fileToInitializationFuns -> fileToInitializationFuns[file]
fileToInitializerPureness[file] == true -> null
else -> {
createInitialisationFunction(file).also {
fileToInitialisationFuns[file] = it
createInitializationFunction(file).also {
fileToInitializationFuns[file] = it
}
}
}) ?: return
val initialisationCall = JsIrBuilder.buildCall(
val initializationCall = JsIrBuilder.buildCall(
target = initFun.symbol,
type = initFun.returnType
)
when (container) {
is IrSimpleFunction ->
irBody.addInitialisation(initialisationCall, container)
irBody.addInitialization(initializationCall, container)
is IrField -> {
container
.correspondingProperty
@@ -82,13 +79,13 @@ class PropertyLazyInitLowering(
?.let { listOf(it.getter, it.setter) }
?.filterNotNull()
?.forEach {
irBody.addInitialisation(initialisationCall, it)
irBody.addInitialization(initializationCall, it)
}
}
}
}
private fun createInitialisationFunction(
private fun createInitializationFunction(
file: IrFile
): IrSimpleFunction? {
val fileName = file.name
@@ -102,12 +99,12 @@ class PropertyLazyInitLowering(
if (fieldToInitializer.isEmpty()) return null
val allFieldsInFilePure = allFieldsInFilePure(fieldToInitializer.values)
fileToPurenessInitializers[file] = allFieldsInFilePure
fileToInitializerPureness[file] = allFieldsInFilePure
if (allFieldsInFilePure) {
return null
}
val initialisedField = irFactory.createInitialisationField(fileName)
val initializedField = irFactory.createInitializationField(fileName)
.apply {
file.declarations.add(this)
parent = file
@@ -121,14 +118,14 @@ class PropertyLazyInitLowering(
}.apply {
buildPropertiesInitializationBody(
fieldToInitializer,
initialisedField
initializedField
)
}
}
private fun IrFactory.createInitialisationField(fileName: String): IrField =
private fun IrFactory.createInitializationField(fileName: String): IrField =
buildField {
name = Name.identifier("properties initialised $fileName")
name = Name.identifier("properties initialized $fileName")
type = irBuiltIns.booleanType
isStatic = true
isFinal = true
@@ -137,18 +134,18 @@ class PropertyLazyInitLowering(
private fun IrSimpleFunction.buildPropertiesInitializationBody(
initializers: Map<IrField, IrExpression>,
initialisedField: IrField
initializedField: IrField
) {
body = irFactory.createBlockBody(
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
buildBodyWithIfGuard(initializers, initialisedField)
buildBodyWithIfGuard(initializers, initializedField)
)
}
private fun buildBodyWithIfGuard(
initializers: Map<IrField, IrExpression>,
initialisedField: IrField
initializedField: IrField
): List<IrStatement> {
val statements = initializers
.map { (field, expression) ->
@@ -156,13 +153,13 @@ class PropertyLazyInitLowering(
}
val upGuard = createIrSetField(
initialisedField,
initializedField,
JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, true)
)
return JsIrBuilder.buildIfElse(
type = irBuiltIns.unitType,
cond = calculator.not(createIrGetField(initialisedField)),
cond = calculator.not(createIrGetField(initializedField)),
thenBranch = JsIrBuilder.buildComposite(
type = irBuiltIns.unitType,
statements = mutableListOf(upGuard).apply { addAll(statements) }
@@ -171,7 +168,7 @@ class PropertyLazyInitLowering(
}
}
private fun IrBody.addInitialisation(
private fun IrBody.addInitialization(
initCall: IrCall,
container: IrSimpleFunction
) {
@@ -217,11 +214,11 @@ class RemoveInitializersForLazyProperties(
private val context: JsIrBackendContext
) : DeclarationTransformer {
val fileToPurenessInitializers
get() = context.fileToPurenessInitializers
private val fileToInitializerPureness
get() = context.fileToInitializerPureness
override fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? {
if (context.configuration[PROPERTY_LAZY_INITIALISATION] != true) {
if (!context.propertyLazyInitialization) {
return null
}
@@ -229,9 +226,9 @@ class RemoveInitializersForLazyProperties(
val file = declaration.parent as? IrFile ?: return null
if (fileToPurenessInitializers[file] == true) return null
if (fileToInitializerPureness[file] == true) return null
val allFieldsInFilePure = fileToPurenessInitializers[file]
val allFieldsInFilePure = fileToInitializerPureness[file]
?: calculateFileFieldsPureness(file)
if (allFieldsInFilePure) {
@@ -252,7 +249,7 @@ class RemoveInitializersForLazyProperties(
.values
val allFieldsInFilePure = allFieldsInFilePure(expressions)
fileToPurenessInitializers[file] = allFieldsInFilePure
fileToInitializerPureness[file] = allFieldsInFilePure
return allFieldsInFilePure
}
}
+2 -2
View File
@@ -18,8 +18,8 @@ where advanced options include:
-Xir-produce-klib-dir Generate unpacked KLIB into parent directory of output JS file.
In combination with -meta-info generates both IR and pre-IR versions of library.
-Xir-produce-klib-file Generate packed klib into file specified by -output. Disables pre-IR backend
-Xir-property-lazy-initialisation
Perform lazy initialisation for properties
-Xir-property-lazy-initialization
Perform lazy initialization for properties
-Xmetadata-only Generate *.meta.js and *.kjsm files only
-Xtyped-arrays Translate primitive arrays to JS typed arrays
-Xwasm Use experimental WebAssembly compiler backend
@@ -1,18 +0,0 @@
// IGNORE_BACKEND: JS, NATIVE
// DONT_TARGET_EXACT_BACKEND: WASM
// PROPERTY_LAZY_INITIALISATION
// FILE: A.kt
val o = "O"
// FILE: B.kt
val ok = o + k
// FILE: C.kt
val k = "K"
// FILE: main.kt
fun box(): String = ok
@@ -1,32 +0,0 @@
// TARGET_BACKEND: JS_IR
// PROPERTY_LAZY_INITIALISATION
// FILE: A.kt
val a = "A"
// FILE: B.kt
val b = "B".apply {}
val c = b
// FILE: C.kt
val d = "D".apply {}
val e = d
// FILE: main.kt
fun box(): String {
d
e
return if (
js("a") === "A" &&
js("typeof b") == "undefined" &&
js("typeof c") == "undefined" &&
js("d") === "D" &&
js("e") === "D"
)
"OK"
else "a = ${js("a")}; typeof b = ${js("typeof b")}; typeof c = ${js("typeof c")}; d = ${js("d")}; e = ${js("e")}"
}
@@ -23144,11 +23144,6 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/properties/kt9603.kt");
}
@TestMetadata("lazyInitialization.kt")
public void testLazyInitialization() throws Exception {
runTest("compiler/testData/codegen/box/properties/lazyInitialization.kt");
}
@TestMetadata("primitiveOverrideDefaultAccessor.kt")
public void testPrimitiveOverrideDefaultAccessor() throws Exception {
runTest("compiler/testData/codegen/box/properties/primitiveOverrideDefaultAccessor.kt");
@@ -23149,11 +23149,6 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/properties/kt9603.kt");
}
@TestMetadata("lazyInitialization.kt")
public void testLazyInitialization() throws Exception {
runTest("compiler/testData/codegen/box/properties/lazyInitialization.kt");
}
@TestMetadata("primitiveOverrideDefaultAccessor.kt")
public void testPrimitiveOverrideDefaultAccessor() throws Exception {
runTest("compiler/testData/codegen/box/properties/primitiveOverrideDefaultAccessor.kt");
@@ -21373,11 +21373,6 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/properties/kt9603.kt");
}
@TestMetadata("lazyInitialization.kt")
public void testLazyInitialization() throws Exception {
runTest("compiler/testData/codegen/box/properties/lazyInitialization.kt");
}
@TestMetadata("primitiveOverrideDefaultAccessor.kt")
public void testPrimitiveOverrideDefaultAccessor() throws Exception {
runTest("compiler/testData/codegen/box/properties/primitiveOverrideDefaultAccessor.kt");