Support finally blocks in non-local returns

This commit is contained in:
Mikhael Bogdanov
2019-04-04 17:08:16 +02:00
parent 4c59d161d4
commit 30aeb8dc0a
42 changed files with 146 additions and 137 deletions
@@ -41,6 +41,7 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionLiteral
import org.jetbrains.kotlin.types.expressions.LabelResolver
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
@@ -279,7 +280,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
val labels = sourceCompiler.getContextLabels()
val infos = MethodInliner.processReturns(adapter, ReturnLabelOwner { labels.contains(it) }, true, null)
sourceCompiler.generateAndInsertFinallyBlocks(
generateAndInsertFinallyBlocks(
adapter, infos, (remapper.remap(parameters.argsSizeOnStack + 1).value as StackValue.Local).index
)
if (!sourceCompiler.isFinallyMarkerRequired()) {
@@ -299,6 +300,71 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
return result
}
fun generateAndInsertFinallyBlocks(
intoNode: MethodNode,
insertPoints: List<MethodInliner.PointForExternalFinallyBlocks>,
offsetForFinallyLocalVar: Int
) {
if (!sourceCompiler.hasFinallyBlocks()) return
val extensionPoints = HashMap<AbstractInsnNode, MethodInliner.PointForExternalFinallyBlocks>()
for (insertPoint in insertPoints) {
extensionPoints.put(insertPoint.beforeIns, insertPoint)
}
val processor = DefaultProcessor(intoNode, offsetForFinallyLocalVar)
var curFinallyDepth = 0
var curInstr: AbstractInsnNode? = intoNode.instructions.first
while (curInstr != null) {
processor.processInstruction(curInstr, true)
if (isFinallyStart(curInstr)) {
//TODO depth index calc could be more precise
curFinallyDepth = getConstant(curInstr.previous)
}
val extension = extensionPoints[curInstr]
if (extension != null) {
val start = Label()
val finallyNode = createEmptyMethodNode()
finallyNode.visitLabel(start)
val finallyCodegen =
sourceCompiler.createCodegenForExternalFinallyBlockGenerationOnNonLocalReturn(finallyNode, curFinallyDepth)
val frameMap = finallyCodegen.frameMap
val mark = frameMap.mark()
var marker = -1
val intervals = processor.localVarsMetaInfo.currentIntervals
for (interval in intervals) {
marker = Math.max(interval.node.index + 1, marker)
}
while (frameMap.currentSize < Math.max(processor.nextFreeLocalIndex, offsetForFinallyLocalVar + marker)) {
frameMap.enterTemp(Type.INT_TYPE)
}
sourceCompiler.generateFinallyBlocksIfNeeded(finallyCodegen, extension.returnType, extension.finallyIntervalEnd.label)
//Exception table for external try/catch/finally blocks will be generated in original codegen after exiting this method
insertNodeBefore(finallyNode, intoNode, curInstr)
val splitBy = SimpleInterval(start.info as LabelNode, extension.finallyIntervalEnd)
processor.tryBlocksMetaInfo.splitAndRemoveCurrentIntervals(splitBy, true)
//processor.getLocalVarsMetaInfo().splitAndRemoveIntervalsFromCurrents(splitBy);
mark.dropTo()
}
curInstr = curInstr.next
}
processor.substituteTryBlockNodes(intoNode)
//processor.substituteLocalVarTable(intoNode);
}
protected abstract fun generateAssertFieldIfNeeded(info: RootInliningContext)
private fun isInlinedToInlineFunInKotlinRuntime(): Boolean {
@@ -28,10 +28,7 @@ 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.Method
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.tree.LabelNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode
import java.util.*
import kotlin.properties.Delegates
interface SourceCompilerForInline {
@@ -64,11 +61,14 @@ interface SourceCompilerForInline {
asmMethod: Method
): SMAPAndMethodNode
fun generateAndInsertFinallyBlocks(
intoNode: MethodNode,
insertPoints: List<MethodInliner.PointForExternalFinallyBlocks>,
offsetForFinallyLocalVar: Int
)
fun hasFinallyBlocks(): Boolean
fun createCodegenForExternalFinallyBlockGenerationOnNonLocalReturn(
finallyNode: MethodNode,
curFinallyDepth: Int
): BaseExpressionCodegen
fun generateFinallyBlocksIfNeeded(finallyCodegen: BaseExpressionCodegen, returnType: Type, afterReturnLabel: Label)
fun isCallInsideSameModuleAsDeclared(functionDescriptor: FunctionDescriptor): Boolean
@@ -84,7 +84,8 @@ interface SourceCompilerForInline {
}
class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, override val callElement: KtElement) : SourceCompilerForInline {
class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, override val callElement: KtElement) :
SourceCompilerForInline {
override val state = codegen.state
@@ -314,74 +315,21 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
return SMAPAndMethodNode(node, smap)
}
override fun generateAndInsertFinallyBlocks(
intoNode: MethodNode,
insertPoints: List<MethodInliner.PointForExternalFinallyBlocks>,
offsetForFinallyLocalVar: Int
) {
if (!codegen.hasFinallyBlocks()) return
override fun hasFinallyBlocks() = codegen.hasFinallyBlocks()
val extensionPoints = HashMap<AbstractInsnNode, MethodInliner.PointForExternalFinallyBlocks>()
for (insertPoint in insertPoints) {
extensionPoints.put(insertPoint.beforeIns, insertPoint)
}
val processor = DefaultProcessor(intoNode, offsetForFinallyLocalVar)
var curFinallyDepth = 0
var curInstr: AbstractInsnNode? = intoNode.instructions.first
while (curInstr != null) {
processor.processInstruction(curInstr, true)
if (isFinallyStart(curInstr)) {
//TODO depth index calc could be more precise
curFinallyDepth = getConstant(curInstr.previous)
}
val extension = extensionPoints[curInstr]
if (extension != null) {
val start = Label()
val finallyNode = createEmptyMethodNode()
finallyNode.visitLabel(start)
val finallyCodegen = ExpressionCodegen(
finallyNode, codegen.frameMap, codegen.returnType,
codegen.getContext(), codegen.state, codegen.parentCodegen
)
finallyCodegen.addBlockStackElementsForNonLocalReturns(codegen.blockStackElements, curFinallyDepth)
val frameMap = finallyCodegen.frameMap
val mark = frameMap.mark()
var marker = -1
val intervals = processor.localVarsMetaInfo.currentIntervals
for (interval in intervals) {
marker = Math.max(interval.node.index + 1, marker)
}
while (frameMap.currentSize < Math.max(processor.nextFreeLocalIndex, offsetForFinallyLocalVar + marker)) {
frameMap.enterTemp(Type.INT_TYPE)
}
finallyCodegen.generateFinallyBlocksIfNeeded(extension.returnType, null, extension.finallyIntervalEnd.label)
//Exception table for external try/catch/finally blocks will be generated in original codegen after exiting this method
insertNodeBefore(finallyNode, intoNode, curInstr)
val splitBy = SimpleInterval(start.info as LabelNode, extension.finallyIntervalEnd)
processor.tryBlocksMetaInfo.splitAndRemoveCurrentIntervals(splitBy, true)
//processor.getLocalVarsMetaInfo().splitAndRemoveIntervalsFromCurrents(splitBy);
mark.dropTo()
}
curInstr = curInstr.next
}
processor.substituteTryBlockNodes(intoNode)
//processor.substituteLocalVarTable(intoNode);
override fun generateFinallyBlocksIfNeeded(finallyCodegen: BaseExpressionCodegen, returnType: Type, afterReturnLabel: Label) {
require(finallyCodegen is ExpressionCodegen)
finallyCodegen.generateFinallyBlocksIfNeeded(returnType, null, afterReturnLabel)
}
override fun createCodegenForExternalFinallyBlockGenerationOnNonLocalReturn(finallyNode: MethodNode, curFinallyDepth: Int) =
ExpressionCodegen(
finallyNode, codegen.frameMap, codegen.returnType,
codegen.getContext(), codegen.state, codegen.parentCodegen
).also {
it.addBlockStackElementsForNonLocalReturns(codegen.blockStackElements, curFinallyDepth)
}
override fun isCallInsideSameModuleAsDeclared(functionDescriptor: FunctionDescriptor): Boolean {
return JvmCodegenUtil.isCallInsideSameModuleAsDeclared(functionDescriptor, codegen.getContext(), codegen.state.outDirectory)
}
@@ -283,7 +283,7 @@ internal fun getReturnType(opcode: Int): Type {
}
}
internal fun insertNodeBefore(from: MethodNode, to: MethodNode, beforeNode: AbstractInsnNode) {
fun insertNodeBefore(from: MethodNode, to: MethodNode, beforeNode: AbstractInsnNode) {
val iterator = from.instructions.iterator()
while (iterator.hasNext()) {
val next = iterator.next()
@@ -291,7 +291,7 @@ internal fun insertNodeBefore(from: MethodNode, to: MethodNode, beforeNode: Abst
}
}
internal fun createEmptyMethodNode() = MethodNode(Opcodes.API_VERSION, 0, "fake", "()V", null, null)
fun createEmptyMethodNode() = MethodNode(Opcodes.API_VERSION, 0, "fake", "()V", null, null)
internal fun createFakeContinuationMethodNodeForInline(): MethodNode {
val methodNode = createEmptyMethodNode()
@@ -347,16 +347,16 @@ internal fun buildClassReaderByInternalName(state: GenerationState, internalName
return ClassReader(file.contentsToByteArray())
}
internal fun generateFinallyMarker(v: InstructionAdapter, depth: Int, start: Boolean) {
fun generateFinallyMarker(v: InstructionAdapter, depth: Int, start: Boolean) {
v.iconst(depth)
v.invokestatic(INLINE_MARKER_CLASS_NAME, if (start) INLINE_MARKER_FINALLY_START else INLINE_MARKER_FINALLY_END, "(I)V", false)
}
internal fun isFinallyEnd(node: AbstractInsnNode) = isFinallyMarker(node, INLINE_MARKER_FINALLY_END)
fun isFinallyEnd(node: AbstractInsnNode) = isFinallyMarker(node, INLINE_MARKER_FINALLY_END)
internal fun isFinallyStart(node: AbstractInsnNode) = isFinallyMarker(node, INLINE_MARKER_FINALLY_START)
fun isFinallyStart(node: AbstractInsnNode) = isFinallyMarker(node, INLINE_MARKER_FINALLY_START)
internal fun isFinallyMarker(node: AbstractInsnNode?): Boolean = node != null && (isFinallyStart(node) || isFinallyEnd(node))
fun isFinallyMarker(node: AbstractInsnNode?): Boolean = node != null && (isFinallyStart(node) || isFinallyEnd(node))
private fun isFinallyMarker(node: AbstractInsnNode, name: String): Boolean {
if (node !is MethodInsnNode) return false
@@ -365,7 +365,7 @@ private fun isFinallyMarker(node: AbstractInsnNode, name: String): Boolean {
internal fun isFinallyMarkerRequired(context: MethodContext) = context.isInlineMethodContext || context is InlineLambdaContext
internal fun getConstant(ins: AbstractInsnNode): Int {
fun getConstant(ins: AbstractInsnNode): Int {
val opcode = ins.opcode
return when (opcode) {
in Opcodes.ICONST_0..Opcodes.ICONST_5 -> opcode - Opcodes.ICONST_0
@@ -109,9 +109,12 @@ class ExpressionCodegen(
val irFunction: IrFunction,
val frame: IrFrameMap,
val mv: InstructionAdapter,
val classCodegen: ClassCodegen
val classCodegen: ClassCodegen,
val isInlineLambda: Boolean = false
) : IrElementVisitor<StackValue, BlockInfo>, BaseExpressionCodegen {
var finallyDepth = 0
/*TODO*/
val intrinsics = IrIntrinsicMethods(classCodegen.context.irBuiltIns)
@@ -331,7 +334,7 @@ class ExpressionCodegen(
}
fun generateCall(expression: IrMemberAccessExpression, callable: Callable, data: BlockInfo, isSuperCall: Boolean = false): StackValue {
val callGenerator = getOrCreateCallGenerator(expression, expression.descriptor)
val callGenerator = getOrCreateCallGenerator(expression, expression.descriptor, data)
val receiver = expression.dispatchReceiver
receiver?.apply {
@@ -1123,7 +1126,17 @@ class ExpressionCodegen(
private fun genFinallyBlock(tryInfo: TryInfo, tryCatchBlockEnd: Label?, afterJumpLabel: Label?, data: BlockInfo) {
assert(tryInfo.gaps.size % 2 == 0) { "Finally block gaps are inconsistent" }
tryInfo.gaps.add(markNewLabel())
finallyDepth++
if (isFinallyMarkerRequired()) {
generateFinallyMarker(mv, finallyDepth, true)
}
gen(tryInfo.tryBlock.finallyExpression!!, data).discard()
if (isFinallyMarkerRequired()) {
generateFinallyMarker(mv, finallyDepth, false)
}
finallyDepth--
if (tryCatchBlockEnd != null) {
tryInfo.tryBlock.finallyExpression!!.markLineNumber(startOffset = false)
mv.goTo(tryCatchBlockEnd)
@@ -1131,7 +1144,7 @@ class ExpressionCodegen(
tryInfo.gaps.add(afterJumpLabel ?: markNewLabel())
}
private fun generateFinallyBlocksIfNeeded(returnType: Type, afterReturnLabel: Label, data: BlockInfo) {
fun generateFinallyBlocksIfNeeded(returnType: Type, afterReturnLabel: Label, data: BlockInfo) {
if (data.hasFinallyBlocks()) {
if (Type.VOID_TYPE != returnType) {
val returnValIndex = frame.enterTemp(returnType)
@@ -1226,7 +1239,8 @@ class ExpressionCodegen(
descriptor: CallableDescriptor,
element: IrMemberAccessExpression?,
typeParameterMappings: TypeParameterMappings?,
isDefaultCompilation: Boolean
isDefaultCompilation: Boolean,
data: BlockInfo
): IrCallGenerator {
if (element == null) return IrCallGenerator.DefaultCallGenerator
@@ -1240,13 +1254,14 @@ class ExpressionCodegen(
return if (isDefaultCompilation) {
TODO()
} else {
IrInlineCodegen(this, state, original, typeParameterMappings!!, IrSourceCompilerForInline(state, element, this))
IrInlineCodegen(this, state, original, typeParameterMappings!!, IrSourceCompilerForInline(state, element, this, data))
}
}
internal fun getOrCreateCallGenerator(
memberAccessExpression: IrMemberAccessExpression,
descriptor: CallableDescriptor
descriptor: CallableDescriptor,
data: BlockInfo
): IrCallGenerator {
val typeArguments =
if (memberAccessExpression.typeArgumentsCount == 0) {
@@ -1280,7 +1295,7 @@ class ExpressionCodegen(
}
}
return getOrCreateCallGenerator(descriptor, memberAccessExpression, mappings, false)
return getOrCreateCallGenerator(descriptor, memberAccessExpression, mappings, false, data)
}
override val frameMap: IrFrameMap
@@ -1311,6 +1326,10 @@ class ExpressionCodegen(
override fun markLineNumberAfterInlineIfNeeded() {
//TODO
}
fun isFinallyMarkerRequired(): Boolean {
return irFunction.isInline || isInlineLambda
}
}
fun DefaultCallArgs.generateOnStackIfNeeded(callGenerator: IrCallGenerator, isConstructor: Boolean, codegen: ExpressionCodegen): Boolean {
@@ -27,7 +27,11 @@ import org.jetbrains.org.objectweb.asm.MethodVisitor
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
open class FunctionCodegen(private val irFunction: IrFunction, private val classCodegen: ClassCodegen) {
open class FunctionCodegen(
private val irFunction: IrFunction,
private val classCodegen: ClassCodegen,
private val isInlineLambda: Boolean = false
) {
val state = classCodegen.state
@@ -56,7 +60,7 @@ open class FunctionCodegen(private val irFunction: IrFunction, private val class
methodVisitor.visitEnd()
} else {
val frameMap = createFrameMapWithReceivers(classCodegen.state, irFunction, signature)
ExpressionCodegen(irFunction, frameMap, InstructionAdapter(methodVisitor), classCodegen).generate()
ExpressionCodegen(irFunction, frameMap, InstructionAdapter(methodVisitor), classCodegen, isInlineLambda).generate()
}
return signature
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.backend.jvm.codegen
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.codegen.BaseExpressionCodegen
import org.jetbrains.kotlin.codegen.ClassBuilder
import org.jetbrains.kotlin.codegen.OwnerKind
import org.jetbrains.kotlin.codegen.inline.*
@@ -37,13 +38,15 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.org.objectweb.asm.*
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import org.jetbrains.org.objectweb.asm.commons.Method
import org.jetbrains.org.objectweb.asm.tree.MethodNode
class IrSourceCompilerForInline(
override val state: GenerationState,
override val callElement: IrMemberAccessExpression,
private val codegen: ExpressionCodegen
private val codegen: ExpressionCodegen,
private val data: BlockInfo
) : SourceCompilerForInline {
@@ -71,7 +74,7 @@ class IrSourceCompilerForInline(
override fun generateLambdaBody(adapter: MethodVisitor, jvmMethodSignature: JvmMethodSignature, lambdaInfo: ExpressionLambda): SMAP {
lambdaInfo as? IrExpressionLambdaImpl ?: error("Expecting ir lambda, but $lambdaInfo")
val functionCodegen = object : FunctionCodegen(lambdaInfo.function, codegen.classCodegen) {
val functionCodegen = object : FunctionCodegen(lambdaInfo.function, codegen.classCodegen, true) {
override fun createMethod(flags: Int, signature: JvmMethodGenericSignature): MethodVisitor {
return adapter
}
@@ -135,22 +138,27 @@ class IrSourceCompilerForInline(
return SMAPAndMethodNode(node!!, SMAP(fakeClassCodegen.getOrCreateSourceMapper().resultMappings))
}
override fun generateAndInsertFinallyBlocks(
intoNode: MethodNode,
insertPoints: List<MethodInliner.PointForExternalFinallyBlocks>,
offsetForFinallyLocalVar: Int
) {
//TODO("not implemented")
override fun hasFinallyBlocks() = data.hasFinallyBlocks()
override fun generateFinallyBlocksIfNeeded(finallyCodegen: BaseExpressionCodegen, returnType: Type, afterReturnLabel: Label) {
require(finallyCodegen is ExpressionCodegen)
finallyCodegen.generateFinallyBlocksIfNeeded(returnType, afterReturnLabel, data)
}
override fun createCodegenForExternalFinallyBlockGenerationOnNonLocalReturn(finallyNode: MethodNode, curFinallyDepth: Int) =
ExpressionCodegen(
codegen.irFunction, codegen.frame, InstructionAdapter(finallyNode), codegen.classCodegen, codegen.isInlineLambda
).also {
it.finallyDepth = curFinallyDepth
}
override fun isCallInsideSameModuleAsDeclared(functionDescriptor: FunctionDescriptor): Boolean {
//TODO("not implemented")
return true
}
override fun isFinallyMarkerRequired(): Boolean {
//TODO("not implemented")
return false
return codegen.isFinallyMarkerRequired()
}
override val compilationContextDescriptor: DeclarationDescriptor
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
inline fun test(s: () -> Int): Int =
try {
val i = s()
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
// WITH_RUNTIME
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
// WITH_RUNTIME
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
//WITH_RUNTIME
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// NO_CHECK_LAMBDA_INLINING
// FILE: 1.kt
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// NO_CHECK_LAMBDA_INLINING
// FILE: 1.kt
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
inline fun <R> test(s: () -> R): R {