Replace last SourceInterpreter with specific one in inliner
#KT-38489: Fixed
This commit is contained in:
@@ -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<AbstractInsnNode>()
|
||||
|
||||
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<VarInsnNode>()?.`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<Frame<BasicValue>?> {
|
||||
val analyzer = object : Analyzer<BasicValue>(BasicInterpreter()) {
|
||||
override fun newFrame(nLocals: Int, nStack: Int): Frame<BasicValue> {
|
||||
|
||||
return object : Frame<BasicValue>(nLocals, nStack) {
|
||||
@Throws(AnalyzerException::class)
|
||||
override fun execute(insn: AbstractInsnNode, interpreter: Interpreter<BasicValue>) {
|
||||
// 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<Frame<SourceValue>?> {
|
||||
val analyzer = object : Analyzer<SourceValue>(SourceInterpreter()) {
|
||||
override fun newFrame(nLocals: Int, nStack: Int): Frame<SourceValue> {
|
||||
|
||||
return object : Frame<SourceValue>(nLocals, nStack) {
|
||||
@Throws(AnalyzerException::class)
|
||||
override fun execute(insn: AbstractInsnNode, interpreter: Interpreter<SourceValue>) {
|
||||
// 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<AbstractInsnNode>()
|
||||
InsnSequence(node.instructions).filterIsInstance<MethodInsnNode>().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
|
||||
|
||||
@@ -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<JvmMethodParameterSignature>): Array<Int> {
|
||||
@@ -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<AbstractInsnNode>
|
||||
) : 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<AbstractInsnNode>
|
||||
): Array<out Frame<BasicValue>?> {
|
||||
val analyzer = object : Analyzer<BasicValue>(FunctionalArgumentInterpreter(inliner, toDelete)) {
|
||||
internal class Aload0BasicValue private constructor(val indices: Set<Int>) : 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<out Frame<BasicValue>?> {
|
||||
val analyzer = object : Analyzer<BasicValue>(interpreter) {
|
||||
override fun newFrame(nLocals: Int, nStack: Int): Frame<BasicValue> {
|
||||
|
||||
return object : Frame<BasicValue>(nLocals, nStack) {
|
||||
@Throws(AnalyzerException::class)
|
||||
override fun execute(insn: AbstractInsnNode, interpreter: Interpreter<BasicValue>) {
|
||||
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)
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
// WITH_RUNTIME
|
||||
// FILE: 1.kt
|
||||
inline fun List<String?>.forEachNotNull(s: String, fn: (String, String) -> Unit) {
|
||||
for (x in this) {
|
||||
fn(s, x ?: continue)
|
||||
}
|
||||
}
|
||||
|
||||
inline fun List<String?>.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"
|
||||
}
|
||||
+22
@@ -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
|
||||
}
|
||||
+10
@@ -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")
|
||||
|
||||
Generated
+10
@@ -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")
|
||||
|
||||
+10
@@ -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")
|
||||
|
||||
Generated
+10
@@ -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")
|
||||
|
||||
Generated
+10
@@ -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")
|
||||
|
||||
+10
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user