Add a fallback flag -Xno-unified-null-checks for KT-22275

#KT-41482 Fixed
This commit is contained in:
Alexander Udalov
2020-08-28 21:10:22 +02:00
parent 40669350f7
commit 5e48be3d11
14 changed files with 35 additions and 16 deletions
@@ -5051,7 +5051,9 @@ The "returned" value of try expression with no finally is either the last expres
return Unit.INSTANCE; return Unit.INSTANCE;
} }
CodegenUtilKt.generateAsCast(v, rightKotlinType, boxedRightType, safeAs, state.getLanguageVersionSettings()); CodegenUtilKt.generateAsCast(
v, rightKotlinType, boxedRightType, safeAs, state.getLanguageVersionSettings(), state.getUnifiedNullChecks()
);
return Unit.INSTANCE; return Unit.INSTANCE;
}); });
@@ -98,11 +98,12 @@ fun generateAsCast(
kotlinType: KotlinType, kotlinType: KotlinType,
asmType: Type, asmType: Type,
isSafe: Boolean, isSafe: Boolean,
languageVersionSettings: LanguageVersionSettings languageVersionSettings: LanguageVersionSettings,
unifiedNullChecks: Boolean,
) { ) {
if (!isSafe) { if (!isSafe) {
if (!TypeUtils.isNullableType(kotlinType)) { if (!TypeUtils.isNullableType(kotlinType)) {
generateNullCheckForNonSafeAs(v, kotlinType, languageVersionSettings) generateNullCheckForNonSafeAs(v, kotlinType, unifiedNullChecks)
} }
} else { } else {
with(v) { with(v) {
@@ -122,15 +123,13 @@ fun generateAsCast(
private fun generateNullCheckForNonSafeAs( private fun generateNullCheckForNonSafeAs(
v: InstructionAdapter, v: InstructionAdapter,
type: KotlinType, type: KotlinType,
languageVersionSettings: LanguageVersionSettings unifiedNullChecks: Boolean,
) { ) {
with(v) { with(v) {
dup() dup()
val nonnull = Label() val nonnull = Label()
ifnonnull(nonnull) ifnonnull(nonnull)
val exceptionClass = val exceptionClass = if (unifiedNullChecks) "java/lang/NullPointerException" else "kotlin/TypeCastException"
if (languageVersionSettings.apiVersion >= ApiVersion.KOTLIN_1_4) "java/lang/NullPointerException"
else "kotlin/TypeCastException"
AsmUtil.genThrow( AsmUtil.genThrow(
v, v,
exceptionClass, exceptionClass,
@@ -41,7 +41,10 @@ class PsiInlineCodegen(
private val actualDispatchReceiver: Type = methodOwner private val actualDispatchReceiver: Type = methodOwner
) : InlineCodegen<ExpressionCodegen>( ) : InlineCodegen<ExpressionCodegen>(
codegen, state, function, methodOwner, signature, typeParameterMappings, sourceCompiler, codegen, state, function, methodOwner, signature, typeParameterMappings, sourceCompiler,
ReifiedTypeInliner(typeParameterMappings, PsiInlineIntrinsicsSupport(state), codegen.typeSystem, state.languageVersionSettings), ReifiedTypeInliner(
typeParameterMappings, PsiInlineIntrinsicsSupport(state), codegen.typeSystem,
state.languageVersionSettings, state.unifiedNullChecks
),
), CallGenerator { ), CallGenerator {
override fun generateAssertFieldIfNeeded(info: RootInliningContext) { override fun generateAssertFieldIfNeeded(info: RootInliningContext) {
if (info.generateAssertField) { if (info.generateAssertField) {
@@ -53,7 +53,8 @@ class ReifiedTypeInliner<KT : KotlinTypeMarker>(
private val parametersMapping: TypeParameterMappings<KT>?, private val parametersMapping: TypeParameterMappings<KT>?,
private val intrinsicsSupport: IntrinsicsSupport<KT>, private val intrinsicsSupport: IntrinsicsSupport<KT>,
private val typeSystem: TypeSystemCommonBackendContext, private val typeSystem: TypeSystemCommonBackendContext,
private val languageVersionSettings: LanguageVersionSettings private val languageVersionSettings: LanguageVersionSettings,
private val unifiedNullChecks: Boolean,
) { ) {
enum class OperationKind { enum class OperationKind {
NEW_ARRAY, AS, SAFE_AS, IS, JAVA_CLASS, ENUM_REIFIED, TYPE_OF; NEW_ARRAY, AS, SAFE_AS, IS, JAVA_CLASS, ENUM_REIFIED, TYPE_OF;
@@ -222,7 +223,7 @@ class ReifiedTypeInliner<KT : KotlinTypeMarker>(
if (stubCheckcast !is TypeInsnNode) return false if (stubCheckcast !is TypeInsnNode) return false
val newMethodNode = MethodNode(Opcodes.API_VERSION) val newMethodNode = MethodNode(Opcodes.API_VERSION)
generateAsCast(InstructionAdapter(newMethodNode), kotlinType, asmType, safe, languageVersionSettings) generateAsCast(InstructionAdapter(newMethodNode), kotlinType, asmType, safe, languageVersionSettings, unifiedNullChecks)
instructions.insert(insn, newMethodNode.instructions) instructions.insert(insn, newMethodNode.instructions)
// Keep stubCheckcast to avoid VerifyErrors on 1.8+ bytecode, // Keep stubCheckcast to avoid VerifyErrors on 1.8+ bytecode,
@@ -249,7 +249,9 @@ class GenerationState private constructor(
val assertionsMode: JVMAssertionsMode = configuration.get(JVMConfigurationKeys.ASSERTIONS_MODE, JVMAssertionsMode.DEFAULT) val assertionsMode: JVMAssertionsMode = configuration.get(JVMConfigurationKeys.ASSERTIONS_MODE, JVMAssertionsMode.DEFAULT)
val isInlineDisabled: Boolean = configuration.getBoolean(CommonConfigurationKeys.DISABLE_INLINE) val isInlineDisabled: Boolean = configuration.getBoolean(CommonConfigurationKeys.DISABLE_INLINE)
val useTypeTableInSerializer: Boolean = configuration.getBoolean(JVMConfigurationKeys.USE_TYPE_TABLE) val useTypeTableInSerializer: Boolean = configuration.getBoolean(JVMConfigurationKeys.USE_TYPE_TABLE)
val unifiedNullChecks: Boolean = languageVersionSettings.apiVersion >= ApiVersion.KOTLIN_1_4 val unifiedNullChecks: Boolean =
languageVersionSettings.apiVersion >= ApiVersion.KOTLIN_1_4 &&
!configuration.getBoolean(JVMConfigurationKeys.NO_UNIFIED_NULL_CHECKS)
val functionsWithInlineClassReturnTypesMangled: Boolean = val functionsWithInlineClassReturnTypesMangled: Boolean =
languageVersionSettings.supportsFeature(LanguageFeature.MangleClassMembersReturningInlineClasses) languageVersionSettings.supportsFeature(LanguageFeature.MangleClassMembersReturningInlineClasses)
@@ -352,6 +352,12 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
) )
var noKotlinNothingValueException: Boolean by FreezableVar(false) var noKotlinNothingValueException: Boolean by FreezableVar(false)
@Argument(
value = "-Xno-unified-null-checks",
description = "Use pre-1.4 exception types in null checks instead of java.lang.NPE. See KT-22275 for more details"
)
var noUnifiedNullChecks: Boolean by FreezableVar(false)
@Argument( @Argument(
value = "-Xprofile", value = "-Xprofile",
valueDescription = "<profilerPath:command:outputDir>", valueDescription = "<profilerPath:command:outputDir>",
@@ -166,6 +166,7 @@ fun CompilerConfiguration.configureAdvancedJvmOptions(arguments: K2JVMCompilerAr
put(JVMConfigurationKeys.EMIT_JVM_TYPE_ANNOTATIONS, arguments.emitJvmTypeAnnotations) put(JVMConfigurationKeys.EMIT_JVM_TYPE_ANNOTATIONS, arguments.emitJvmTypeAnnotations)
put(JVMConfigurationKeys.NO_OPTIMIZED_CALLABLE_REFERENCES, arguments.noOptimizedCallableReferences) put(JVMConfigurationKeys.NO_OPTIMIZED_CALLABLE_REFERENCES, arguments.noOptimizedCallableReferences)
put(JVMConfigurationKeys.NO_KOTLIN_NOTHING_VALUE_EXCEPTION, arguments.noKotlinNothingValueException) put(JVMConfigurationKeys.NO_KOTLIN_NOTHING_VALUE_EXCEPTION, arguments.noKotlinNothingValueException)
put(JVMConfigurationKeys.NO_UNIFIED_NULL_CHECKS, arguments.noUnifiedNullChecks)
if (!JVMConstructorCallNormalizationMode.isSupportedValue(arguments.constructorCallNormalizationMode)) { if (!JVMConstructorCallNormalizationMode.isSupportedValue(arguments.constructorCallNormalizationMode)) {
getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report( getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(
@@ -123,6 +123,9 @@ public class JVMConfigurationKeys {
public static final CompilerConfigurationKey<Boolean> NO_KOTLIN_NOTHING_VALUE_EXCEPTION = public static final CompilerConfigurationKey<Boolean> NO_KOTLIN_NOTHING_VALUE_EXCEPTION =
CompilerConfigurationKey.create("Do not use KotlinNothingValueException available since 1.4"); CompilerConfigurationKey.create("Do not use KotlinNothingValueException available since 1.4");
public static final CompilerConfigurationKey<Boolean> NO_UNIFIED_NULL_CHECKS =
CompilerConfigurationKey.create("Use pre-1.4 exception types in null checks instead of java.lang.NPE");
public static final CompilerConfigurationKey<Boolean> USE_OLD_SPILLED_VAR_TYPE_ANALYSIS = public static final CompilerConfigurationKey<Boolean> USE_OLD_SPILLED_VAR_TYPE_ANALYSIS =
CompilerConfigurationKey.create("Use old, SourceInterpreter-based analysis for fields, used for spilled variables in coroutines"); CompilerConfigurationKey.create("Use old, SourceInterpreter-based analysis for fields, used for spilled variables in coroutines");
} }
@@ -1201,7 +1201,8 @@ class ExpressionCodegen(
mappings, mappings,
IrInlineIntrinsicsSupport(context, typeMapper), IrInlineIntrinsicsSupport(context, typeMapper),
IrTypeCheckerContext(context.irBuiltIns), IrTypeCheckerContext(context.irBuiltIns),
state.languageVersionSettings state.languageVersionSettings,
state.unifiedNullChecks,
) )
return IrInlineCodegen(this, state, callee, methodOwner, signature, mappings, sourceCompiler, reifiedTypeInliner) return IrInlineCodegen(this, state, callee, methodOwner, signature, mappings, sourceCompiler, reifiedTypeInliner)
+1
View File
@@ -73,6 +73,7 @@ where advanced options include:
Do not use optimized callable reference superclasses available from 1.4 Do not use optimized callable reference superclasses available from 1.4
-Xno-param-assertions Don't generate not-null assertions on parameters of methods accessible from Java -Xno-param-assertions Don't generate not-null assertions on parameters of methods accessible from Java
-Xno-receiver-assertions Don't generate not-null assertion for extension receiver arguments of platform types -Xno-receiver-assertions Don't generate not-null assertion for extension receiver arguments of platform types
-Xno-unified-null-checks Use pre-1.4 exception types in null checks instead of java.lang.NPE. See KT-22275 for more details
-Xno-use-ir Do not use the IR backend. Useful for a custom-built compiler where IR backend is enabled by default -Xno-use-ir Do not use the IR backend. Useful for a custom-built compiler where IR backend is enabled by default
-Xprofile=<profilerPath:command:outputDir> -Xprofile=<profilerPath:command:outputDir>
Debug option: Run compiler with async profiler, save snapshots to outputDir, command is passed to async-profiler on start Debug option: Run compiler with async profiler, save snapshots to outputDir, command is passed to async-profiler on start
@@ -1,4 +1,4 @@
// !API_VERSION: 1.3 // KOTLIN_CONFIGURATION_FLAGS: +JVM.NO_UNIFIED_NULL_CHECKS
// WITH_RUNTIME // WITH_RUNTIME
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
@@ -1,4 +1,4 @@
// !API_VERSION: 1.3 // KOTLIN_CONFIGURATION_FLAGS: +JVM.NO_UNIFIED_NULL_CHECKS
// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// FILE: A.java // FILE: A.java
@@ -1,4 +1,4 @@
// !API_VERSION: 1.3 // KOTLIN_CONFIGURATION_FLAGS: +JVM.NO_UNIFIED_NULL_CHECKS
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// FILE: A.java // FILE: A.java
@@ -1,4 +1,4 @@
// !API_VERSION: 1.3 // KOTLIN_CONFIGURATION_FLAGS: +JVM.NO_UNIFIED_NULL_CHECKS
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// FILE: 1.kt // FILE: 1.kt
// WITH_RUNTIME // WITH_RUNTIME