JVM IR: inherit some lowerings from ClassLoweringPass

This slightly simplifies code, but has no other immediate benefits. In
the future though, we may end up optimizing all ClassLoweringPass
JVM IR phases by making them traverse only one list of all classes in
the module, instead of traversing the whole IR tree each time.
This commit is contained in:
Alexander Udalov
2023-08-23 21:53:03 +02:00
committed by Space Team
parent 073df585c4
commit 3246b0a6bd
4 changed files with 35 additions and 59 deletions
@@ -5,16 +5,12 @@
package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.util.isAnnotationClass
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
internal val annotationPhase = makeIrFilePhase<JvmBackendContext>(
{ AnnotationLowering() },
@@ -22,13 +18,10 @@ internal val annotationPhase = makeIrFilePhase<JvmBackendContext>(
description = "Remove constructors of annotation classes"
)
private class AnnotationLowering : FileLoweringPass, IrElementTransformerVoid() {
override fun lower(irFile: IrFile) = irFile.transformChildrenVoid(this)
override fun visitClass(declaration: IrClass): IrStatement =
declaration.transformPostfix {
if (isAnnotationClass) {
declarations.removeIf { it is IrConstructor }
}
private class AnnotationLowering : ClassLoweringPass {
override fun lower(irClass: IrClass) {
if (irClass.isAnnotationClass) {
irClass.declarations.removeIf { it is IrConstructor }
}
}
}
@@ -5,7 +5,7 @@
package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.lower.SpecialMethodWithDefaultInfo
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irNot
@@ -18,7 +18,6 @@ import org.jetbrains.kotlin.backend.jvm.ir.*
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.builders.declarations.addFunction
import org.jetbrains.kotlin.ir.declarations.*
@@ -30,7 +29,6 @@ import org.jetbrains.kotlin.ir.types.isNullable
import org.jetbrains.kotlin.ir.types.isPrimitiveType
import org.jetbrains.kotlin.ir.types.makeNullable
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.org.objectweb.asm.Type
@@ -118,7 +116,7 @@ internal val bridgePhase = makeIrFilePhase(
prerequisite = setOf(jvmValueClassPhase, inheritedDefaultMethodsOnClassesPhase)
)
internal class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass, IrElementTransformerVoid() {
internal class BridgeLowering(val context: JvmBackendContext) : ClassLoweringPass {
// Represents a synthetic bridge to `overridden` with a precomputed signature
private class Bridge(
val overridden: IrSimpleFunction,
@@ -126,27 +124,21 @@ internal class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass
val overriddenSymbols: MutableList<IrSimpleFunctionSymbol> = mutableListOf()
)
override fun lower(irFile: IrFile) {
irFile.transformChildrenVoid()
}
override fun lower(irClass: IrClass) {
// Bridges in DefaultImpls classes are handled in InterfaceLowering.
if (irClass.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS || irClass.isAnnotationClass) return
override fun visitClass(declaration: IrClass): IrStatement {
// Bridges in DefaultImpl classes are handled in InterfaceLowering.
if (declaration.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS || declaration.isAnnotationClass)
return super.visitClass(declaration)
val bridgeTargets = irClass.functions.filterTo(SmartList()) { it.isPotentialBridgeTarget() }
if (bridgeTargets.isEmpty()) return
val bridgeTargets = declaration.functions.filterTo(SmartList()) { it.isPotentialBridgeTarget() }
if (bridgeTargets.isEmpty())
return super.visitClass(declaration)
bridgeTargets.forEach { createBridges(irClass, it) }
bridgeTargets.forEach { createBridges(declaration, it) }
if (declaration.isSingleFieldValueClass) {
if (irClass.isSingleFieldValueClass) {
// Inline class (implementing 'MutableCollection<T>', where T is Int or an inline class mapped to Int)
// can contain a static replacement for a function 'remove', which forces value parameter boxing
// in order to avoid signature clash with 'remove(int)' method in 'java.util.List'.
// We should rewrite this static replacement as well ('remove' function itself is handled during special bridge processing).
val remove = declaration.functions.find {
val remove = irClass.functions.find {
val original = context.inlineClassReplacements.originalFunctionForStaticReplacement[it]
original != null && context.defaultMethodSignatureMapper.shouldBoxSingleValueParameterForSpecialCaseOfRemove(original)
}
@@ -156,8 +148,6 @@ internal class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass
}
}
}
return super.visitClass(declaration)
}
private fun IrSimpleFunction.isPotentialBridgeTarget(): Boolean {
@@ -28,7 +28,9 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
import org.jetbrains.kotlin.ir.expressions.putArgument
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
internal val inheritedDefaultMethodsOnClassesPhase = makeIrFilePhase(
::InheritedDefaultMethodsOnClassesLowering,
@@ -123,25 +125,24 @@ internal val replaceDefaultImplsOverriddenSymbolsPhase = makeIrFilePhase(
description = "Replace overridden symbols for methods inherited from interfaces to classes"
)
private class ReplaceDefaultImplsOverriddenSymbols(private val context: JvmBackendContext) : FileLoweringPass, IrElementVisitorVoid {
override fun lower(irFile: IrFile) {
irFile.acceptVoid(this)
}
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
private class ReplaceDefaultImplsOverriddenSymbols(private val context: JvmBackendContext) : ClassLoweringPass {
override fun lower(irClass: IrClass) {
for (declaration in irClass.declarations) {
if (declaration is IrSimpleFunction) {
visitSimpleFunction(declaration)
}
}
}
// Functions introduced by InheritedDefaultMethodsOnClassesLowering may be inherited lower in the hierarchy.
// Here we use the same logic as the delegation itself (`getTargetForRedirection`) to determine
// if the overridden symbol has been, or will be, replaced and patch it accordingly.
override fun visitSimpleFunction(declaration: IrSimpleFunction) {
fun visitSimpleFunction(declaration: IrSimpleFunction) {
declaration.overriddenSymbols = declaration.overriddenSymbols.map { symbol ->
if (symbol.owner.findInterfaceImplementation(context.config.jvmDefaultMode) != null)
context.cachedDeclarations.getDefaultImplsRedirection(symbol.owner).symbol
else symbol
}
super.visitSimpleFunction(declaration)
}
}
@@ -5,15 +5,13 @@
package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.ir.createJvmIrBuilder
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.builders.irCall
import org.jetbrains.kotlin.ir.builders.irExprBody
import org.jetbrains.kotlin.ir.builders.irGetField
@@ -31,23 +29,17 @@ internal val objectClassPhase = makeIrFilePhase(
description = "Handle object classes"
)
private class ObjectClassLowering(val context: JvmBackendContext) : IrElementTransformerVoidWithContext(), FileLoweringPass {
private var pendingTransformations = mutableListOf<Function0<Unit>>()
private class ObjectClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
private val pendingTransformations = mutableListOf<Function0<Unit>>()
override fun lower(irFile: IrFile) {
irFile.accept(this, null)
pendingTransformations.forEach { it() }
super.lower(irFile)
for (transformation in pendingTransformations) {
transformation.invoke()
}
}
override fun visitClassNew(declaration: IrClass): IrStatement {
process(declaration)
return super.visitClassNew(declaration)
}
private fun process(irClass: IrClass) {
override fun lower(irClass: IrClass) {
if (!irClass.isObject) return
val publicInstanceField = context.cachedDeclarations.getFieldForObjectInstance(irClass)