IR: remove the use of lazy from LocalDeclarationsLowering
This commit is contained in:
+40
-49
@@ -17,14 +17,15 @@ import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
|||||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
|
||||||
import org.jetbrains.kotlin.ir.*
|
import org.jetbrains.kotlin.ir.*
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.buildConstructor
|
import org.jetbrains.kotlin.ir.builders.declarations.buildConstructor
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.buildField
|
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.buildValueParameter
|
import org.jetbrains.kotlin.ir.builders.declarations.buildValueParameter
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
@@ -165,6 +166,14 @@ class LocalDeclarationsLowering(
|
|||||||
override lateinit var transformedDeclaration: IrConstructor
|
override lateinit var transformedDeclaration: IrConstructor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class PotentiallyUnusedField {
|
||||||
|
var symbolIfUsed: IrFieldSymbol? = null
|
||||||
|
private set
|
||||||
|
|
||||||
|
val symbol: IrFieldSymbol
|
||||||
|
get() = symbolIfUsed ?: IrFieldSymbolImpl().also { symbolIfUsed = it }
|
||||||
|
}
|
||||||
|
|
||||||
private inner class LocalClassContext(
|
private inner class LocalClassContext(
|
||||||
val declaration: IrClass,
|
val declaration: IrClass,
|
||||||
val inInlineFunctionScope: Boolean,
|
val inInlineFunctionScope: Boolean,
|
||||||
@@ -174,7 +183,7 @@ class LocalDeclarationsLowering(
|
|||||||
|
|
||||||
// NOTE: This map is iterated over in `rewriteClassMembers` and we're relying on
|
// NOTE: This map is iterated over in `rewriteClassMembers` and we're relying on
|
||||||
// the deterministic iteration order that `mutableMapOf` provides.
|
// the deterministic iteration order that `mutableMapOf` provides.
|
||||||
val capturedValueToField: MutableMap<IrValueDeclaration, Lazy<IrField>> = mutableMapOf()
|
val capturedValueToField: MutableMap<IrValueDeclaration, PotentiallyUnusedField> = mutableMapOf()
|
||||||
|
|
||||||
override fun irGet(startOffset: Int, endOffset: Int, valueDeclaration: IrValueDeclaration): IrExpression? {
|
override fun irGet(startOffset: Int, endOffset: Int, valueDeclaration: IrValueDeclaration): IrExpression? {
|
||||||
// On the JVM backend, `AnonymousObjectTransformer` in the bytecode inliner uses field assignment
|
// On the JVM backend, `AnonymousObjectTransformer` in the bytecode inliner uses field assignment
|
||||||
@@ -190,11 +199,10 @@ class LocalDeclarationsLowering(
|
|||||||
constructorContext?.irGet(startOffset, endOffset, valueDeclaration)?.let { return it }
|
constructorContext?.irGet(startOffset, endOffset, valueDeclaration)?.let { return it }
|
||||||
}
|
}
|
||||||
|
|
||||||
val field = capturedValueToField[valueDeclaration]?.value ?: return null
|
val field = capturedValueToField[valueDeclaration] ?: return null
|
||||||
|
|
||||||
val receiver = declaration.thisReceiver!!
|
val receiver = declaration.thisReceiver!!
|
||||||
return IrGetFieldImpl(
|
return IrGetFieldImpl(
|
||||||
startOffset, endOffset, field.symbol, field.type,
|
startOffset, endOffset, field.symbol, valueDeclaration.type,
|
||||||
receiver = IrGetValueImpl(startOffset, endOffset, receiver.type, receiver.symbol)
|
receiver = IrGetValueImpl(startOffset, endOffset, receiver.type, receiver.symbol)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -205,12 +213,12 @@ class LocalDeclarationsLowering(
|
|||||||
|
|
||||||
private class LocalClassMemberContext(val member: IrDeclaration, val classContext: LocalClassContext) : LocalContext() {
|
private class LocalClassMemberContext(val member: IrDeclaration, val classContext: LocalClassContext) : LocalContext() {
|
||||||
override fun irGet(startOffset: Int, endOffset: Int, valueDeclaration: IrValueDeclaration): IrExpression? {
|
override fun irGet(startOffset: Int, endOffset: Int, valueDeclaration: IrValueDeclaration): IrExpression? {
|
||||||
val field = classContext.capturedValueToField[valueDeclaration]?.value ?: return null
|
val field = classContext.capturedValueToField[valueDeclaration] ?: return null
|
||||||
// This lowering does not process accesses to outer `this`.
|
// This lowering does not process accesses to outer `this`.
|
||||||
val receiver = (if (member is IrFunction) member.dispatchReceiverParameter else classContext.declaration.thisReceiver)
|
val receiver = (if (member is IrFunction) member.dispatchReceiverParameter else classContext.declaration.thisReceiver)
|
||||||
?: error("No dispatch receiver parameter for ${member.render()}")
|
?: error("No dispatch receiver parameter for ${member.render()}")
|
||||||
return IrGetFieldImpl(
|
return IrGetFieldImpl(
|
||||||
startOffset, endOffset, field.symbol, field.type,
|
startOffset, endOffset, field.symbol, valueDeclaration.type,
|
||||||
receiver = IrGetValueImpl(startOffset, endOffset, receiver.type, receiver.symbol)
|
receiver = IrGetValueImpl(startOffset, endOffset, receiver.type, receiver.symbol)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -500,7 +508,7 @@ class LocalDeclarationsLowering(
|
|||||||
|
|
||||||
assert(constructorsCallingSuper.any()) { "Expected at least one constructor calling super; class: $irClass" }
|
assert(constructorsCallingSuper.any()) { "Expected at least one constructor calling super; class: $irClass" }
|
||||||
|
|
||||||
val usedCaptureFields = localClassContext.capturedValueToField.values.mapNotNull { if (it.isInitialized()) it.value else null }
|
val usedCaptureFields = createFieldsForCapturedValues(localClassContext)
|
||||||
irClass.declarations += usedCaptureFields
|
irClass.declarations += usedCaptureFields
|
||||||
|
|
||||||
context.mapping.capturedFields[irClass] =
|
context.mapping.capturedFields[irClass] =
|
||||||
@@ -515,9 +523,9 @@ class LocalDeclarationsLowering(
|
|||||||
blockBody.statements.addAll(
|
blockBody.statements.addAll(
|
||||||
0,
|
0,
|
||||||
localClassContext.capturedValueToField.mapNotNull { (capturedValue, field) ->
|
localClassContext.capturedValueToField.mapNotNull { (capturedValue, field) ->
|
||||||
if (!field.isInitialized()) return@mapNotNull null
|
val symbol = field.symbolIfUsed ?: return@mapNotNull null
|
||||||
IrSetFieldImpl(
|
IrSetFieldImpl(
|
||||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, field.value.symbol,
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol,
|
||||||
IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irClass.thisReceiver!!.symbol),
|
IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irClass.thisReceiver!!.symbol),
|
||||||
constructorContext.irGet(UNDEFINED_OFFSET, UNDEFINED_OFFSET, capturedValue)!!,
|
constructorContext.irGet(UNDEFINED_OFFSET, UNDEFINED_OFFSET, capturedValue)!!,
|
||||||
context.irBuiltIns.unitType,
|
context.irBuiltIns.unitType,
|
||||||
@@ -582,9 +590,10 @@ class LocalDeclarationsLowering(
|
|||||||
}
|
}
|
||||||
|
|
||||||
localClasses.values.forEach {
|
localClasses.values.forEach {
|
||||||
val localClassVisibility = visibilityPolicy.forClass(it.declaration, it.inInlineFunctionScope)
|
it.declaration.visibility = visibilityPolicy.forClass(it.declaration, it.inInlineFunctionScope)
|
||||||
it.declaration.visibility = localClassVisibility
|
it.closure.capturedValues.associateTo(it.capturedValueToField) { capturedValue ->
|
||||||
createFieldsForCapturedValues(it)
|
capturedValue.owner to PotentiallyUnusedField()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
localClassConstructors.values.forEach {
|
localClassConstructors.values.forEach {
|
||||||
@@ -766,44 +775,26 @@ class LocalDeclarationsLowering(
|
|||||||
context.mapping.capturedConstructors[oldDeclaration] = newDeclaration
|
context.mapping.capturedConstructors[oldDeclaration] = newDeclaration
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createFieldForCapturedValue(
|
private fun createFieldsForCapturedValues(localClassContext: LocalClassContext): List<IrField> {
|
||||||
startOffset: Int,
|
|
||||||
endOffset: Int,
|
|
||||||
name: Name,
|
|
||||||
visibility: DescriptorVisibility,
|
|
||||||
parent: IrClass,
|
|
||||||
fieldType: IrType,
|
|
||||||
isCrossinline: Boolean
|
|
||||||
): IrField =
|
|
||||||
context.irFactory.buildField {
|
|
||||||
this.startOffset = startOffset
|
|
||||||
this.endOffset = endOffset
|
|
||||||
this.origin =
|
|
||||||
if (isCrossinline) DECLARATION_ORIGIN_FIELD_FOR_CROSSINLINE_CAPTURED_VALUE
|
|
||||||
else DECLARATION_ORIGIN_FIELD_FOR_CAPTURED_VALUE
|
|
||||||
this.name = name
|
|
||||||
this.type = fieldType
|
|
||||||
this.visibility = visibility
|
|
||||||
this.isFinal = true
|
|
||||||
}.also {
|
|
||||||
it.parent = parent
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createFieldsForCapturedValues(localClassContext: LocalClassContext) {
|
|
||||||
val classDeclaration = localClassContext.declaration
|
val classDeclaration = localClassContext.declaration
|
||||||
val generatedNames = mutableSetOf<String>()
|
val generatedNames = mutableSetOf<String>()
|
||||||
localClassContext.closure.capturedValues.forEach { capturedValue ->
|
return localClassContext.capturedValueToField.mapNotNull { (capturedValue, field) ->
|
||||||
val owner = capturedValue.owner
|
val symbol = field.symbolIfUsed ?: return@mapNotNull null
|
||||||
localClassContext.capturedValueToField[owner] = lazy(LazyThreadSafetyMode.NONE) {
|
val origin = if (capturedValue is IrValueParameter && capturedValue.isCrossinline)
|
||||||
createFieldForCapturedValue(
|
DECLARATION_ORIGIN_FIELD_FOR_CROSSINLINE_CAPTURED_VALUE
|
||||||
classDeclaration.startOffset,
|
else
|
||||||
classDeclaration.endOffset,
|
DECLARATION_ORIGIN_FIELD_FOR_CAPTURED_VALUE
|
||||||
suggestNameForCapturedValue(owner, generatedNames),
|
context.irFactory.createField(
|
||||||
visibilityPolicy.forCapturedField(capturedValue),
|
classDeclaration.startOffset,
|
||||||
classDeclaration,
|
classDeclaration.endOffset,
|
||||||
owner.type,
|
origin,
|
||||||
owner is IrValueParameter && owner.isCrossinline
|
symbol,
|
||||||
)
|
suggestNameForCapturedValue(capturedValue, generatedNames),
|
||||||
|
capturedValue.type,
|
||||||
|
visibilityPolicy.forCapturedField(capturedValue.symbol),
|
||||||
|
isFinal = true, isExternal = false, isStatic = false,
|
||||||
|
).also {
|
||||||
|
it.parent = classDeclaration
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user