Revert "JVM_IR: Use direct field access instead of calling certain accessors."
This reverts commit 62f9e7a810.
This commit is contained in:
@@ -314,9 +314,10 @@ private val jvmFilePhases =
|
||||
staticDefaultFunctionPhase then
|
||||
syntheticAccessorPhase then
|
||||
|
||||
|
||||
jvmArgumentNullabilityAssertions then
|
||||
toArrayPhase then
|
||||
jvmOptimizationLoweringPhase then
|
||||
jvmBuiltinOptimizationLoweringPhase then
|
||||
additionalClassAnnotationPhase then
|
||||
typeOperatorLowering then
|
||||
replaceKFunctionInvokeWithFunctionInvokePhase then
|
||||
|
||||
+21
-84
@@ -6,17 +6,15 @@
|
||||
package org.jetbrains.kotlin.backend.jvm.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.lower.irBlock
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.unboxInlineClass
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.Not
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.builders.irGetField
|
||||
import org.jetbrains.kotlin.ir.builders.irSetField
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
@@ -26,15 +24,16 @@ import org.jetbrains.kotlin.ir.types.isNullableAny
|
||||
import org.jetbrains.kotlin.ir.types.isPrimitiveType
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
|
||||
internal val jvmOptimizationLoweringPhase = makeIrFilePhase(
|
||||
::JvmOptimizationLowering,
|
||||
internal val jvmBuiltinOptimizationLoweringPhase = makeIrFilePhase(
|
||||
::JvmBuiltinOptimizationLowering,
|
||||
name = "JvmBuiltinOptimizationLowering",
|
||||
description = "Optimize code for JVM code generation"
|
||||
description = "Optimize builtin calls for JVM code generation"
|
||||
)
|
||||
|
||||
class JvmOptimizationLowering(val context: JvmBackendContext) : FileLoweringPass {
|
||||
class JvmBuiltinOptimizationLowering(val context: JvmBackendContext) : FileLoweringPass {
|
||||
|
||||
companion object {
|
||||
fun isNegation(expression: IrExpression, context: JvmBackendContext): Boolean =
|
||||
@@ -72,38 +71,9 @@ class JvmOptimizationLowering(val context: JvmBackendContext) : FileLoweringPass
|
||||
}
|
||||
|
||||
override fun lower(irFile: IrFile) {
|
||||
val transformer = object : IrElementTransformer<IrClass?> {
|
||||
|
||||
// Thread the current class through the transformations in order to replace
|
||||
// final default accessor calls with direct backing field access when
|
||||
// possible.
|
||||
override fun visitClass(declaration: IrClass, data: IrClass?): IrStatement {
|
||||
declaration.transformChildren(this, declaration)
|
||||
return declaration
|
||||
}
|
||||
|
||||
// For some functions, we clear the current class field since the code could end up
|
||||
// in another class then the one it is nested under in the IR.
|
||||
// TODO: Loosen this up for local functions for lambdas passed as an inline lambda
|
||||
// argument to an inline function. In that case the code does end up in the current class.
|
||||
override fun visitFunction(declaration: IrFunction, currentClass: IrClass?): IrStatement {
|
||||
val codeMightBeGeneratedInDifferentClass = declaration.isSuspend ||
|
||||
declaration.isInline ||
|
||||
declaration.origin == IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA
|
||||
declaration.transformChildren(this, currentClass.takeUnless { codeMightBeGeneratedInDifferentClass })
|
||||
return declaration
|
||||
}
|
||||
|
||||
override fun visitCall(expression: IrCall, currentClass: IrClass?): IrExpression {
|
||||
expression.transformChildren(this, currentClass)
|
||||
|
||||
if (expression.symbol.owner.origin == IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR) {
|
||||
if (currentClass == null) return expression
|
||||
val simpleFunction = (expression.symbol.owner as? IrSimpleFunction) ?: return expression
|
||||
val property = simpleFunction.correspondingPropertySymbol?.owner ?: return expression
|
||||
if (property.isLateinit) return expression
|
||||
return optimizePropertyAccess(expression, simpleFunction, property, currentClass)
|
||||
}
|
||||
irFile.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||
override fun visitCall(expression: IrCall): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
if (isNegation(expression, context) && isNegation(expression.dispatchReceiver!!, context)) {
|
||||
return (expression.dispatchReceiver as IrCall).dispatchReceiver!!
|
||||
@@ -145,41 +115,9 @@ class JvmOptimizationLowering(val context: JvmBackendContext) : FileLoweringPass
|
||||
return expression
|
||||
}
|
||||
|
||||
private fun optimizePropertyAccess(
|
||||
expression: IrCall,
|
||||
accessor: IrSimpleFunction,
|
||||
property: IrProperty,
|
||||
currentClass: IrClass
|
||||
): IrExpression {
|
||||
if (accessor.parentAsClass == currentClass &&
|
||||
property.backingField?.parentAsClass == currentClass &&
|
||||
accessor.modality == Modality.FINAL &&
|
||||
!accessor.isExternal
|
||||
) {
|
||||
val backingField = property.backingField!!
|
||||
val receiver = expression.dispatchReceiver
|
||||
return context.createIrBuilder(expression.symbol, expression.startOffset, expression.endOffset).irBlock(expression) {
|
||||
if (backingField.isStatic && receiver != null) {
|
||||
// If the field is static, evaluate the receiver for potential side effects.
|
||||
+receiver.coerceToUnit(context.irBuiltIns)
|
||||
}
|
||||
if (accessor.valueParameters.size > 0) {
|
||||
+irSetField(
|
||||
receiver.takeUnless { backingField.isStatic },
|
||||
backingField,
|
||||
expression.getValueArgument(expression.valueArgumentsCount - 1)!!
|
||||
)
|
||||
} else {
|
||||
+irGetField(receiver.takeUnless { backingField.isStatic }, backingField)
|
||||
}
|
||||
}
|
||||
}
|
||||
return expression
|
||||
}
|
||||
|
||||
override fun visitWhen(expression: IrWhen, currentClass: IrClass?): IrExpression {
|
||||
override fun visitWhen(expression: IrWhen): IrExpression {
|
||||
val isCompilerGenerated = expression.origin == null
|
||||
expression.transformChildren(this, currentClass)
|
||||
expression.transformChildrenVoid(this)
|
||||
// Remove all branches with constant false condition.
|
||||
expression.branches.removeIf {
|
||||
it.condition.isFalseConst() && isCompilerGenerated
|
||||
@@ -321,19 +259,19 @@ class JvmOptimizationLowering(val context: JvmBackendContext) : FileLoweringPass
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitBlockBody(body: IrBlockBody, currentClass: IrClass?): IrBody {
|
||||
body.transformChildren(this, currentClass)
|
||||
override fun visitBlockBody(body: IrBlockBody): IrBody {
|
||||
body.transformChildrenVoid(this)
|
||||
removeUnnecessaryTemporaryVariables(body.statements)
|
||||
return body
|
||||
}
|
||||
|
||||
override fun visitContainerExpression(expression: IrContainerExpression, currentClass: IrClass?): IrExpression {
|
||||
expression.transformChildren(this, currentClass)
|
||||
override fun visitContainerExpression(expression: IrContainerExpression): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
removeUnnecessaryTemporaryVariables(expression.statements)
|
||||
return expression
|
||||
}
|
||||
|
||||
override fun visitGetValue(expression: IrGetValue, currentClass: IrClass?): IrExpression {
|
||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||
// Replace IrGetValue of an immutable temporary variable with a constant
|
||||
// initializer with the constant initializer.
|
||||
val variable = expression.symbol.owner
|
||||
@@ -342,7 +280,6 @@ class JvmOptimizationLowering(val context: JvmBackendContext) : FileLoweringPass
|
||||
else
|
||||
expression
|
||||
}
|
||||
}
|
||||
irFile.transformChildren(transformer, null)
|
||||
})
|
||||
}
|
||||
}
|
||||
+10
-2
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.ir.expressions.IrFieldAccessExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.types.makeNotNull
|
||||
import org.jetbrains.kotlin.ir.util.coerceToUnit
|
||||
import org.jetbrains.kotlin.ir.util.hasAnnotation
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
@@ -130,7 +129,16 @@ class PropertiesToFieldsLowering(val context: CommonBackendContext) : IrElementT
|
||||
if (receiver != null && needBlock) {
|
||||
// Evaluate `dispatchReceiver` for the sake of its side effects, then return `setOrGetExpr`.
|
||||
return context.createIrBuilder(setOrGetExpr.symbol, setOrGetExpr.startOffset, setOrGetExpr.endOffset).irBlock(setOrGetExpr) {
|
||||
+receiver.coerceToUnit(context.irBuiltIns)
|
||||
// `coerceToUnit()` is private in InsertImplicitCasts, have to reproduce it here
|
||||
val receiverVoid = IrTypeOperatorCallImpl(
|
||||
receiver.startOffset, receiver.endOffset,
|
||||
context.irBuiltIns.unitType,
|
||||
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT,
|
||||
context.irBuiltIns.unitType,
|
||||
receiver
|
||||
)
|
||||
|
||||
+receiverVoid
|
||||
setOrGetExpr.receiver = null
|
||||
+setOrGetExpr
|
||||
}
|
||||
|
||||
+15
-7
@@ -37,7 +37,7 @@ import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
|
||||
import org.jetbrains.kotlin.ir.util.TypeTranslator
|
||||
import org.jetbrains.kotlin.ir.util.coerceToUnit
|
||||
import org.jetbrains.kotlin.ir.util.coerceToUnitIfNeeded
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.psi2ir.containsNull
|
||||
@@ -147,7 +147,7 @@ internal class InsertImplicitCasts(
|
||||
body.transformPostfix {
|
||||
statements.forEachIndexed { i, irStatement ->
|
||||
if (irStatement is IrExpression) {
|
||||
body.statements[i] = irStatement.coerceToUnit(irBuiltIns)
|
||||
body.statements[i] = irStatement.coerceToUnit()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -163,7 +163,7 @@ internal class InsertImplicitCasts(
|
||||
if (i == lastIndex)
|
||||
irStatement.cast(type)
|
||||
else
|
||||
irStatement.coerceToUnit(irBuiltIns)
|
||||
irStatement.coerceToUnit()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -171,7 +171,7 @@ internal class InsertImplicitCasts(
|
||||
override fun visitReturn(expression: IrReturn): IrExpression =
|
||||
expression.transformPostfix {
|
||||
value = if (expression.returnTargetSymbol is IrConstructorSymbol) {
|
||||
value.coerceToUnit(irBuiltIns)
|
||||
value.coerceToUnit()
|
||||
} else {
|
||||
val returnTargetDescriptor = expression.returnTarget
|
||||
val isLambdaReturnValue = returnTargetDescriptor is AnonymousFunctionDescriptor
|
||||
@@ -233,7 +233,7 @@ internal class InsertImplicitCasts(
|
||||
override fun visitLoop(loop: IrLoop): IrExpression =
|
||||
loop.transformPostfix {
|
||||
condition = condition.cast(builtIns.booleanType)
|
||||
body = body?.coerceToUnit(irBuiltIns)
|
||||
body = body?.coerceToUnit()
|
||||
}
|
||||
|
||||
override fun visitThrow(expression: IrThrow): IrExpression =
|
||||
@@ -249,7 +249,7 @@ internal class InsertImplicitCasts(
|
||||
aCatch.result = aCatch.result.cast(type)
|
||||
}
|
||||
|
||||
finallyExpression = finallyExpression?.coerceToUnit(irBuiltIns)
|
||||
finallyExpression = finallyExpression?.coerceToUnit()
|
||||
}
|
||||
|
||||
override fun visitTypeOperator(expression: IrTypeOperatorCall): IrExpression =
|
||||
@@ -318,7 +318,7 @@ internal class InsertImplicitCasts(
|
||||
|
||||
return when {
|
||||
expectedType.isUnit() ->
|
||||
coerceToUnit(irBuiltIns)
|
||||
coerceToUnit()
|
||||
|
||||
valueType.isDynamic() && !expectedType.isDynamic() ->
|
||||
if (expectedType.isNullableAny())
|
||||
@@ -383,6 +383,14 @@ internal class InsertImplicitCasts(
|
||||
)
|
||||
}
|
||||
|
||||
private fun IrExpression.coerceToUnit(): IrExpression {
|
||||
val valueType = getKotlinType(this)
|
||||
return coerceToUnitIfNeeded(valueType, irBuiltIns)
|
||||
}
|
||||
|
||||
private fun getKotlinType(irExpression: IrExpression) =
|
||||
irExpression.type.originalKotlinType!!
|
||||
|
||||
private fun KotlinType.isBuiltInIntegerType(): Boolean =
|
||||
KotlinBuiltIns.isByte(this) ||
|
||||
KotlinBuiltIns.isShort(this) ||
|
||||
|
||||
@@ -18,7 +18,6 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
@@ -155,14 +154,6 @@ fun IrExpression.isTrueConst() = this is IrConst<*> && this.kind == IrConstKind.
|
||||
|
||||
fun IrExpression.isFalseConst() = this is IrConst<*> && this.kind == IrConstKind.Boolean && this.value == false
|
||||
|
||||
fun IrExpression.coerceToUnit(builtins: IrBuiltIns): IrExpression {
|
||||
val valueType = getKotlinType(this)
|
||||
return coerceToUnitIfNeeded(valueType, builtins)
|
||||
}
|
||||
|
||||
private fun getKotlinType(irExpression: IrExpression) =
|
||||
irExpression.type.toKotlinType()
|
||||
|
||||
fun IrExpression.coerceToUnitIfNeeded(valueType: KotlinType, irBuiltIns: IrBuiltIns): IrExpression {
|
||||
return if (KotlinTypeChecker.DEFAULT.isSubtypeOf(valueType, irBuiltIns.unitType.toKotlinType()))
|
||||
this
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
package b
|
||||
|
||||
abstract class B {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
val x = 1
|
||||
|
||||
class A {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
class Example
|
||||
{
|
||||
var a1 = 0
|
||||
|
||||
Reference in New Issue
Block a user