JVM_IR: avoid recursive constructor calls in ClassCodegen
This commit is contained in:
committed by
teamcityserver
parent
570e20696c
commit
2f697e9195
+14
-10
@@ -69,8 +69,17 @@ class ClassCodegen private constructor(
|
|||||||
val context: JvmBackendContext,
|
val context: JvmBackendContext,
|
||||||
private val parentFunction: IrFunction?,
|
private val parentFunction: IrFunction?,
|
||||||
) : InnerClassConsumer {
|
) : InnerClassConsumer {
|
||||||
private val parentClassCodegen = (parentFunction?.parentAsClass ?: irClass.parent as? IrClass)?.let { getOrCreate(it, context) }
|
// We need to avoid recursive calls to getOrCreate() from within the constructor to prevent lockups
|
||||||
private val withinInline: Boolean = parentClassCodegen?.withinInline == true || parentFunction?.isInline == true
|
// in ConcurrentHashMap context.classCodegens.
|
||||||
|
private val parentClassCodegen by lazy {
|
||||||
|
(parentFunction?.parentAsClass ?: irClass.parent as? IrClass)?.let { getOrCreate(it, context) }
|
||||||
|
}
|
||||||
|
private val withinInline: Boolean by lazy { parentClassCodegen?.withinInline == true || parentFunction?.isInline == true }
|
||||||
|
private val metadataSerializer: MetadataSerializer by lazy {
|
||||||
|
context.backendExtension.createSerializer(
|
||||||
|
context, irClass, type, visitor.serializationBindings, parentClassCodegen?.metadataSerializer
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private val state get() = context.state
|
private val state get() = context.state
|
||||||
private val typeMapper get() = context.typeMapper
|
private val typeMapper get() = context.typeMapper
|
||||||
@@ -225,11 +234,6 @@ class ClassCodegen private constructor(
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private val metadataSerializer: MetadataSerializer =
|
|
||||||
context.backendExtension.createSerializer(
|
|
||||||
context, irClass, type, visitor.serializationBindings, parentClassCodegen?.metadataSerializer
|
|
||||||
)
|
|
||||||
|
|
||||||
private fun generateKotlinMetadataAnnotation() {
|
private fun generateKotlinMetadataAnnotation() {
|
||||||
val facadeClassName = context.multifileFacadeForPart[irClass.attributeOwnerId]
|
val facadeClassName = context.multifileFacadeForPart[irClass.attributeOwnerId]
|
||||||
val metadata = irClass.metadata
|
val metadata = irClass.metadata
|
||||||
@@ -437,14 +441,14 @@ class ClassCodegen private constructor(
|
|||||||
if (parentClassCodegen != null) {
|
if (parentClassCodegen != null) {
|
||||||
// In case there's no primary constructor, it's unclear which constructor should be the enclosing one, so we select the first.
|
// In case there's no primary constructor, it's unclear which constructor should be the enclosing one, so we select the first.
|
||||||
val enclosingFunction = if (irClass.attributeOwnerId in context.isEnclosedInConstructor) {
|
val enclosingFunction = if (irClass.attributeOwnerId in context.isEnclosedInConstructor) {
|
||||||
val containerClass = parentClassCodegen.irClass
|
val containerClass = parentClassCodegen!!.irClass
|
||||||
containerClass.primaryConstructor
|
containerClass.primaryConstructor
|
||||||
?: containerClass.declarations.firstIsInstanceOrNull<IrConstructor>()
|
?: containerClass.declarations.firstIsInstanceOrNull<IrConstructor>()
|
||||||
?: error("Class in a non-static initializer found, but container has no constructors: ${containerClass.render()}")
|
?: error("Class in a non-static initializer found, but container has no constructors: ${containerClass.render()}")
|
||||||
} else parentFunction
|
} else parentFunction
|
||||||
if (enclosingFunction != null || irClass.isAnonymousInnerClass) {
|
if (enclosingFunction != null || irClass.isAnonymousInnerClass) {
|
||||||
val method = enclosingFunction?.let(context.methodSignatureMapper::mapAsmMethod)
|
val method = enclosingFunction?.let(context.methodSignatureMapper::mapAsmMethod)
|
||||||
visitor.visitOuterClass(parentClassCodegen.type.internalName, method?.name, method?.descriptor)
|
visitor.visitOuterClass(parentClassCodegen!!.type.internalName, method?.name, method?.descriptor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -511,7 +515,7 @@ class ClassCodegen private constructor(
|
|||||||
it.origin == JvmLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER
|
it.origin == JvmLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER
|
||||||
},
|
},
|
||||||
): ClassCodegen =
|
): ClassCodegen =
|
||||||
context.classCodegens.getOrPut(irClass) { ClassCodegen(irClass, context, parentFunction) }.also {
|
context.classCodegens.computeIfAbsent(irClass) { ClassCodegen(irClass, context, parentFunction) }.also {
|
||||||
assert(parentFunction == null || it.parentFunction == parentFunction) {
|
assert(parentFunction == null || it.parentFunction == parentFunction) {
|
||||||
"inconsistent parent function for ${irClass.render()}:\n" +
|
"inconsistent parent function for ${irClass.render()}:\n" +
|
||||||
"New: ${parentFunction!!.render()}\n" +
|
"New: ${parentFunction!!.render()}\n" +
|
||||||
|
|||||||
Reference in New Issue
Block a user