From a2b6282d4999da370da4611bc6895258e671f34d Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 5 Mar 2020 16:40:04 +0100 Subject: [PATCH] Refactor ApiVersion.KOTLIN_1_4 usages in relation to unified null checks --- .../src/org/jetbrains/kotlin/codegen/AsmUtil.java | 9 ++------- .../org/jetbrains/kotlin/codegen/ExpressionCodegen.java | 2 +- .../codegen/serialization/JvmSerializerExtension.kt | 4 ++-- .../jetbrains/kotlin/codegen/state/GenerationState.kt | 1 + .../kotlin/backend/jvm/codegen/ExpressionCodegen.kt | 5 +---- .../kotlin/backend/jvm/lower/CheckNotNullLowering.kt | 3 +-- .../lower/JvmArgumentNullabilityAssertionsLowering.kt | 5 +---- .../kotlin/backend/jvm/lower/TypeOperatorLowering.kt | 9 ++------- 8 files changed, 11 insertions(+), 27 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java index 4d00b3d2c70..9f566e9e080 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java @@ -22,7 +22,6 @@ import org.jetbrains.kotlin.codegen.intrinsics.HashCode; import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods; import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper; -import org.jetbrains.kotlin.config.ApiVersion; import org.jetbrains.kotlin.config.JvmTarget; import org.jetbrains.kotlin.config.LanguageFeature; import org.jetbrains.kotlin.config.LanguageVersionSettings; @@ -1023,9 +1022,7 @@ public class AsmUtil { } value.put(asmType, v); v.visitLdcInsn(name); - String methodName = state.getLanguageVersionSettings().getApiVersion().compareTo(ApiVersion.KOTLIN_1_4) >= 0 - ? "checkNotNullParameter" - : "checkParameterIsNotNull"; + String methodName = state.getUnifiedNullChecks() ? "checkNotNullParameter" : "checkParameterIsNotNull"; v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, methodName, "(Ljava/lang/Object;Ljava/lang/String;)V", false); } } @@ -1048,9 +1045,7 @@ public class AsmUtil { if (innerType.getSort() == Type.OBJECT || innerType.getSort() == Type.ARRAY) { v.dup(); v.visitLdcInsn(runtimeAssertionInfo.getMessage()); - String methodName = state.getLanguageVersionSettings().getApiVersion().compareTo(ApiVersion.KOTLIN_1_4) >= 0 - ? "checkNotNullExpressionValue" - : "checkExpressionValueIsNotNull"; + String methodName = state.getUnifiedNullChecks() ? "checkNotNullExpressionValue" : "checkExpressionValueIsNotNull"; v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, methodName, "(Ljava/lang/Object;Ljava/lang/String;)V", false); } StackValue.coerce(innerType, innerKotlinType, type, kotlinType, v); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 995ed225f24..567a0a484ee 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -4250,7 +4250,7 @@ public class ExpressionCodegen extends KtVisitor impleme return StackValue.operation(base.type, base.kotlinType, v -> { base.put(base.type, base.kotlinType, v); v.dup(); - if (state.getLanguageVersionSettings().getApiVersion().compareTo(ApiVersion.KOTLIN_1_4) >= 0) { + if (state.getUnifiedNullChecks()) { v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "checkNotNull", "(Ljava/lang/Object;)V", false); } else { Label ok = new Label(); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializerExtension.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializerExtension.kt index 213a94355a3..368f616586f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializerExtension.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializerExtension.kt @@ -12,7 +12,6 @@ import org.jetbrains.kotlin.codegen.createFreeFakeLocalPropertyDescriptor import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.* import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.KotlinTypeMapperBase -import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.load.java.JvmAbi @@ -53,6 +52,7 @@ class JvmSerializerExtension @JvmOverloads constructor( private val classBuilderMode = state.classBuilderMode private val languageVersionSettings = state.languageVersionSettings private val isParamAssertionsDisabled = state.isParamAssertionsDisabled + private val unifiedNullChecks = state.unifiedNullChecks override val metadataVersion = state.metadataVersion override fun shouldUseTypeTable(): Boolean = useTypeTable @@ -191,7 +191,7 @@ class JvmSerializerExtension @JvmOverloads constructor( } private fun MutableVersionRequirementTable.writeInlineParameterNullCheckRequirement(add: (Int) -> Unit) { - if (languageVersionSettings.apiVersion >= ApiVersion.KOTLIN_1_4) { + if (unifiedNullChecks) { // Since Kotlin 1.4, we generate a call to Intrinsics.checkNotNullParameter in inline functions which causes older compilers // (earlier than 1.3.50) to crash because a functional parameter in this position can't be inlined add(writeVersionRequirement(1, 3, 50, ProtoBuf.VersionRequirement.VersionKind.COMPILER_VERSION, this)) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt index c15636827b6..e0fabef66e2 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt @@ -242,6 +242,7 @@ class GenerationState private constructor( val assertionsMode: JVMAssertionsMode = configuration.get(JVMConfigurationKeys.ASSERTIONS_MODE, JVMAssertionsMode.DEFAULT) val isInlineDisabled: Boolean = configuration.getBoolean(CommonConfigurationKeys.DISABLE_INLINE) val useTypeTableInSerializer: Boolean = configuration.getBoolean(JVMConfigurationKeys.USE_TYPE_TABLE) + val unifiedNullChecks: Boolean = languageVersionSettings.apiVersion >= ApiVersion.KOTLIN_1_4 val rootContext: CodegenContext<*> = RootContext(this) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt index 02417632d07..8ae2db2ab9c 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt @@ -28,7 +28,6 @@ import org.jetbrains.kotlin.codegen.intrinsics.TypeIntrinsics import org.jetbrains.kotlin.codegen.pseudoInsns.fakeAlwaysFalseIfeq import org.jetbrains.kotlin.codegen.pseudoInsns.fixStackAndJump import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter -import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.isReleaseCoroutines import org.jetbrains.kotlin.config.languageVersionSettings @@ -283,9 +282,7 @@ class ExpressionCodegen( if (!param.type.unboxInlineClass().isNullable() && !isPrimitive(asmType)) { mv.load(findLocalIndex(param.symbol), asmType) mv.aconst(param.name.asString()) - val methodName = - if (state.languageVersionSettings.apiVersion >= ApiVersion.KOTLIN_1_4) "checkNotNullParameter" - else "checkParameterIsNotNull" + val methodName = if (state.unifiedNullChecks) "checkNotNullParameter" else "checkParameterIsNotNull" mv.invokestatic(IrIntrinsicMethods.INTRINSICS_CLASS_NAME, methodName, "(Ljava/lang/Object;Ljava/lang/String;)V", false) } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/CheckNotNullLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/CheckNotNullLowering.kt index 718097b7b93..9205857095f 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/CheckNotNullLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/CheckNotNullLowering.kt @@ -11,7 +11,6 @@ import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.irIfThen import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext -import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.expressions.IrCall @@ -43,7 +42,7 @@ private class CheckNotNullLowering(private val backendContext: JvmBackendContext // Starting with Kotlin 1.4 null-checks are lowered to calls to the "checkNotNull" intrinsic, which // throws a NullPointerException on failure. Prior to Kotlin 1.4 we instead inline the null-check and // call the "throwNpe" intrinsic on failure which throws a KotlinNullPointerException. - if (backendContext.state.languageVersionSettings.apiVersion >= ApiVersion.KOTLIN_1_4) { + if (backendContext.state.unifiedNullChecks) { +irCall(backendContext.ir.symbols.checkNotNull).apply { putValueArgument(0, irGet(argument)) } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmArgumentNullabilityAssertionsLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmArgumentNullabilityAssertionsLowering.kt index f11571d3448..dbefe089274 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmArgumentNullabilityAssertionsLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmArgumentNullabilityAssertionsLowering.kt @@ -7,11 +7,8 @@ package org.jetbrains.kotlin.backend.jvm.lower import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.lower.SpecialBridgeMethods -import org.jetbrains.kotlin.backend.common.lower.flattenStringConcatenationPhase -import org.jetbrains.kotlin.backend.common.lower.loops.forLoopsPhase import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext -import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.IrDeclaration @@ -35,7 +32,7 @@ private enum class AssertionScope { private class JvmArgumentNullabilityAssertionsLowering(context: JvmBackendContext) : FileLoweringPass, IrElementTransformer { - private val isWithUnifiedNullChecks = context.state.languageVersionSettings.apiVersion >= ApiVersion.KOTLIN_1_4 + private val isWithUnifiedNullChecks = context.state.unifiedNullChecks private val isCallAssertionsDisabled = context.state.isCallAssertionsDisabled private val isReceiverAssertionsDisabled = context.state.isReceiverAssertionsDisabled diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/TypeOperatorLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/TypeOperatorLowering.kt index c0807599876..f24ac1e3a2b 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/TypeOperatorLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/TypeOperatorLowering.kt @@ -14,7 +14,6 @@ import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.codegen.fileParent import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound -import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.builders.* @@ -184,18 +183,14 @@ private class TypeOperatorLowering(private val context: JvmBackendContext) : Fil private fun sourceViewFor(declaration: IrDeclaration) = context.psiSourceManager.getKtFile(declaration.fileParent)!!.viewProvider.contents - // Since Kotlin 1.4 we throw NullPointerExceptions instead of more specialized exception classes. - private val useNullPointerExceptions: Boolean - get() = context.state.languageVersionSettings.apiVersion >= ApiVersion.KOTLIN_1_4 - private val typeCastException: IrFunctionSymbol = - if (useNullPointerExceptions) + if (context.state.unifiedNullChecks) context.ir.symbols.ThrowNullPointerException else context.ir.symbols.ThrowTypeCastException private val checkExpressionValueIsNotNull: IrFunctionSymbol = - if (useNullPointerExceptions) + if (context.state.unifiedNullChecks) context.ir.symbols.checkNotNullExpressionValue else context.ir.symbols.checkExpressionValueIsNotNull