[WASM] Lazy properties initialization
This commit is contained in:
committed by
igoriakovlev
parent
e58d4163ad
commit
82455c849d
+1
@@ -30,6 +30,7 @@ interface JsCommonBackendContext : CommonBackendContext {
|
||||
override val mapping: JsMapping
|
||||
|
||||
val reflectionSymbols: ReflectionSymbols
|
||||
val propertyLazyInitialization: PropertyLazyInitialization
|
||||
|
||||
override val inlineClassesUtils: JsCommonInlineClassesUtils
|
||||
|
||||
|
||||
@@ -294,8 +294,6 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
|
||||
val doNotIntrinsifyAnnotationSymbol = context.symbolTable.referenceClass(context.getJsInternalClass("DoNotIntrinsify"))
|
||||
val jsFunAnnotationSymbol = context.symbolTable.referenceClass(context.getJsInternalClass("JsFun"))
|
||||
|
||||
val jsEagerInitializationAnnotationSymbol = context.symbolTable.referenceClass(context.getJsInternalClass("EagerInitialization"))
|
||||
|
||||
// TODO move CharSequence-related stiff to IntrinsifyCallsLowering
|
||||
val charSequenceClassSymbol = context.symbolTable.referenceClass(context.getClass(FqName("kotlin.CharSequence")))
|
||||
val charSequenceLengthPropertyGetterSymbol by context.lazy2 {
|
||||
|
||||
@@ -56,7 +56,7 @@ class JsIrBackendContext(
|
||||
override val scriptMode: Boolean = false,
|
||||
override val es6mode: Boolean = false,
|
||||
val dceRuntimeDiagnostic: RuntimeDiagnostic? = null,
|
||||
val propertyLazyInitialization: Boolean = false,
|
||||
propertyLazyInitialization: Boolean = false,
|
||||
val baseClassIntoMetadata: Boolean = false,
|
||||
val safeExternalBoolean: Boolean = false,
|
||||
val safeExternalBooleanDiagnostic: RuntimeDiagnostic? = null,
|
||||
@@ -65,8 +65,6 @@ class JsIrBackendContext(
|
||||
val icCompatibleIr2Js: Boolean = false,
|
||||
) : JsCommonBackendContext {
|
||||
|
||||
val fileToInitializationFuns: MutableMap<IrFile, IrSimpleFunction?> = mutableMapOf()
|
||||
val fileToInitializerPureness: MutableMap<IrFile, Boolean> = mutableMapOf()
|
||||
val fieldToInitializer: MutableMap<IrField, IrExpression> = mutableMapOf()
|
||||
|
||||
val localClassNames: MutableMap<IrClass, String> = mutableMapOf()
|
||||
@@ -142,6 +140,11 @@ class JsIrBackendContext(
|
||||
val intrinsics: JsIntrinsics = JsIntrinsics(irBuiltIns, this)
|
||||
override val reflectionSymbols: ReflectionSymbols get() = intrinsics.reflectionSymbols
|
||||
|
||||
override val propertyLazyInitialization: PropertyLazyInitialization = PropertyLazyInitialization(
|
||||
enabled = propertyLazyInitialization,
|
||||
eagerInitialization = symbolTable.referenceClass(getJsInternalClass("EagerInitialization"))
|
||||
)
|
||||
|
||||
override val catchAllThrowableType: IrType
|
||||
get() = dynamicType
|
||||
|
||||
@@ -207,7 +210,8 @@ class JsIrBackendContext(
|
||||
|
||||
override val getContinuation = symbolTable.referenceSimpleFunction(getJsInternalFunction("getContinuation"))
|
||||
|
||||
override val coroutineContextGetter = symbolTable.referenceSimpleFunction(context.coroutineSymbols.coroutineContextProperty.getter!!)
|
||||
override val coroutineContextGetter =
|
||||
symbolTable.referenceSimpleFunction(context.coroutineSymbols.coroutineContextProperty.getter!!)
|
||||
|
||||
override val suspendCoroutineUninterceptedOrReturn =
|
||||
symbolTable.referenceSimpleFunction(getJsInternalFunction(COROUTINE_SUSPEND_OR_RETURN_JS_NAME))
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* 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.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
|
||||
class PropertyLazyInitialization(val enabled: Boolean, eagerInitialization: IrClassSymbol) {
|
||||
val fileToInitializationFuns: MutableMap<IrFile, IrSimpleFunction?> = mutableMapOf()
|
||||
val fileToInitializerPureness: MutableMap<IrFile, Boolean> = mutableMapOf()
|
||||
val eagerInitialization: IrClassSymbol = eagerInitialization
|
||||
}
|
||||
+31
-28
@@ -13,8 +13,7 @@ import org.jetbrains.kotlin.backend.common.ir.isTopLevel
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities.INTERNAL
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrArithBuilder
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.prependFunctionCall
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.addFunction
|
||||
@@ -28,25 +27,23 @@ import kotlin.collections.component2
|
||||
import kotlin.collections.set
|
||||
|
||||
class PropertyLazyInitLowering(
|
||||
private val context: JsIrBackendContext
|
||||
private val context: JsCommonBackendContext
|
||||
) : BodyLoweringPass {
|
||||
|
||||
private val irBuiltIns
|
||||
get() = context.irBuiltIns
|
||||
|
||||
private val calculator = JsIrArithBuilder(context)
|
||||
|
||||
private val irFactory
|
||||
get() = context.irFactory
|
||||
|
||||
private val fileToInitializationFuns
|
||||
get() = context.fileToInitializationFuns
|
||||
get() = context.propertyLazyInitialization.fileToInitializationFuns
|
||||
|
||||
private val fileToInitializerPureness
|
||||
get() = context.fileToInitializerPureness
|
||||
get() = context.propertyLazyInitialization.fileToInitializerPureness
|
||||
|
||||
override fun lower(irBody: IrBody, container: IrDeclaration) {
|
||||
if (!context.propertyLazyInitialization) {
|
||||
if (!context.propertyLazyInitialization.enabled) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -132,32 +129,35 @@ class PropertyLazyInitLowering(
|
||||
body = irFactory.createBlockBody(
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
buildBodyWithIfGuard(initializers, initializedField)
|
||||
listOf(buildBodyWithIfGuard(initializers, initializedField))
|
||||
)
|
||||
}
|
||||
|
||||
private fun buildBodyWithIfGuard(
|
||||
initializers: Map<IrField, IrExpression>,
|
||||
initializedField: IrField
|
||||
): List<IrStatement> {
|
||||
val statements = initializers
|
||||
.map { (field, expression) ->
|
||||
createIrSetField(field, expression)
|
||||
): IrStatement {
|
||||
val statements = buildList<IrStatement> {
|
||||
val upGuard = createIrSetField(
|
||||
initializedField,
|
||||
JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, true)
|
||||
)
|
||||
add(upGuard)
|
||||
initializers.forEach { (field, expression) ->
|
||||
add(createIrSetField(field, expression))
|
||||
}
|
||||
|
||||
val upGuard = createIrSetField(
|
||||
initializedField,
|
||||
JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, true)
|
||||
)
|
||||
add(JsIrBuilder.buildBlock(irBuiltIns.unitType))
|
||||
}
|
||||
|
||||
return JsIrBuilder.buildIfElse(
|
||||
type = irBuiltIns.unitType,
|
||||
cond = calculator.not(createIrGetField(initializedField)),
|
||||
thenBranch = JsIrBuilder.buildComposite(
|
||||
cond = createIrGetField(initializedField),
|
||||
thenBranch = JsIrBuilder.buildBlock(irBuiltIns.unitType),
|
||||
elseBranch = JsIrBuilder.buildComposite(
|
||||
type = irBuiltIns.unitType,
|
||||
statements = mutableListOf(upGuard).apply { addAll(statements) }
|
||||
statements = statements
|
||||
)
|
||||
).let { listOf(it) }
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@@ -188,14 +188,14 @@ private fun allFieldsInFilePure(fieldToInitializer: Collection<IrExpression>): B
|
||||
}
|
||||
|
||||
class RemoveInitializersForLazyProperties(
|
||||
private val context: JsIrBackendContext
|
||||
private val context: JsCommonBackendContext
|
||||
) : DeclarationTransformer {
|
||||
|
||||
private val fileToInitializerPureness
|
||||
get() = context.fileToInitializerPureness
|
||||
get() = context.propertyLazyInitialization.fileToInitializerPureness
|
||||
|
||||
override fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? {
|
||||
if (!context.propertyLazyInitialization) {
|
||||
if (!context.propertyLazyInitialization.enabled) {
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -235,7 +235,10 @@ class RemoveInitializersForLazyProperties(
|
||||
}
|
||||
}
|
||||
|
||||
private fun calculateFieldToExpression(declarations: Collection<IrDeclaration>, context: JsIrBackendContext): Map<IrField, IrExpression> =
|
||||
private fun calculateFieldToExpression(
|
||||
declarations: Collection<IrDeclaration>,
|
||||
context: JsCommonBackendContext
|
||||
): Map<IrField, IrExpression> =
|
||||
declarations
|
||||
.asSequence()
|
||||
.filter { it.isCompatibleDeclaration(context) }
|
||||
@@ -276,9 +279,9 @@ private fun IrDeclaration.propertyWithPersistentSafe(transform: IrDeclaration.()
|
||||
private fun <T> IrDeclaration.withPersistentSafe(transform: IrDeclaration.() -> T?): T? =
|
||||
transform()
|
||||
|
||||
private fun IrDeclaration.isCompatibleDeclaration(context: JsIrBackendContext) =
|
||||
private fun IrDeclaration.isCompatibleDeclaration(context: JsCommonBackendContext) =
|
||||
correspondingProperty?.let {
|
||||
it.isForLazyInit() && !it.hasAnnotation(context.intrinsics.jsEagerInitializationAnnotationSymbol)
|
||||
it.isForLazyInit() && !it.hasAnnotation(context.propertyLazyInitialization.eagerInitialization)
|
||||
} ?: true && withPersistentSafe { origin in compatibleOrigins } == true
|
||||
|
||||
private val compatibleOrigins = listOf(
|
||||
|
||||
Reference in New Issue
Block a user