[JVM IR] Drop ConstLowering
It basically can be replaced with IR interpreter. The only half-hack was required in `PropertyReferenceLowering`. Const interpreter is running before it, so we can't optimize some calls on const properties that appear after this lowering. Solution is to inline constants manually during property reference lowering.
This commit is contained in:
@@ -369,7 +369,6 @@ private val jvmFilePhases = listOf(
|
||||
singletonOrConstantDelegationPhase,
|
||||
propertyReferencePhase,
|
||||
arrayConstructorPhase,
|
||||
constPhase1,
|
||||
|
||||
// TODO: merge the next three phases together, as visitors behave incorrectly between them
|
||||
// (backing fields moved out of companion objects are reachable by two paths):
|
||||
@@ -422,7 +421,6 @@ private val jvmFilePhases = listOf(
|
||||
|
||||
tailCallOptimizationPhase,
|
||||
addContinuationPhase,
|
||||
constPhase2, // handle const properties in default arguments of "original" suspend funs
|
||||
|
||||
innerClassesPhase,
|
||||
innerClassesMemberBodyPhase,
|
||||
|
||||
-45
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.backend.jvm.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.lower.InlineConstTransformer
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.constantValue
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.incremental.components.InlineConstTracker
|
||||
import org.jetbrains.kotlin.ir.declarations.IrField
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConst
|
||||
import org.jetbrains.kotlin.ir.interpreter.transformer.reportOnIr
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
|
||||
internal val constPhase1 = makeIrFilePhase(
|
||||
::ConstLowering,
|
||||
name = "Const1",
|
||||
description = "Substitute calls to const properties with constant values"
|
||||
)
|
||||
|
||||
internal val constPhase2 = makeIrFilePhase(
|
||||
::ConstLowering,
|
||||
name = "Const2",
|
||||
description = "Substitute calls to const properties with constant values"
|
||||
)
|
||||
|
||||
class ConstLowering(val context: JvmBackendContext) : FileLoweringPass {
|
||||
val inlineConstTracker =
|
||||
context.state.configuration[CommonConfigurationKeys.INLINE_CONST_TRACKER]
|
||||
|
||||
override fun lower(irFile: IrFile) = irFile.transformChildrenVoid(JvmInlineConstTransformer(irFile, inlineConstTracker))
|
||||
}
|
||||
|
||||
private class JvmInlineConstTransformer(val irFile: IrFile, val inlineConstTracker: InlineConstTracker?) : InlineConstTransformer() {
|
||||
override val IrField.constantInitializer get() = constantValue()
|
||||
override fun reportInlineConst(field: IrField, value: IrConst<*>) {
|
||||
inlineConstTracker?.reportOnIr(irFile, field, value)
|
||||
}
|
||||
}
|
||||
+13
@@ -65,6 +65,17 @@ internal class PropertyReferenceLowering(val context: JvmBackendContext) : IrEle
|
||||
private val IrMemberAccessExpression<*>.field: IrFieldSymbol?
|
||||
get() = (this as? IrPropertyReference)?.field
|
||||
|
||||
private val IrMemberAccessExpression<*>.constInitializer: IrExpression?
|
||||
get() {
|
||||
if (this !is IrPropertyReference) return null
|
||||
val constPropertyField = if (field == null) {
|
||||
symbol.owner.takeIf { it.isConst }?.backingField
|
||||
} else {
|
||||
field!!.owner.takeIf { it.isFinal && it.isStatic }
|
||||
}
|
||||
return constPropertyField?.initializer?.expression?.shallowCopyOrNull()
|
||||
}
|
||||
|
||||
private val arrayItemGetter =
|
||||
context.ir.symbols.array.owner.functions.single { it.name.asString() == "get" }
|
||||
|
||||
@@ -441,6 +452,7 @@ internal class PropertyReferenceLowering(val context: JvmBackendContext) : IrEle
|
||||
|
||||
expression.getter?.owner?.let { getter ->
|
||||
referenceClass.addOverride(get!!) { arguments ->
|
||||
expression.constInitializer?.let { return@addOverride it }
|
||||
irGet(getter.returnType, null, getter.symbol).apply {
|
||||
setCallArguments(this, arguments)
|
||||
}
|
||||
@@ -469,6 +481,7 @@ internal class PropertyReferenceLowering(val context: JvmBackendContext) : IrEle
|
||||
}
|
||||
|
||||
referenceClass.addOverride(get!!) { arguments ->
|
||||
expression.constInitializer?.let { return@addOverride it }
|
||||
irGetField(fieldReceiver(arguments), field)
|
||||
}
|
||||
|
||||
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.interpreter.preprocessor
|
||||
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.IrField
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetObjectValueImpl
|
||||
import org.jetbrains.kotlin.ir.types.classOrFail
|
||||
|
||||
class IrInterpreterConstGetterPreprocessor : IrInterpreterPreprocessor {
|
||||
override fun visitFunction(declaration: IrFunction, data: IrInterpreterPreprocessorData): IrStatement {
|
||||
// It is useless to visit default accessor, we probably want to leave code there as it is
|
||||
if (declaration.origin == IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR) return declaration
|
||||
return super.visitFunction(declaration, data)
|
||||
}
|
||||
|
||||
override fun visitCall(expression: IrCall, data: IrInterpreterPreprocessorData): IrElement {
|
||||
val function = (expression.symbol.owner as? IrSimpleFunction) ?: return super.visitCall(expression, data)
|
||||
val field = function.correspondingPropertySymbol?.owner?.backingField ?: return super.visitCall(expression, data)
|
||||
return expression.lowerConstRead(field, data) ?: super.visitCall(expression, data)
|
||||
}
|
||||
|
||||
override fun visitGetField(expression: IrGetField, data: IrInterpreterPreprocessorData): IrExpression {
|
||||
return expression.lowerConstRead(expression.symbol.owner, data) ?: super.visitGetField(expression, data)
|
||||
}
|
||||
|
||||
private fun IrExpression.lowerConstRead(field: IrField, data: IrInterpreterPreprocessorData): IrExpression? {
|
||||
val receiver = when (this) {
|
||||
is IrCall -> dispatchReceiver
|
||||
is IrGetField -> receiver
|
||||
else -> return null
|
||||
}
|
||||
|
||||
if (receiver == null || !field.hasConstantValue()) return null
|
||||
|
||||
transformChildren(this@IrInterpreterConstGetterPreprocessor, data)
|
||||
|
||||
val getObject = IrGetObjectValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, receiver.type, receiver.type.classOrFail)
|
||||
when (this) {
|
||||
is IrCall -> this.dispatchReceiver = getObject
|
||||
is IrGetField -> this.receiver = getObject
|
||||
}
|
||||
|
||||
return if (receiver.shouldDropConstReceiver()) {
|
||||
this
|
||||
} else {
|
||||
IrCompositeImpl(startOffset, endOffset, this.type, null, listOf(receiver, this))
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrExpression.shouldDropConstReceiver(): Boolean {
|
||||
return this is IrGetValue || this is IrGetObjectValue
|
||||
}
|
||||
|
||||
fun IrField.hasConstantValue(): Boolean {
|
||||
val implicitConst = isFinal && isStatic && origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB && initializer != null
|
||||
return implicitConst || correspondingPropertySymbol?.owner?.isConst == true
|
||||
}
|
||||
}
|
||||
-2
@@ -5,7 +5,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.interpreter.preprocessor
|
||||
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
@@ -18,7 +17,6 @@ import org.jetbrains.kotlin.ir.expressions.IrGetValue
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
|
||||
import org.jetbrains.kotlin.ir.interpreter.property
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.classFqName
|
||||
import org.jetbrains.kotlin.ir.types.typeOrNull
|
||||
import org.jetbrains.kotlin.ir.types.typeWith
|
||||
import org.jetbrains.kotlin.ir.util.isKFunction
|
||||
|
||||
+2
-1
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
|
||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreterConfiguration
|
||||
import org.jetbrains.kotlin.ir.interpreter.checker.*
|
||||
import org.jetbrains.kotlin.ir.interpreter.preprocessor.IrInterpreterConstGetterPreprocessor
|
||||
import org.jetbrains.kotlin.ir.interpreter.preprocessor.IrInterpreterKCallableNamePreprocessor
|
||||
import org.jetbrains.kotlin.ir.interpreter.preprocessor.IrInterpreterPreprocessorData
|
||||
import org.jetbrains.kotlin.ir.interpreter.property
|
||||
@@ -72,7 +73,7 @@ fun IrFile.preprocessForConstTransformer(
|
||||
interpreter: IrInterpreter,
|
||||
mode: EvaluationMode,
|
||||
): IrFile {
|
||||
val preprocessors = setOf(IrInterpreterKCallableNamePreprocessor())
|
||||
val preprocessors = setOf(IrInterpreterKCallableNamePreprocessor(), IrInterpreterConstGetterPreprocessor())
|
||||
val preprocessedFile = preprocessors.fold(this) { file, preprocessor ->
|
||||
preprocessor.preprocess(file, IrInterpreterPreprocessorData(mode, interpreter.irBuiltIns))
|
||||
}
|
||||
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
// IGNORE_BACKEND: NATIVE
|
||||
// WITH_STDLIB
|
||||
// WITH_STDLIB
|
||||
// WITH_REFLECT
|
||||
|
||||
// MODULE: lib
|
||||
|
||||
Reference in New Issue
Block a user