diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt index 205f0a95333..132f26e6855 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.codegen.optimization.common.asSequence import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful import org.jetbrains.kotlin.codegen.optimization.fixStack.peek import org.jetbrains.kotlin.codegen.optimization.fixStack.top +import org.jetbrains.kotlin.codegen.optimization.nullCheck.isCheckParameterIsNotNull import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.ParameterDescriptor @@ -39,7 +40,9 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter import org.jetbrains.org.objectweb.asm.commons.LocalVariablesSorter import org.jetbrains.org.objectweb.asm.commons.MethodRemapper import org.jetbrains.org.objectweb.asm.tree.* -import org.jetbrains.org.objectweb.asm.tree.analysis.* +import org.jetbrains.org.objectweb.asm.tree.analysis.BasicInterpreter +import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue +import org.jetbrains.org.objectweb.asm.tree.analysis.Frame import org.jetbrains.org.objectweb.asm.util.Printer import java.util.* import kotlin.math.max @@ -502,7 +505,7 @@ class MethodInliner( val toDelete = SmartSet.create() - val sources = analyzeMethodWithFunctionalArgumentInterpreter(this, processingNode, toDelete) + val sources = analyzeMethodNodeWithInterpreter(processingNode, FunctionalArgumentInterpreter(this, toDelete)) val instructions = processingNode.instructions var awaitClassReification = false @@ -671,7 +674,7 @@ class MethodInliner( if (inliningContext.state.isIrBackend) return val lambdaInfo = inliningContext.lambdaInfo ?: return if (!lambdaInfo.isSuspend) return - val sources = analyzeMethodNodeBeforeInline(processingNode) + val sources = analyzeMethodNodeWithInterpreter(processingNode, Aload0Interpreter(processingNode)) val cfg = ControlFlowGraph.build(processingNode) val aload0s = processingNode.instructions.asSequence().filter { it.opcode == Opcodes.ALOAD && it.safeAs()?.`var` == 0 } @@ -726,10 +729,17 @@ class MethodInliner( "${suspensionPoint.name}${suspensionPoint.desc} shall have 1+ parameters" } } - paramTypes.reversed().asSequence().withIndex() - .filter { it.value == languageVersionSettings.continuationAsmType() || it.value == OBJECT_TYPE } - .flatMap { frame.getStack(frame.stackSize - it.index - 1).insns.asSequence() } - .filter { it in aload0s }.let { toReplace.addAll(it) } + + for ((index, param) in paramTypes.reversed().withIndex()) { + if (param != languageVersionSettings.continuationAsmType() && param != OBJECT_TYPE) continue + val sourceIndices = (frame.getStack(frame.stackSize - index - 1) as? Aload0BasicValue)?.indices ?: continue + for (sourceIndex in sourceIndices) { + val src = processingNode.instructions[sourceIndex] + if (src in aload0s) { + toReplace.add(src) + } + } + } } // Expected pattern here: @@ -776,7 +786,7 @@ class MethodInliner( ApiVersionCallsPreprocessingMethodTransformer(targetApiVersion).transform("fake", node) } - val frames = analyzeMethodNodeWithBasicInterpreter(node) + val frames = analyzeMethodNodeWithInterpreter(node, BasicInterpreter()) val localReturnsNormalizer = LocalReturnsNormalizer() @@ -1016,51 +1026,6 @@ class MethodInliner( ) } - private fun analyzeMethodNodeWithBasicInterpreter(node: MethodNode): Array?> { - val analyzer = object : Analyzer(BasicInterpreter()) { - override fun newFrame(nLocals: Int, nStack: Int): Frame { - - return object : Frame(nLocals, nStack) { - @Throws(AnalyzerException::class) - override fun execute(insn: AbstractInsnNode, interpreter: Interpreter) { - // This can be a void non-local return from a non-void method; Frame#execute would throw and do nothing else. - if (insn.opcode == Opcodes.RETURN) return - super.execute(insn, interpreter) - } - } - } - } - - try { - return analyzer.analyze("fake", node) - } catch (e: AnalyzerException) { - throw RuntimeException(e) - } - } - - private fun analyzeMethodNodeBeforeInline(node: MethodNode): Array?> { - val analyzer = object : Analyzer(SourceInterpreter()) { - override fun newFrame(nLocals: Int, nStack: Int): Frame { - - return object : Frame(nLocals, nStack) { - @Throws(AnalyzerException::class) - override fun execute(insn: AbstractInsnNode, interpreter: Interpreter) { - // This can be a void non-local return from a non-void method; Frame#execute would throw and do nothing else. - if (insn.opcode == Opcodes.RETURN) return - super.execute(insn, interpreter) - } - } - } - } - - try { - return analyzer.analyze("fake", node) - } catch (e: AnalyzerException) { - throw RuntimeException(e) - } - - } - //remove next template: // aload x // LDC paramName @@ -1068,7 +1033,7 @@ class MethodInliner( private fun removeClosureAssertions(node: MethodNode) { val toDelete = arrayListOf() InsnSequence(node.instructions).filterIsInstance().forEach { methodInsnNode -> - if (isParameterNullabilityCheck(methodInsnNode)) { + if (methodInsnNode.isCheckParameterIsNotNull()) { val prev = methodInsnNode.previous assert(Opcodes.LDC == prev?.opcode) { "'${methodInsnNode.name}' should go after LDC but $prev" } val prevPev = methodInsnNode.previous.previous diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInlinerUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInlinerUtil.kt index 106dc0c691d..ac56f28a20f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInlinerUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInlinerUtil.kt @@ -5,12 +5,16 @@ package org.jetbrains.kotlin.codegen.inline -import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful +import org.jetbrains.kotlin.codegen.optimization.nullCheck.isCheckParameterIsNotNull +import org.jetbrains.kotlin.resolve.jvm.AsmTypes import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature import org.jetbrains.org.objectweb.asm.Opcodes -import org.jetbrains.org.objectweb.asm.tree.* +import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode +import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode +import org.jetbrains.org.objectweb.asm.tree.MethodNode +import org.jetbrains.org.objectweb.asm.tree.VarInsnNode import org.jetbrains.org.objectweb.asm.tree.analysis.* fun parameterOffsets(isStatic: Boolean, valueParameters: List): Array { @@ -56,9 +60,9 @@ fun AbstractInsnNode.getNextMeaningful(): AbstractInsnNode? { return result } -// Interpreter, that analyzes only functional arguments, to replace SourceInterpreter, since SourceInterpreter' merge has O(N²) complexity +// Interpreter, that analyzes functional arguments only, to replace SourceInterpreter, since SourceInterpreter's merge has O(N²) complexity -internal open class FunctionalArgumentValue( +internal class FunctionalArgumentValue( val functionalArgument: FunctionalArgument, basicValue: BasicValue? ) : BasicValue(basicValue?.type) { override fun toString(): String = "$functionalArgument" @@ -67,17 +71,17 @@ internal open class FunctionalArgumentValue( val BasicValue?.functionalArgument get() = (this as? FunctionalArgumentValue)?.functionalArgument -private class FunctionalArgumentInterpreter( +internal class FunctionalArgumentInterpreter( private val inliner: MethodInliner, private val toDelete: MutableSet -) : BasicInterpreter(Opcodes.ASM5) { +) : BasicInterpreter(Opcodes.API_VERSION) { override fun unaryOperation(insn: AbstractInsnNode, value: BasicValue): BasicValue? = markInstructionIfNeeded(insn, super.unaryOperation(insn, value)) override fun copyOperation(insn: AbstractInsnNode, value: BasicValue?): BasicValue? { val basicValue = super.copyOperation(insn, value) - // Paramter checks are processed separately - if (insn.next?.opcode == Opcodes.LDC && isParameterNullabilityCheck(insn.next?.next)) { + // Parameter checks are processed separately + if (insn.next?.opcode == Opcodes.LDC && insn.next?.next?.isCheckParameterIsNotNull() == true) { return basicValue } if (value.functionalArgument is LambdaInfo) { @@ -109,24 +113,35 @@ private class FunctionalArgumentInterpreter( else super.merge(v, w) } -fun isParameterNullabilityCheck(methodInsnNode: AbstractInsnNode?): Boolean = - methodInsnNode is MethodInsnNode && methodInsnNode.owner == IntrinsicMethods.INTRINSICS_CLASS_NAME && - (methodInsnNode.name == "checkParameterIsNotNull" || methodInsnNode.name == "checkNotNullParameter") +// Interpreter, that analyzes only ALOAD_0s, which are used as continuation arguments -internal fun analyzeMethodWithFunctionalArgumentInterpreter( - inliner: MethodInliner, - node: MethodNode, - toDelete: MutableSet -): Array?> { - val analyzer = object : Analyzer(FunctionalArgumentInterpreter(inliner, toDelete)) { +internal class Aload0BasicValue private constructor(val indices: Set) : BasicValue(AsmTypes.OBJECT_TYPE) { + constructor(i: Int) : this(setOf(i)) {} + + operator fun plus(other: Aload0BasicValue) = Aload0BasicValue(indices + other.indices) +} + +internal class Aload0Interpreter(private val node: MethodNode) : BasicInterpreter(Opcodes.API_VERSION) { + override fun copyOperation(insn: AbstractInsnNode, value: BasicValue?): BasicValue? = + when { + insn.isAload0() -> Aload0BasicValue(node.instructions.indexOf(insn)) + insn.opcode == Opcodes.ALOAD -> if (value == null) null else BasicValue(value.type) + else -> super.copyOperation(insn, value) + } + + override fun merge(v: BasicValue?, w: BasicValue?): BasicValue = + if (v is Aload0BasicValue && w is Aload0BasicValue) v + w else super.merge(v, w) +} + +internal fun AbstractInsnNode.isAload0() = opcode == Opcodes.ALOAD && (this as VarInsnNode).`var` == 0 + +internal fun analyzeMethodNodeWithInterpreter(node: MethodNode, interpreter: BasicInterpreter): Array?> { + val analyzer = object : Analyzer(interpreter) { override fun newFrame(nLocals: Int, nStack: Int): Frame { return object : Frame(nLocals, nStack) { @Throws(AnalyzerException::class) override fun execute(insn: AbstractInsnNode, interpreter: Interpreter) { - if (node.name == "waitForEx\$default" && node.instructions.indexOf(insn) == 18) { - {}() - } // This can be a void non-local return from a non-void method; Frame#execute would throw and do nothing else. if (insn.opcode == Opcodes.RETURN) return super.execute(insn, interpreter) diff --git a/compiler/testData/codegen/boxInline/complexStack/breaContinuekInInlineLambdaArgument.kt b/compiler/testData/codegen/boxInline/complexStack/breaContinuekInInlineLambdaArgument.kt new file mode 100644 index 00000000000..826cd4ced56 --- /dev/null +++ b/compiler/testData/codegen/boxInline/complexStack/breaContinuekInInlineLambdaArgument.kt @@ -0,0 +1,28 @@ +// WITH_RUNTIME +// FILE: 1.kt +inline fun List.forEachNotNull(s: String, fn: (String, String) -> Unit) { + for (x in this) { + fn(s, x ?: continue) + } +} + +inline fun List.forEachUntilNull(s: String, fn: (String, String) -> Unit) { + for (x in this) { + fn(s, x ?: break) + } +} +// FILE: 2.kt +fun box(): String { + var res = "" + listOf("O", null, "K").forEachNotNull("|") { a, b -> + res += a + b + } + if (res != "|O|K") return res + res = "" + + listOf("O", null, "K").forEachUntilNull("|") { a, b -> + res += a + b + } + if (res != "|O") return res + return "OK" +} diff --git a/compiler/testData/codegen/boxInline/complexStack/spillConstructorArgumentsAndInlineLambdaParameter.kt b/compiler/testData/codegen/boxInline/complexStack/spillConstructorArgumentsAndInlineLambdaParameter.kt new file mode 100644 index 00000000000..f13a8c588b6 --- /dev/null +++ b/compiler/testData/codegen/boxInline/complexStack/spillConstructorArgumentsAndInlineLambdaParameter.kt @@ -0,0 +1,22 @@ +// FILE: 1.kt +class A(val s: String) + +inline fun inlineMe(limit: Int, c: (String) -> String): A { + var index = 0 + var res: A? + while (true) { + res = A(c(try { + throw IllegalStateException("") + } catch (ignored: Throwable) { + "OK" + }) + ) + if (index++ == limit) break + } + return res!! +} + +// FILE: 2.kt +fun box(): String { + return inlineMe(1) { "OK" }.s +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java index 23809b4eba7..a0f94c5ce2d 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java @@ -1111,6 +1111,11 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo runTest("compiler/testData/codegen/boxInline/complexStack/asCheck2.kt"); } + @TestMetadata("breaContinuekInInlineLambdaArgument.kt") + public void testBreaContinuekInInlineLambdaArgument() throws Exception { + runTest("compiler/testData/codegen/boxInline/complexStack/breaContinuekInInlineLambdaArgument.kt"); + } + @TestMetadata("simple.kt") public void testSimple() throws Exception { runTest("compiler/testData/codegen/boxInline/complexStack/simple.kt"); @@ -1135,6 +1140,11 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo public void testSimpleExtension() throws Exception { runTest("compiler/testData/codegen/boxInline/complexStack/simpleExtension.kt"); } + + @TestMetadata("spillConstructorArgumentsAndInlineLambdaParameter.kt") + public void testSpillConstructorArgumentsAndInlineLambdaParameter() throws Exception { + runTest("compiler/testData/codegen/boxInline/complexStack/spillConstructorArgumentsAndInlineLambdaParameter.kt"); + } } @TestMetadata("compiler/testData/codegen/boxInline/contracts") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java index 525e8d03ff6..1189ce5a9fc 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java @@ -1111,6 +1111,11 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi runTest("compiler/testData/codegen/boxInline/complexStack/asCheck2.kt"); } + @TestMetadata("breaContinuekInInlineLambdaArgument.kt") + public void testBreaContinuekInInlineLambdaArgument() throws Exception { + runTest("compiler/testData/codegen/boxInline/complexStack/breaContinuekInInlineLambdaArgument.kt"); + } + @TestMetadata("simple.kt") public void testSimple() throws Exception { runTest("compiler/testData/codegen/boxInline/complexStack/simple.kt"); @@ -1135,6 +1140,11 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi public void testSimpleExtension() throws Exception { runTest("compiler/testData/codegen/boxInline/complexStack/simpleExtension.kt"); } + + @TestMetadata("spillConstructorArgumentsAndInlineLambdaParameter.kt") + public void testSpillConstructorArgumentsAndInlineLambdaParameter() throws Exception { + runTest("compiler/testData/codegen/boxInline/complexStack/spillConstructorArgumentsAndInlineLambdaParameter.kt"); + } } @TestMetadata("compiler/testData/codegen/boxInline/contracts") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxInlineCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxInlineCodegenTestGenerated.java index e28fea66adb..c7dea6090f6 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxInlineCodegenTestGenerated.java @@ -1111,6 +1111,11 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli runTest("compiler/testData/codegen/boxInline/complexStack/asCheck2.kt"); } + @TestMetadata("breaContinuekInInlineLambdaArgument.kt") + public void testBreaContinuekInInlineLambdaArgument() throws Exception { + runTest("compiler/testData/codegen/boxInline/complexStack/breaContinuekInInlineLambdaArgument.kt"); + } + @TestMetadata("simple.kt") public void testSimple() throws Exception { runTest("compiler/testData/codegen/boxInline/complexStack/simple.kt"); @@ -1135,6 +1140,11 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli public void testSimpleExtension() throws Exception { runTest("compiler/testData/codegen/boxInline/complexStack/simpleExtension.kt"); } + + @TestMetadata("spillConstructorArgumentsAndInlineLambdaParameter.kt") + public void testSpillConstructorArgumentsAndInlineLambdaParameter() throws Exception { + runTest("compiler/testData/codegen/boxInline/complexStack/spillConstructorArgumentsAndInlineLambdaParameter.kt"); + } } @TestMetadata("compiler/testData/codegen/boxInline/contracts") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstInlineKotlinTestGenerated.java index 61510e62b84..021620dd8f8 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstInlineKotlinTestGenerated.java @@ -1111,6 +1111,11 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC runTest("compiler/testData/codegen/boxInline/complexStack/asCheck2.kt"); } + @TestMetadata("breaContinuekInInlineLambdaArgument.kt") + public void testBreaContinuekInInlineLambdaArgument() throws Exception { + runTest("compiler/testData/codegen/boxInline/complexStack/breaContinuekInInlineLambdaArgument.kt"); + } + @TestMetadata("simple.kt") public void testSimple() throws Exception { runTest("compiler/testData/codegen/boxInline/complexStack/simple.kt"); @@ -1135,6 +1140,11 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC public void testSimpleExtension() throws Exception { runTest("compiler/testData/codegen/boxInline/complexStack/simpleExtension.kt"); } + + @TestMetadata("spillConstructorArgumentsAndInlineLambdaParameter.kt") + public void testSpillConstructorArgumentsAndInlineLambdaParameter() throws Exception { + runTest("compiler/testData/codegen/boxInline/complexStack/spillConstructorArgumentsAndInlineLambdaParameter.kt"); + } } @TestMetadata("compiler/testData/codegen/boxInline/contracts") diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenInlineTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenInlineTestGenerated.java index bd3ed321a1c..eadc25474f3 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenInlineTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenInlineTestGenerated.java @@ -956,6 +956,11 @@ public class IrJsCodegenInlineTestGenerated extends AbstractIrJsCodegenInlineTes runTest("compiler/testData/codegen/boxInline/complexStack/asCheck2.kt"); } + @TestMetadata("breaContinuekInInlineLambdaArgument.kt") + public void testBreaContinuekInInlineLambdaArgument() throws Exception { + runTest("compiler/testData/codegen/boxInline/complexStack/breaContinuekInInlineLambdaArgument.kt"); + } + @TestMetadata("simple.kt") public void testSimple() throws Exception { runTest("compiler/testData/codegen/boxInline/complexStack/simple.kt"); @@ -980,6 +985,11 @@ public class IrJsCodegenInlineTestGenerated extends AbstractIrJsCodegenInlineTes public void testSimpleExtension() throws Exception { runTest("compiler/testData/codegen/boxInline/complexStack/simpleExtension.kt"); } + + @TestMetadata("spillConstructorArgumentsAndInlineLambdaParameter.kt") + public void testSpillConstructorArgumentsAndInlineLambdaParameter() throws Exception { + runTest("compiler/testData/codegen/boxInline/complexStack/spillConstructorArgumentsAndInlineLambdaParameter.kt"); + } } @TestMetadata("compiler/testData/codegen/boxInline/contracts") diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenInlineTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenInlineTestGenerated.java index ccba28b4880..15b93782473 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenInlineTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenInlineTestGenerated.java @@ -956,6 +956,11 @@ public class JsCodegenInlineTestGenerated extends AbstractJsCodegenInlineTest { runTest("compiler/testData/codegen/boxInline/complexStack/asCheck2.kt"); } + @TestMetadata("breaContinuekInInlineLambdaArgument.kt") + public void testBreaContinuekInInlineLambdaArgument() throws Exception { + runTest("compiler/testData/codegen/boxInline/complexStack/breaContinuekInInlineLambdaArgument.kt"); + } + @TestMetadata("simple.kt") public void testSimple() throws Exception { runTest("compiler/testData/codegen/boxInline/complexStack/simple.kt"); @@ -980,6 +985,11 @@ public class JsCodegenInlineTestGenerated extends AbstractJsCodegenInlineTest { public void testSimpleExtension() throws Exception { runTest("compiler/testData/codegen/boxInline/complexStack/simpleExtension.kt"); } + + @TestMetadata("spillConstructorArgumentsAndInlineLambdaParameter.kt") + public void testSpillConstructorArgumentsAndInlineLambdaParameter() throws Exception { + runTest("compiler/testData/codegen/boxInline/complexStack/spillConstructorArgumentsAndInlineLambdaParameter.kt"); + } } @TestMetadata("compiler/testData/codegen/boxInline/contracts")