diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt index a17d2fd3de9..ea9f5f3d29a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt @@ -669,7 +669,7 @@ class CoroutineTransformerMethodVisitor( val value = frame.getLocal(slot) if (value.type == null || !livenessFrame.isAlive(slot)) continue - if (value == StrictBasicValue.NULL_VALUE || value is TypedNullValue) { + if (value == StrictBasicValue.NULL_VALUE) { referencesToSpill += slot to null continue } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/SpilledVariableFieldTypesAnalysis.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/SpilledVariableFieldTypesAnalysis.kt index d09d7ea2295..609c1181e52 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/SpilledVariableFieldTypesAnalysis.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/SpilledVariableFieldTypesAnalysis.kt @@ -8,7 +8,6 @@ package org.jetbrains.kotlin.codegen.coroutines import org.jetbrains.kotlin.codegen.StackValue import org.jetbrains.kotlin.codegen.optimization.common.FastMethodAnalyzer import org.jetbrains.kotlin.codegen.optimization.common.OptimizationBasicInterpreter -import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue import org.jetbrains.org.objectweb.asm.Label import org.jetbrains.org.objectweb.asm.Opcodes import org.jetbrains.org.objectweb.asm.Type @@ -135,7 +134,7 @@ internal fun performSpilledVariableFieldTypesAnalysis( for ((insn, type) in interpreter.needsToBeCoerced) { methodNode.instructions.insert(insn, withInstructionAdapter { coerceInt(type, this) }) } - return FastMethodAnalyzer(thisName, methodNode, NullCheckcastAwareOptimizationBasicInterpreter()).analyze() + return FastMethodAnalyzer(thisName, methodNode, OptimizationBasicInterpreter()).analyze() } private fun coerceInt(to: Type, v: InstructionAdapter) { @@ -159,24 +158,3 @@ private fun Type.isIntLike(): Boolean = when (sort) { Type.BOOLEAN, Type.BYTE, Type.CHAR, Type.SHORT -> true else -> false } - -// Represents [ACONST_NULL, CHECKCAST Type] sequence result. -internal class TypedNullValue(type: Type) : StrictBasicValue(type) - -// Preserves nulls through CHECKCASTS. -private class NullCheckcastAwareOptimizationBasicInterpreter : OptimizationBasicInterpreter() { - override fun unaryOperation(insn: AbstractInsnNode, value: BasicValue?): BasicValue? { - if (insn.opcode == Opcodes.CHECKCAST && (value == StrictBasicValue.NULL_VALUE || value is TypedNullValue)) { - return TypedNullValue(Type.getObjectType((insn as TypeInsnNode).desc)) - } - return super.unaryOperation(insn, value) - } - - override fun merge(v: BasicValue, w: BasicValue): BasicValue = - when { - v is TypedNullValue && w is TypedNullValue -> if (v.type == w.type) v else StrictBasicValue.NULL_VALUE - v is TypedNullValue -> super.merge(StrictBasicValue.NULL_VALUE, w) - w is TypedNullValue -> super.merge(v, StrictBasicValue.NULL_VALUE) - else -> super.merge(v, w) - } -} diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/OptimizationBasicInterpreter.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/OptimizationBasicInterpreter.java index 29122ede940..8c52059e38a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/OptimizationBasicInterpreter.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/OptimizationBasicInterpreter.java @@ -204,7 +204,7 @@ public class OptimizationBasicInterpreter extends Interpreter implem case DREM: return StrictBasicValue.DOUBLE_VALUE; case AALOAD: - return StrictBasicValue.REFERENCE_VALUE; + return StrictBasicValue.NULL_VALUE; case LCMP: case FCMPL: case FCMPG: @@ -331,6 +331,9 @@ public class OptimizationBasicInterpreter extends Interpreter implem case ATHROW: return null; case CHECKCAST: + if (value == StrictBasicValue.NULL_VALUE) { + return StrictBasicValue.NULL_VALUE; + } desc = ((TypeInsnNode) insn).desc; return newValue(Type.getObjectType(desc)); case INSTANCEOF: diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/StrictBasicValue.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/StrictBasicValue.kt index d2597f42e61..b5196238497 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/StrictBasicValue.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/StrictBasicValue.kt @@ -68,7 +68,12 @@ open class StrictBasicValue(type: Type?) : BasicValue(type) { override fun hashCode() = (type?.hashCode() ?: 0) override fun toString(): String { - if (this === UNINITIALIZED_VALUE) return "." - return super.toString() + val inner = when { + this === REFERENCE_VALUE -> "R" + this === NULL_VALUE -> "null" + this === UNINITIALIZED_VALUE -> "." + else -> super.toString() + } + return "${this::class.java.simpleName}($inner)" } } diff --git a/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt index 74b139ec8ff..2fffea13474 100644 --- a/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt +++ b/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt @@ -657,18 +657,6 @@ class ExpressionCodegen( val value = initializer.accept(this, data) initializer.markLineNumber(startOffset = true) value.materializeAt(varType, declaration.type) - // We need to generate CHECKCAST from ACONST_NULL here for coroutines, - // since otherwise, upon spilling and then unspilling, we will get VerifyError, - // because state-machine builder does not know the type of the ACONST_NULL - // and assumes it to be Ljava/lang/Object;, which is incorrect. - // Generating CHECKCAST hints the state-machine builder the type of the variable - // avoiding the issue of VerifyError. See KT-51718 - // Exception is Ljava/lang/Object;, since CHECKCAST Ljava/lang/Object; is effectively no-op. - if (initializer.isNullConst() && varType != OBJECT_TYPE && - (irFunction.isSuspend || irFunction.isInvokeSuspendOfLambda()) - ) { - mv.checkcast(varType) - } declaration.markLineNumber(startOffset = true) mv.store(index, varType) } else if (declaration.isVisibleInLVT) {