diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AssertCodegenUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/AssertCodegenUtil.kt index e6bdfe5b00e..c9bddec6496 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AssertCodegenUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AssertCodegenUtil.kt @@ -6,6 +6,8 @@ package org.jetbrains.kotlin.codegen import org.jetbrains.kotlin.codegen.coroutines.createCustomCopy +import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence +import org.jetbrains.kotlin.codegen.optimization.common.findPreviousOrNull import org.jetbrains.kotlin.config.JVMAssertionsMode import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.isTopLevelInPackage @@ -19,12 +21,15 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy import org.jetbrains.kotlin.resolve.jvm.AsmTypes import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin +import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.org.objectweb.asm.Label import org.jetbrains.org.objectweb.asm.MethodVisitor import org.jetbrains.org.objectweb.asm.Opcodes import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode +import org.jetbrains.org.objectweb.asm.tree.LdcInsnNode +import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode import org.jetbrains.org.objectweb.asm.tree.MethodNode const val ASSERTIONS_DISABLED_FIELD_NAME = "\$assertionsDisabled" @@ -130,7 +135,7 @@ private fun inlineAlwaysInlineAssert(resolvedCall: ResolvedCall<*>, codegen: Exp ) } -fun generateAssertionsDisabledFieldInitialization(classBuilder: ClassBuilder, clInitBuilder: MethodVisitor) { +fun generateAssertionsDisabledFieldInitialization(classBuilder: ClassBuilder, clInitBuilder: MethodVisitor, className: String) { classBuilder.newField( JvmDeclarationOrigin.NO_ORIGIN, Opcodes.ACC_STATIC or Opcodes.ACC_FINAL or Opcodes.ACC_SYNTHETIC, ASSERTIONS_DISABLED_FIELD_NAME, "Z", null, null @@ -139,7 +144,7 @@ fun generateAssertionsDisabledFieldInitialization(classBuilder: ClassBuilder, cl val elseLabel = Label() with(InstructionAdapter(clInitBuilder)) { mark(Label()) - aconst(Type.getObjectType(classBuilder.thisName)) + aconst(Type.getObjectType(className)) invokevirtual("java/lang/Class", "desiredAssertionStatus", "()Z", false) ifne(thenLabel) iconst(1) @@ -153,6 +158,16 @@ fun generateAssertionsDisabledFieldInitialization(classBuilder: ClassBuilder, cl } } +fun rewriteAssertionsDisabledFieldInitialization(methodNode: MethodNode, className: String) { + InsnSequence(methodNode.instructions).firstOrNull { + it is FieldInsnNode && it.opcode == Opcodes.PUTSTATIC && it.name == ASSERTIONS_DISABLED_FIELD_NAME + }?.findPreviousOrNull { + it is MethodInsnNode && it.opcode == Opcodes.INVOKEVIRTUAL + && it.owner == "java/lang/Class" && it.name == "desiredAssertionStatus" && it.desc == "()Z" + }?.previous?.safeAs()?.cst = + Type.getObjectType(className) +} + private fun ResolvedCall.replaceAssertWithAssertInner(): ResolvedCall { val newCandidateDescriptor = resultingDescriptor.createCustomCopy { setName(Name.identifier(ALWAYS_ENABLED_ASSERT_FUNCTION_NAME)) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java index 7a4633dde3d..d62b299a3be 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java @@ -965,7 +965,7 @@ public abstract class MemberCodegen coroutineTransformer.newMethod(next) else -> newMethod(classBuilder, next) } + + if (next.name == "") { + rewriteAssertionsDisabledFieldInitialization(next, inliningContext.root.callSiteInfo.ownerClassName) + } + val funResult = inlineMethodAndUpdateGlobalResult(parentRemapper, deferringVisitor, next, allCapturedParamBuilder, false) val returnType = Type.getReturnType(next.desc) @@ -195,7 +200,7 @@ class AnonymousObjectTransformer( if (inliningContext.generateAssertField && fieldNames.none { it.key == ASSERTIONS_DISABLED_FIELD_NAME }) { val clInitBuilder = classBuilder.newMethod(NO_ORIGIN, Opcodes.ACC_STATIC, "", "()V", null, null) - generateAssertionsDisabledFieldInitialization(classBuilder, clInitBuilder) + generateAssertionsDisabledFieldInitialization(classBuilder, clInitBuilder, inliningContext.root.callSiteInfo.ownerClassName) clInitBuilder.visitInsn(Opcodes.RETURN) clInitBuilder.visitEnd() } diff --git a/compiler/testData/codegen/boxInline/assert/jvmCrossinlineLambdaDeclarationSite.kt b/compiler/testData/codegen/boxInline/assert/jvmCrossinlineLambdaDeclarationSite.kt index b05547d8674..503a113b98f 100644 --- a/compiler/testData/codegen/boxInline/assert/jvmCrossinlineLambdaDeclarationSite.kt +++ b/compiler/testData/codegen/boxInline/assert/jvmCrossinlineLambdaDeclarationSite.kt @@ -1,6 +1,4 @@ // TARGET_BACKEND: JVM -// IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND_MULTI_MODULE: JVM_IR // FILE: inline.kt // KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm // WITH_RUNTIME @@ -185,8 +183,9 @@ class ShouldBeEnabled : Checker { fun setDesiredAssertionStatus(v: Boolean): Checker { val loader = Checker::class.java.classLoader loader.setDefaultAssertionStatus(false) - loader.setPackageAssertionStatus("test", v) - val c = loader.loadClass(if (v) "ShouldBeEnabled" else "ShouldBeDisabled") + val className = if (v) "ShouldBeEnabled" else "ShouldBeDisabled" + loader.setClassAssertionStatus(className, v) + val c = loader.loadClass(className) return c.newInstance() as Checker } @@ -202,14 +201,32 @@ fun box(): String { if (c.checkFalseWithMessageFalse()) return "FAIL 31" c = setDesiredAssertionStatus(true) - if (c.checkTrueTrue()) return "FAIL 100" - if (c.checkTrueFalse()) return "FAIL 101" - if (c.checkTrueWithMessageTrue()) return "FAIL 110" - if (c.checkTrueWithMessageFalse()) return "FAIL 111" - if (c.checkFalseTrue()) return "FAIL 120" - if (c.checkFalseFalse()) return "FAIL 121" - if (c.checkFalseWithMessageTrue()) return "FAIL 130" - if (c.checkFalseWithMessageFalse()) return "FAIL 131" + if (!c.checkTrueTrue()) return "FAIL 100" + try { + c.checkTrueFalse() + return "FAIL 101" + } catch (ignore: AssertionError) {} + if (!c.checkTrueWithMessageTrue()) return "FAIL 110" + try { + c.checkTrueWithMessageFalse() + return "FAIL 111" + } catch (ignore: AssertionError) {} + try { + c.checkFalseTrue() + return "FAIL 120" + } catch (ignore: AssertionError) {} + try { + c.checkFalseFalse() + return "FAIL 121" + } catch (ignore: AssertionError) {} + try { + c.checkFalseWithMessageTrue() + return "FAIL 130" + } catch (ignore: AssertionError) {} + try { + c.checkFalseWithMessageFalse() + return "FAIL 131" + } catch (ignore: AssertionError) {} return "OK" } \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/assert/jvmCrossinlineAssertInLambda.kt b/compiler/testData/codegen/bytecodeText/assert/jvmCrossinlineAssertInLambda.kt index f855446ebb9..0604fbd1eca 100644 --- a/compiler/testData/codegen/bytecodeText/assert/jvmCrossinlineAssertInLambda.kt +++ b/compiler/testData/codegen/bytecodeText/assert/jvmCrossinlineAssertInLambda.kt @@ -1,6 +1,3 @@ -// This test is ignored until KT-36794 is fixed -// IGNORE_BACKEND: JVM -// IGNORE_BACKEND: JVM_IR // KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm inline fun inlineMe(crossinline c : () -> Unit) = {