Revert "JVM_IR: Use direct field access instead of calling certain accessors."

This reverts commit 62f9e7a810.
This commit is contained in:
max-kammerer
2020-01-28 14:54:57 +01:00
parent 6fdd4cb134
commit f256547cc8
8 changed files with 51 additions and 103 deletions
@@ -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
@@ -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)
})
}
}
@@ -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
}
@@ -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
View File
@@ -1,3 +1,4 @@
// IGNORE_BACKEND: JVM_IR
class Example
{
var a1 = 0