diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt index dafed48c474..a255d267e56 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt @@ -121,7 +121,9 @@ abstract class InlineCodegen( // In case `codegen.visitor` is ``, initializer for the `$assertionsDisabled` field // needs to be inserted before the code that actually uses it. - generateAssertFieldIfNeeded(info) + if (info.generateAssertField) { + generateAssertField() + } val shouldSpillStack = node.requiresEmptyStackOnEntry() if (shouldSpillStack) { @@ -193,7 +195,7 @@ abstract class InlineCodegen( processor.substituteLocalVarTable(intoNode) } - protected abstract fun generateAssertFieldIfNeeded(info: RootInliningContext) + protected abstract fun generateAssertField() private fun isInlinedToInlineFunInKotlinRuntime(): Boolean { val codegen = this.codegen as? ExpressionCodegen ?: return false diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiInlineCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiInlineCodegen.kt index 29f21c63c59..3646f4d87ea 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiInlineCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiInlineCodegen.kt @@ -51,11 +51,8 @@ class PsiInlineCodegen( state.languageVersionSettings, state.unifiedNullChecks ), ), CallGenerator { - override fun generateAssertFieldIfNeeded(info: RootInliningContext) { - if (info.generateAssertField) { - codegen.parentCodegen.generateAssertField() - } - } + override fun generateAssertField() = + codegen.parentCodegen.generateAssertField() override fun genCallInner( callableMethod: Callable, diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxInlineCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxInlineCodegenTestGenerated.java index 780ba63d8e0..f5a3cac843a 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxInlineCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxInlineCodegenTestGenerated.java @@ -894,6 +894,12 @@ public class FirBlackBoxInlineCodegenTestGenerated extends AbstractFirBlackBoxIn runTest("compiler/testData/codegen/boxInline/assert/jvmDoubleInline.kt"); } + @Test + @TestMetadata("jvmInlineIntoTwoMethods.kt") + public void testJvmInlineIntoTwoMethods() throws Exception { + runTest("compiler/testData/codegen/boxInline/assert/jvmInlineIntoTwoMethods.kt"); + } + @Test @TestMetadata("jvmInlineUsedAsNoinline.kt") public void testJvmInlineUsedAsNoinline() throws Exception { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt index 6a95d4d3d10..c191f1aeaa0 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt @@ -197,22 +197,19 @@ class ClassCodegen private constructor( } } - fun generateAssertFieldIfNeeded(generatingClInit: Boolean): IrExpression? { if (irClass.hasAssertionsDisabledField(context)) return null val topLevelClass = generateSequence(this) { it.parentClassCodegen }.last().irClass val field = irClass.buildAssertionsDisabledField(context, topLevelClass) - generateField(field) - // Normally, `InitializersLowering` would move the initializer to , but - // it's obviously too late for that. - val init = IrSetFieldImpl( - field.startOffset, field.endOffset, field.symbol, null, - field.initializer!!.expression, context.irBuiltIns.unitType - ) + irClass.declarations.add(0, field) + // Normally, `InitializersLowering` would move the initializer to , but it's obviously too late for that. + val init = with(field) { + IrSetFieldImpl(startOffset, endOffset, symbol, null, initializer!!.expression, context.irBuiltIns.unitType) + } if (generatingClInit) { - // Too late to modify the IR; have to ask the currently active `ExpressionCodegen` - // to generate this statement directly. + // Too late to modify the IR; have to ask the currently active `ExpressionCodegen` to generate this statement + // directly. At least we know that nothing before this point uses the field. return init } val classInitializer = irClass.functions.singleOrNull { it.name.asString() == "" } ?: irClass.addFunction { @@ -221,6 +218,7 @@ class ClassCodegen private constructor( }.apply { body = IrBlockBodyImpl(startOffset, endOffset) } + // Should be initialized first in case some inline function call in `` also uses assertions. (classInitializer.body as IrBlockBody).statements.add(0, init) return null } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt index 605bbd1a4a5..7f24017d2a9 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt @@ -46,13 +46,11 @@ class IrInlineCodegen( InlineCodegen(codegen, state, signature, typeParameterMappings, sourceCompiler, reifiedTypeInliner), IrInlineCallGenerator { - override fun generateAssertFieldIfNeeded(info: RootInliningContext) { - if (info.generateAssertField) { - // May be inlining code into ``, in which case it's too late to modify the IR and - // `generateAssertFieldIfNeeded` will return a statement for which we need to emit bytecode. - val isClInit = info.callSiteInfo.method.name == "" - codegen.classCodegen.generateAssertFieldIfNeeded(isClInit)?.accept(codegen, BlockInfo())?.discard() - } + override fun generateAssertField() { + // May be inlining code into ``, in which case it's too late to modify the IR and + // `generateAssertFieldIfNeeded` will return a statement for which we need to emit bytecode. + val isClInit = sourceCompiler.inlineCallSiteInfo.method.name == "" + codegen.classCodegen.generateAssertFieldIfNeeded(isClInit)?.accept(codegen, BlockInfo())?.discard() } override fun genValueAndPut( diff --git a/compiler/testData/codegen/boxInline/assert/jvmInlineIntoTwoMethods.kt b/compiler/testData/codegen/boxInline/assert/jvmInlineIntoTwoMethods.kt new file mode 100644 index 00000000000..e9eb098813d --- /dev/null +++ b/compiler/testData/codegen/boxInline/assert/jvmInlineIntoTwoMethods.kt @@ -0,0 +1,32 @@ +// FULL_JDK +// WITH_RUNTIME +// TARGET_BACKEND: JVM +// ASSERTIONS_MODE: jvm +// FILE: inline.kt +package test + +class A { + inline fun assert(message: String): Nothing { + assert(false) { message } + throw IllegalStateException("unreachable") + } +} + +// FILE: inlineSite.kt +import test.* + +class Checker { + fun o(): Nothing = A().assert("O") + fun k(): Nothing = A().assert("K") +} + +class Dummy + +fun box(): String { + var c = Dummy::class.java.classLoader.apply { + setDefaultAssertionStatus(true) + }.loadClass("Checker").newInstance() as Checker + val o = try { c.o() } catch (e: AssertionError) { e.message } + val k = try { c.k() } catch (e: AssertionError) { e.message } + return o + k +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxInlineCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxInlineCodegenTestGenerated.java index 2d07d4659ec..8de7be176d5 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxInlineCodegenTestGenerated.java @@ -894,6 +894,12 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo runTest("compiler/testData/codegen/boxInline/assert/jvmDoubleInline.kt"); } + @Test + @TestMetadata("jvmInlineIntoTwoMethods.kt") + public void testJvmInlineIntoTwoMethods() throws Exception { + runTest("compiler/testData/codegen/boxInline/assert/jvmInlineIntoTwoMethods.kt"); + } + @Test @TestMetadata("jvmInlineUsedAsNoinline.kt") public void testJvmInlineUsedAsNoinline() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java index 41e9fc79430..790dcb57a31 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java @@ -894,6 +894,12 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi runTest("compiler/testData/codegen/boxInline/assert/jvmDoubleInline.kt"); } + @Test + @TestMetadata("jvmInlineIntoTwoMethods.kt") + public void testJvmInlineIntoTwoMethods() throws Exception { + runTest("compiler/testData/codegen/boxInline/assert/jvmInlineIntoTwoMethods.kt"); + } + @Test @TestMetadata("jvmInlineUsedAsNoinline.kt") public void testJvmInlineUsedAsNoinline() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxInlineCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxInlineCodegenTestGenerated.java index 54cf86c6b20..37c65142b57 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxInlineCodegenTestGenerated.java @@ -894,6 +894,12 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli runTest("compiler/testData/codegen/boxInline/assert/jvmDoubleInline.kt"); } + @Test + @TestMetadata("jvmInlineIntoTwoMethods.kt") + public void testJvmInlineIntoTwoMethods() throws Exception { + runTest("compiler/testData/codegen/boxInline/assert/jvmInlineIntoTwoMethods.kt"); + } + @Test @TestMetadata("jvmInlineUsedAsNoinline.kt") public void testJvmInlineUsedAsNoinline() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrCompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrCompileKotlinAgainstInlineKotlinTestGenerated.java index c747117fcf3..3554c0785ea 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrCompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrCompileKotlinAgainstInlineKotlinTestGenerated.java @@ -894,6 +894,12 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC runTest("compiler/testData/codegen/boxInline/assert/jvmDoubleInline.kt"); } + @Test + @TestMetadata("jvmInlineIntoTwoMethods.kt") + public void testJvmInlineIntoTwoMethods() throws Exception { + runTest("compiler/testData/codegen/boxInline/assert/jvmInlineIntoTwoMethods.kt"); + } + @Test @TestMetadata("jvmInlineUsedAsNoinline.kt") public void testJvmInlineUsedAsNoinline() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmIrAgainstOldBoxInlineTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmIrAgainstOldBoxInlineTestGenerated.java index 3390bc7770c..f3cb9911317 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmIrAgainstOldBoxInlineTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmIrAgainstOldBoxInlineTestGenerated.java @@ -894,6 +894,12 @@ public class JvmIrAgainstOldBoxInlineTestGenerated extends AbstractJvmIrAgainstO runTest("compiler/testData/codegen/boxInline/assert/jvmDoubleInline.kt"); } + @Test + @TestMetadata("jvmInlineIntoTwoMethods.kt") + public void testJvmInlineIntoTwoMethods() throws Exception { + runTest("compiler/testData/codegen/boxInline/assert/jvmInlineIntoTwoMethods.kt"); + } + @Test @TestMetadata("jvmInlineUsedAsNoinline.kt") public void testJvmInlineUsedAsNoinline() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmOldAgainstIrBoxInlineTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmOldAgainstIrBoxInlineTestGenerated.java index 964439b3a43..08cd7b460d6 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmOldAgainstIrBoxInlineTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmOldAgainstIrBoxInlineTestGenerated.java @@ -894,6 +894,12 @@ public class JvmOldAgainstIrBoxInlineTestGenerated extends AbstractJvmOldAgainst runTest("compiler/testData/codegen/boxInline/assert/jvmDoubleInline.kt"); } + @Test + @TestMetadata("jvmInlineIntoTwoMethods.kt") + public void testJvmInlineIntoTwoMethods() throws Exception { + runTest("compiler/testData/codegen/boxInline/assert/jvmInlineIntoTwoMethods.kt"); + } + @Test @TestMetadata("jvmInlineUsedAsNoinline.kt") public void testJvmInlineUsedAsNoinline() throws Exception {