Support default lambda inlining in IR
This commit is contained in:
@@ -130,16 +130,16 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
|||||||
|
|
||||||
fun performInline(
|
fun performInline(
|
||||||
typeArguments: List<TypeParameterMarker>?,
|
typeArguments: List<TypeParameterMarker>?,
|
||||||
callDefault: Boolean,
|
inlineDefaultLambdas: Boolean,
|
||||||
typeSystem: TypeSystemCommonBackendContext,
|
mapDefaultSignature: Boolean,
|
||||||
codegen: BaseExpressionCodegen
|
typeSystem: TypeSystemCommonBackendContext
|
||||||
) {
|
) {
|
||||||
var nodeAndSmap: SMAPAndMethodNode? = null
|
var nodeAndSmap: SMAPAndMethodNode? = null
|
||||||
try {
|
try {
|
||||||
nodeAndSmap = createInlineMethodNode(
|
nodeAndSmap = createInlineMethodNode(
|
||||||
functionDescriptor, methodOwner, jvmSignature, callDefault, typeArguments, typeSystem, state, sourceCompiler
|
functionDescriptor, methodOwner, jvmSignature, mapDefaultSignature, typeArguments, typeSystem, state, sourceCompiler
|
||||||
)
|
)
|
||||||
endCall(inlineCall(nodeAndSmap, callDefault))
|
endCall(inlineCall(nodeAndSmap, inlineDefaultLambdas))
|
||||||
} catch (e: CompilationException) {
|
} catch (e: CompilationException) {
|
||||||
throw e
|
throw e
|
||||||
} catch (e: InlineException) {
|
} catch (e: InlineException) {
|
||||||
@@ -210,16 +210,12 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
|||||||
?: error("No stack value for continuation parameter of suspend function")
|
?: error("No stack value for continuation parameter of suspend function")
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun inlineCall(nodeAndSmap: SMAPAndMethodNode, callDefault: Boolean): InlineResult {
|
protected fun inlineCall(nodeAndSmap: SMAPAndMethodNode, inlineDefaultLambda: Boolean): InlineResult {
|
||||||
assert(delayedHiddenWriting == null) { "'putHiddenParamsIntoLocals' should be called after 'processAndPutHiddenParameters(true)'" }
|
assert(delayedHiddenWriting == null) { "'putHiddenParamsIntoLocals' should be called after 'processAndPutHiddenParameters(true)'" }
|
||||||
defaultSourceMapper.callSiteMarker = CallSiteMarker(codegen.lastLineNumber)
|
defaultSourceMapper.callSiteMarker = CallSiteMarker(codegen.lastLineNumber)
|
||||||
val node = nodeAndSmap.node
|
val node = nodeAndSmap.node
|
||||||
if (callDefault) {
|
if (inlineDefaultLambda) {
|
||||||
val defaultLambdas = expandMaskConditionsAndUpdateVariableNodes(
|
for (lambda in extractDefaultLambdas(node)) {
|
||||||
node, maskStartIndex, maskValues, methodHandleInDefaultMethodIndex,
|
|
||||||
extractDefaultLambdaOffsetAndDescriptor(jvmSignature, functionDescriptor)
|
|
||||||
)
|
|
||||||
for (lambda in defaultLambdas) {
|
|
||||||
invocationParamBuilder.buildParameters().getParameterByDeclarationSlot(lambda.offset).functionalArgument = lambda
|
invocationParamBuilder.buildParameters().getParameterByDeclarationSlot(lambda.offset).functionalArgument = lambda
|
||||||
val prev = expressionMap.put(lambda.offset, lambda)
|
val prev = expressionMap.put(lambda.offset, lambda)
|
||||||
assert(prev == null) { "Lambda with offset ${lambda.offset} already exists: $prev" }
|
assert(prev == null) { "Lambda with offset ${lambda.offset} already exists: $prev" }
|
||||||
@@ -283,6 +279,8 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract fun extractDefaultLambdas(node: MethodNode): List<DefaultLambda>
|
||||||
|
|
||||||
fun generateAndInsertFinallyBlocks(
|
fun generateAndInsertFinallyBlocks(
|
||||||
intoNode: MethodNode,
|
intoNode: MethodNode,
|
||||||
insertPoints: List<MethodInliner.PointForExternalFinallyBlocks>,
|
insertPoints: List<MethodInliner.PointForExternalFinallyBlocks>,
|
||||||
@@ -486,7 +484,9 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
|||||||
if (kind !== ValueKind.DEFAULT_MASK && kind !== ValueKind.METHOD_HANDLE_IN_DEFAULT) {
|
if (kind !== ValueKind.DEFAULT_MASK && kind !== ValueKind.METHOD_HANDLE_IN_DEFAULT) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
assert(value is StackValue.Constant) { "Additional default method argument should be constant, but " + value }
|
assert(value is StackValue.Constant) {
|
||||||
|
"Additional default method argument should be constant, but " + value
|
||||||
|
}
|
||||||
val constantValue = (value as StackValue.Constant).value
|
val constantValue = (value as StackValue.Constant).value
|
||||||
if (kind === ValueKind.DEFAULT_MASK) {
|
if (kind === ValueKind.DEFAULT_MASK) {
|
||||||
assert(constantValue is Int) { "Mask should be of Integer type, but " + constantValue }
|
assert(constantValue is Int) { "Mask should be of Integer type, but " + constantValue }
|
||||||
@@ -714,6 +714,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
|||||||
return NestedSourceMapper(parent, nodeAndSmap.sortedRanges, nodeAndSmap.classSMAP.sourceInfo)
|
return NestedSourceMapper(parent, nodeAndSmap.sortedRanges, nodeAndSmap.classSMAP.sourceInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val BaseExpressionCodegen.v: InstructionAdapter
|
val BaseExpressionCodegen.v: InstructionAdapter
|
||||||
|
|||||||
@@ -85,7 +85,20 @@ abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : FunctionalArgu
|
|||||||
class NonInlineableArgumentForInlineableParameterCalledInSuspend(val isSuspend: Boolean) : FunctionalArgument
|
class NonInlineableArgumentForInlineableParameterCalledInSuspend(val isSuspend: Boolean) : FunctionalArgument
|
||||||
object NonInlineableArgumentForInlineableSuspendParameter : FunctionalArgument
|
object NonInlineableArgumentForInlineableSuspendParameter : FunctionalArgument
|
||||||
|
|
||||||
class DefaultLambda(
|
|
||||||
|
class PsiDefaultLambda(
|
||||||
|
lambdaClassType: Type,
|
||||||
|
capturedArgs: Array<Type>,
|
||||||
|
parameterDescriptor: ValueParameterDescriptor,
|
||||||
|
offset: Int,
|
||||||
|
needReification: Boolean
|
||||||
|
) : DefaultLambda(lambdaClassType, capturedArgs, parameterDescriptor, offset, needReification) {
|
||||||
|
override fun mapAsmSignature(sourceCompiler: SourceCompilerForInline): Method {
|
||||||
|
return sourceCompiler.state.typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor).asmMethod
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class DefaultLambda(
|
||||||
override val lambdaClassType: Type,
|
override val lambdaClassType: Type,
|
||||||
private val capturedArgs: Array<Type>,
|
private val capturedArgs: Array<Type>,
|
||||||
val parameterDescriptor: ValueParameterDescriptor,
|
val parameterDescriptor: ValueParameterDescriptor,
|
||||||
@@ -93,17 +106,17 @@ class DefaultLambda(
|
|||||||
val needReification: Boolean
|
val needReification: Boolean
|
||||||
) : LambdaInfo(parameterDescriptor.isCrossinline) {
|
) : LambdaInfo(parameterDescriptor.isCrossinline) {
|
||||||
|
|
||||||
override var isBoundCallableReference by Delegates.notNull<Boolean>()
|
final override var isBoundCallableReference by Delegates.notNull<Boolean>()
|
||||||
private set
|
private set
|
||||||
|
|
||||||
val parameterOffsetsInDefault: MutableList<Int> = arrayListOf()
|
val parameterOffsetsInDefault: MutableList<Int> = arrayListOf()
|
||||||
|
|
||||||
override lateinit var invokeMethod: Method
|
final override lateinit var invokeMethod: Method
|
||||||
private set
|
private set
|
||||||
|
|
||||||
override lateinit var invokeMethodDescriptor: FunctionDescriptor
|
override lateinit var invokeMethodDescriptor: FunctionDescriptor
|
||||||
|
|
||||||
override lateinit var capturedVars: List<CapturedParamDesc>
|
final override lateinit var capturedVars: List<CapturedParamDesc>
|
||||||
private set
|
private set
|
||||||
|
|
||||||
override fun isReturnFromMe(labelName: String): Boolean = false
|
override fun isReturnFromMe(labelName: String): Boolean = false
|
||||||
@@ -168,12 +181,13 @@ class DefaultLambda(
|
|||||||
isBoundCallableReference = (isFunctionReference || isPropertyReference) && capturedVars.isNotEmpty()
|
isBoundCallableReference = (isFunctionReference || isPropertyReference) && capturedVars.isNotEmpty()
|
||||||
|
|
||||||
val methodName = (if (isPropertyReference) OperatorNameConventions.GET else OperatorNameConventions.INVOKE).asString()
|
val methodName = (if (isPropertyReference) OperatorNameConventions.GET else OperatorNameConventions.INVOKE).asString()
|
||||||
val signature = sourceCompiler.state.typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor).asmMethod.descriptor
|
|
||||||
|
val signature = mapAsmSignature(sourceCompiler)
|
||||||
|
|
||||||
node = getMethodNode(
|
node = getMethodNode(
|
||||||
classReader.b,
|
classReader.b,
|
||||||
methodName,
|
methodName,
|
||||||
signature,
|
signature.descriptor,
|
||||||
lambdaClassType,
|
lambdaClassType,
|
||||||
signatureAmbiguity = true
|
signatureAmbiguity = true
|
||||||
) ?: error("Can't find method '$methodName$signature' in '${classReader.className}'")
|
) ?: error("Can't find method '$methodName$signature' in '${classReader.className}'")
|
||||||
@@ -185,6 +199,8 @@ class DefaultLambda(
|
|||||||
reifiedTypeInliner.reifyInstructions(node.node)
|
reifiedTypeInliner.reifyInstructions(node.node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract fun mapAsmSignature(sourceCompiler: SourceCompilerForInline): Method
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Type.boxReceiverForBoundReference() =
|
internal fun Type.boxReceiverForBoundReference() =
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.types.KotlinType
|
|||||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||||
|
|
||||||
class PsiInlineCodegen(
|
class PsiInlineCodegen(
|
||||||
codegen: ExpressionCodegen,
|
codegen: ExpressionCodegen,
|
||||||
@@ -64,7 +65,7 @@ class PsiInlineCodegen(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
performInline(resolvedCall?.typeArguments?.keys?.toList(), callDefault, codegen.typeSystem, codegen)
|
performInline(resolvedCall?.typeArguments?.keys?.toList(), callDefault, callDefault, codegen.typeSystem)
|
||||||
} finally {
|
} finally {
|
||||||
state.globalInlineContext.exitFromInliningOf(resolvedCall)
|
state.globalInlineContext.exitFromInliningOf(resolvedCall)
|
||||||
}
|
}
|
||||||
@@ -193,4 +194,12 @@ class PsiInlineCodegen(
|
|||||||
delayedHiddenWriting!!.invoke()
|
delayedHiddenWriting!!.invoke()
|
||||||
delayedHiddenWriting = null
|
delayedHiddenWriting = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun extractDefaultLambdas(node: MethodNode): List<DefaultLambda> {
|
||||||
|
return expandMaskConditionsAndUpdateVariableNodes(
|
||||||
|
node, maskStartIndex, maskValues, methodHandleInDefaultMethodIndex,
|
||||||
|
extractDefaultLambdaOffsetAndDescriptor(jvmSignature, functionDescriptor),
|
||||||
|
::PsiDefaultLambda
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,13 +61,14 @@ fun extractDefaultLambdaOffsetAndDescriptor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun expandMaskConditionsAndUpdateVariableNodes(
|
fun <T, R : DefaultLambda> expandMaskConditionsAndUpdateVariableNodes(
|
||||||
node: MethodNode,
|
node: MethodNode,
|
||||||
maskStartIndex: Int,
|
maskStartIndex: Int,
|
||||||
masks: List<Int>,
|
masks: List<Int>,
|
||||||
methodHandlerIndex: Int,
|
methodHandlerIndex: Int,
|
||||||
defaultLambdas: Map<Int, ValueParameterDescriptor>
|
defaultLambdas: Map<Int, T>,
|
||||||
): List<DefaultLambda> {
|
lambdaConstructor: (Type, Array<Type>, T, Int, Boolean) -> R
|
||||||
|
): List<R> {
|
||||||
fun isMaskIndex(varIndex: Int): Boolean {
|
fun isMaskIndex(varIndex: Int): Boolean {
|
||||||
return maskStartIndex <= varIndex && varIndex < maskStartIndex + masks.size
|
return maskStartIndex <= varIndex && varIndex < maskStartIndex + masks.size
|
||||||
}
|
}
|
||||||
@@ -110,7 +111,7 @@ fun expandMaskConditionsAndUpdateVariableNodes(
|
|||||||
val toDelete = linkedSetOf<AbstractInsnNode>()
|
val toDelete = linkedSetOf<AbstractInsnNode>()
|
||||||
val toInsert = arrayListOf<Pair<AbstractInsnNode, AbstractInsnNode>>()
|
val toInsert = arrayListOf<Pair<AbstractInsnNode, AbstractInsnNode>>()
|
||||||
|
|
||||||
val defaultLambdasInfo = extractDefaultLambdasInfo(conditions, defaultLambdas, toDelete, toInsert)
|
val defaultLambdasInfo = extractDefaultLambdasInfo(conditions, defaultLambdas, toDelete, toInsert, lambdaConstructor)
|
||||||
|
|
||||||
val indexToVarNode = node.localVariables?.filter { it.index < maskStartIndex }?.associateBy { it.index } ?: emptyMap()
|
val indexToVarNode = node.localVariables?.filter { it.index < maskStartIndex }?.associateBy { it.index } ?: emptyMap()
|
||||||
conditions.forEach {
|
conditions.forEach {
|
||||||
@@ -137,12 +138,13 @@ fun expandMaskConditionsAndUpdateVariableNodes(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun extractDefaultLambdasInfo(
|
private fun <T, R : DefaultLambda> extractDefaultLambdasInfo(
|
||||||
conditions: List<Condition>,
|
conditions: List<Condition>,
|
||||||
defaultLambdas: Map<Int, ValueParameterDescriptor>,
|
defaultLambdas: Map<Int, T>,
|
||||||
toDelete: MutableCollection<AbstractInsnNode>,
|
toDelete: MutableCollection<AbstractInsnNode>,
|
||||||
toInsert: MutableList<Pair<AbstractInsnNode, AbstractInsnNode>>
|
toInsert: MutableList<Pair<AbstractInsnNode, AbstractInsnNode>>,
|
||||||
): List<DefaultLambda> {
|
lambdaConstructor: (Type, Array<Type>, T, Int, Boolean) -> R
|
||||||
|
): List<R> {
|
||||||
val defaultLambdaConditions = conditions.filter { it.expandNotDelete && defaultLambdas.contains(it.varIndex) }
|
val defaultLambdaConditions = conditions.filter { it.expandNotDelete && defaultLambdas.contains(it.varIndex) }
|
||||||
return defaultLambdaConditions.map {
|
return defaultLambdaConditions.map {
|
||||||
val varAssignmentInstruction = it.varInsNode!!
|
val varAssignmentInstruction = it.varInsNode!!
|
||||||
@@ -186,7 +188,7 @@ private fun extractDefaultLambdasInfo(
|
|||||||
|
|
||||||
toInsert.add(varAssignmentInstruction to defaultLambdaFakeCallStub(argTypes, it.varIndex))
|
toInsert.add(varAssignmentInstruction to defaultLambdaFakeCallStub(argTypes, it.varIndex))
|
||||||
|
|
||||||
DefaultLambda(owner, argTypes, defaultLambdas[it.varIndex]!!, it.varIndex, needReification)
|
lambdaConstructor(owner, argTypes, defaultLambdas[it.varIndex]!!, it.varIndex, needReification)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -985,7 +985,7 @@ class ExpressionCodegen(
|
|||||||
override fun toKotlinType(type: IrType): KotlinType = type.toKotlinType()
|
override fun toKotlinType(type: IrType): KotlinType = type.toKotlinType()
|
||||||
}, IrTypeCheckerContext(context.irBuiltIns), state.languageVersionSettings)
|
}, IrTypeCheckerContext(context.irBuiltIns), state.languageVersionSettings)
|
||||||
|
|
||||||
return IrInlineCodegen(this, state, callee.descriptor, methodOwner, signature, mappings, sourceCompiler, reifiedTypeInliner)
|
return IrInlineCodegen(this, state, callee, methodOwner, signature, mappings, sourceCompiler, reifiedTypeInliner)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun consumeReifiedOperationMarker(typeParameter: TypeParameterMarker) {
|
override fun consumeReifiedOperationMarker(typeParameter: TypeParameterMarker) {
|
||||||
|
|||||||
+82
-22
@@ -15,31 +15,36 @@ import org.jetbrains.kotlin.codegen.ValueKind
|
|||||||
import org.jetbrains.kotlin.codegen.inline.*
|
import org.jetbrains.kotlin.codegen.inline.*
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
|
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||||
import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor
|
import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
|
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||||
import org.jetbrains.kotlin.ir.util.dump
|
import org.jetbrains.kotlin.ir.util.dump
|
||||||
import org.jetbrains.kotlin.ir.util.getArgumentsWithIr
|
import org.jetbrains.kotlin.ir.util.getArgumentsWithIr
|
||||||
import org.jetbrains.kotlin.ir.util.isSuspend
|
import org.jetbrains.kotlin.ir.util.isSuspend
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||||
|
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||||
|
|
||||||
class IrInlineCodegen(
|
class IrInlineCodegen(
|
||||||
codegen: ExpressionCodegen,
|
codegen: ExpressionCodegen,
|
||||||
state: GenerationState,
|
state: GenerationState,
|
||||||
function: FunctionDescriptor,
|
private val function: IrFunction,
|
||||||
methodOwner: Type,
|
methodOwner: Type,
|
||||||
signature: JvmMethodSignature,
|
signature: JvmMethodSignature,
|
||||||
typeParameterMappings: TypeParameterMappings<IrType>,
|
typeParameterMappings: TypeParameterMappings<IrType>,
|
||||||
sourceCompiler: SourceCompilerForInline,
|
sourceCompiler: SourceCompilerForInline,
|
||||||
reifiedTypeInliner: ReifiedTypeInliner<IrType>
|
reifiedTypeInliner: ReifiedTypeInliner<IrType>
|
||||||
) : InlineCodegen<ExpressionCodegen>(
|
) : InlineCodegen<ExpressionCodegen>(
|
||||||
codegen, state, function, methodOwner, signature, typeParameterMappings, sourceCompiler, reifiedTypeInliner
|
codegen, state, function.descriptor, methodOwner, signature, typeParameterMappings, sourceCompiler, reifiedTypeInliner
|
||||||
), IrCallGenerator {
|
), IrCallGenerator {
|
||||||
override fun generateAssertFieldIfNeeded(info: RootInliningContext) {
|
override fun generateAssertFieldIfNeeded(info: RootInliningContext) {
|
||||||
if (info.generateAssertField && (sourceCompiler as IrSourceCompilerForInline).isPrimaryCopy) {
|
if (info.generateAssertField && (sourceCompiler as IrSourceCompilerForInline).isPrimaryCopy) {
|
||||||
@@ -52,12 +57,16 @@ class IrInlineCodegen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun putClosureParametersOnStack(next: LambdaInfo, functionReferenceReceiver: StackValue?) {
|
override fun putClosureParametersOnStack(next: LambdaInfo, functionReferenceReceiver: StackValue?) {
|
||||||
val lambdaInfo = next as IrExpressionLambdaImpl
|
activeLambda = next
|
||||||
activeLambda = lambdaInfo
|
|
||||||
|
|
||||||
lambdaInfo.reference.getArgumentsWithIr().forEachIndexed { index, (_, ir) ->
|
when (next) {
|
||||||
putCapturedValueOnStack(ir, lambdaInfo.capturedParamsInDesc[index], index)
|
is IrExpressionLambdaImpl -> next.reference.getArgumentsWithIr().forEachIndexed { index, (_, ir) ->
|
||||||
|
putCapturedValueOnStack(ir, next.capturedParamsInDesc[index], index)
|
||||||
|
}
|
||||||
|
is IrDefaultLambda -> rememberCapturedForDefaultLambda(next)
|
||||||
|
else -> throw RuntimeException("Unknown lambda: $next")
|
||||||
}
|
}
|
||||||
|
|
||||||
activeLambda = null
|
activeLambda = null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,7 +77,11 @@ class IrInlineCodegen(
|
|||||||
codegen: ExpressionCodegen,
|
codegen: ExpressionCodegen,
|
||||||
blockInfo: BlockInfo
|
blockInfo: BlockInfo
|
||||||
) {
|
) {
|
||||||
if (irValueParameter.isInlineParameter() && isInlineIrExpression(argumentExpression)) {
|
if (irValueParameter.isInlineParameter(
|
||||||
|
/*after transformation inlinable lambda parameter with default value would have nullable type: check default value type first*/
|
||||||
|
irValueParameter.defaultValue?.expression?.type ?: irValueParameter.type
|
||||||
|
) && isInlineIrExpression(argumentExpression)
|
||||||
|
) {
|
||||||
val irReference: IrFunctionReference =
|
val irReference: IrFunctionReference =
|
||||||
(argumentExpression as IrBlock).statements.filterIsInstance<IrFunctionReference>().single()
|
(argumentExpression as IrBlock).statements.filterIsInstance<IrFunctionReference>().single()
|
||||||
val boundReceiver = argumentExpression.statements.filterIsInstance<IrVariable>().singleOrNull()
|
val boundReceiver = argumentExpression.statements.filterIsInstance<IrVariable>().singleOrNull()
|
||||||
@@ -81,20 +94,39 @@ class IrInlineCodegen(
|
|||||||
activeLambda = null
|
activeLambda = null
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val onStack = if (irValueParameter.index >= 0)
|
val kind = when (irValueParameter.origin) {
|
||||||
// Reuse an existing local if possible. NOTE: when stopping at a breakpoint placed
|
IrDeclarationOrigin.MASK_FOR_DEFAULT_FUNCTION -> ValueKind.DEFAULT_MASK
|
||||||
// in an inline function, arguments which reuse an existing local will not be visible
|
IrDeclarationOrigin.METHOD_HANDLER_IN_DEFAULT_FUNCTION -> ValueKind.METHOD_HANDLE_IN_DEFAULT
|
||||||
// in the debugger.
|
//TODO: support DEFAULT_PARAMETER
|
||||||
codegen.genOrGetLocal(argumentExpression, blockInfo)
|
else -> ValueKind.CAPTURED
|
||||||
else
|
}
|
||||||
// Do not reuse locals for receivers. While it's actually completely fine, the non-IR
|
|
||||||
// backend does not do it for internal reasons, and here we replicate the debugging
|
val onStack = when {
|
||||||
// experience.
|
kind == ValueKind.METHOD_HANDLE_IN_DEFAULT -> StackValue.constant(null, AsmTypes.OBJECT_TYPE)
|
||||||
codegen.gen(argumentExpression, parameterType, irValueParameter.type, blockInfo)
|
kind == ValueKind.DEFAULT_MASK -> StackValue.constant((argumentExpression as IrConst<*>).value, Type.INT_TYPE)
|
||||||
// TODO support default argument erasure: do nothing if the parameter is a default mask, the argument is a constant int,
|
kind == ValueKind.DEFAULT_PARAMETER -> StackValue.constant(null, AsmTypes.OBJECT_TYPE)
|
||||||
// and processDefaultMaskOrMethodHandler(StackValue.constant(...), ValueKind.DEFAULT_MASK) is true.
|
irValueParameter.index >= 0
|
||||||
val expectedType = JvmKotlinType(parameterType, irValueParameter.type.toKotlinType())
|
// Reuse an existing local if possible. NOTE: when stopping at a breakpoint placed
|
||||||
putArgumentOrCapturedToLocalVal(expectedType, onStack, -1, irValueParameter.index, ValueKind.CAPTURED)
|
// in an inline function, arguments which reuse an existing local will not be visible
|
||||||
|
// in the debugger.
|
||||||
|
-> codegen.genOrGetLocal(argumentExpression, blockInfo)
|
||||||
|
else
|
||||||
|
// Do not reuse locals for receivers. While it's actually completely fine, the non-IR
|
||||||
|
// backend does not do it for internal reasons, and here we replicate the debugging
|
||||||
|
// experience.
|
||||||
|
-> codegen.gen(argumentExpression, parameterType, irValueParameter.type, blockInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//TODO support default argument erasure
|
||||||
|
if (!processDefaultMaskOrMethodHandler(
|
||||||
|
onStack,
|
||||||
|
kind
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
val expectedType = JvmKotlinType(parameterType, irValueParameter.type.toKotlinType())
|
||||||
|
putArgumentOrCapturedToLocalVal(expectedType, onStack, -1, irValueParameter.index, kind)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,7 +148,12 @@ class IrInlineCodegen(
|
|||||||
// TODO port inlining cycle detection to IrFunctionAccessExpression & pass it
|
// TODO port inlining cycle detection to IrFunctionAccessExpression & pass it
|
||||||
state.globalInlineContext.enterIntoInlining(null)
|
state.globalInlineContext.enterIntoInlining(null)
|
||||||
try {
|
try {
|
||||||
performInline(expression.symbol.owner.typeParameters.map { it.symbol }, false, codegen.typeMapper.typeSystem, codegen)
|
performInline(
|
||||||
|
expression.symbol.owner.typeParameters.map { it.symbol },
|
||||||
|
function.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER,
|
||||||
|
false,
|
||||||
|
codegen.typeMapper.typeSystem
|
||||||
|
)
|
||||||
} finally {
|
} finally {
|
||||||
state.globalInlineContext.exitFromInliningOf(null)
|
state.globalInlineContext.exitFromInliningOf(null)
|
||||||
}
|
}
|
||||||
@@ -138,6 +175,14 @@ class IrInlineCodegen(
|
|||||||
expressionMap[closureInfo.index] = lambda
|
expressionMap[closureInfo.index] = lambda
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun extractDefaultLambdas(node: MethodNode): List<DefaultLambda> {
|
||||||
|
return expandMaskConditionsAndUpdateVariableNodes(
|
||||||
|
node, maskStartIndex, maskValues, methodHandleInDefaultMethodIndex,
|
||||||
|
extractDefaultLambdaOffsetAndDescriptor(jvmSignature, function),
|
||||||
|
::IrDefaultLambda
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class IrExpressionLambdaImpl(
|
class IrExpressionLambdaImpl(
|
||||||
@@ -194,6 +239,21 @@ class IrExpressionLambdaImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class IrDefaultLambda(
|
||||||
|
lambdaClassType: Type,
|
||||||
|
capturedArgs: Array<Type>,
|
||||||
|
private val irValueParameter: IrValueParameter,
|
||||||
|
offset: Int,
|
||||||
|
needReification: Boolean
|
||||||
|
) : DefaultLambda(lambdaClassType, capturedArgs, irValueParameter.descriptor as ValueParameterDescriptor, offset, needReification) {
|
||||||
|
|
||||||
|
override fun mapAsmSignature(sourceCompiler: SourceCompilerForInline): Method {
|
||||||
|
val invoke =
|
||||||
|
irValueParameter.type.classOrNull!!.owner.declarations.filterIsInstance<IrFunction>().single { it.name.asString() == "invoke" }
|
||||||
|
return (sourceCompiler as IrSourceCompilerForInline).codegen.context.methodSignatureMapper.mapSignatureSkipGeneric(invoke).asmMethod
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun isInlineIrExpression(argumentExpression: IrExpression) =
|
fun isInlineIrExpression(argumentExpression: IrExpression) =
|
||||||
when (argumentExpression) {
|
when (argumentExpression) {
|
||||||
is IrBlock -> argumentExpression.isInlineIrBlock()
|
is IrBlock -> argumentExpression.isInlineIrBlock()
|
||||||
|
|||||||
+1
-1
@@ -40,7 +40,7 @@ class IrSourceCompilerForInline(
|
|||||||
override val state: GenerationState,
|
override val state: GenerationState,
|
||||||
override val callElement: IrMemberAccessExpression,
|
override val callElement: IrMemberAccessExpression,
|
||||||
private val callee: IrFunction,
|
private val callee: IrFunction,
|
||||||
private val codegen: ExpressionCodegen,
|
internal val codegen: ExpressionCodegen,
|
||||||
private val data: BlockInfo
|
private val data: BlockInfo
|
||||||
) : SourceCompilerForInline {
|
) : SourceCompilerForInline {
|
||||||
|
|
||||||
|
|||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.backend.jvm.codegen
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.ir.isInlineParameter
|
||||||
|
import org.jetbrains.kotlin.codegen.inline.parameterOffsets
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||||
|
|
||||||
|
fun extractDefaultLambdaOffsetAndDescriptor(
|
||||||
|
jvmSignature: JvmMethodSignature,
|
||||||
|
irFunction: IrFunction
|
||||||
|
): Map<Int, IrValueParameter> {
|
||||||
|
val valueParameters = jvmSignature.valueParameters
|
||||||
|
val parameterOffsets = parameterOffsets(irFunction.isStatic, valueParameters)
|
||||||
|
|
||||||
|
val valueParameterOffset = if (irFunction.extensionReceiverParameter != null) 1 else 0
|
||||||
|
|
||||||
|
return irFunction.valueParameters.filter {
|
||||||
|
it.defaultValue != null && it.isInlineParameter(it.defaultValue!!.expression.type)
|
||||||
|
}.associateBy {
|
||||||
|
parameterOffsets[valueParameterOffset + it.index]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -96,7 +96,7 @@ val IrFunction.propertyIfAccessor: IrDeclaration
|
|||||||
|
|
||||||
fun IrFunction.hasJvmDefault(): Boolean = propertyIfAccessor.hasAnnotation(JVM_DEFAULT_FQ_NAME)
|
fun IrFunction.hasJvmDefault(): Boolean = propertyIfAccessor.hasAnnotation(JVM_DEFAULT_FQ_NAME)
|
||||||
|
|
||||||
fun IrValueParameter.isInlineParameter() =
|
fun IrValueParameter.isInlineParameter(type: IrType = this.type) =
|
||||||
index >= 0 && !isNoinline && !type.isNullable() && (type.isFunction() || type.isSuspendFunctionTypeOrSubtype())
|
index >= 0 && !isNoinline && !type.isNullable() && (type.isFunction() || type.isSuspendFunctionTypeOrSubtype())
|
||||||
|
|
||||||
val IrType.isBoxedArray: Boolean
|
val IrType.isBoxedArray: Boolean
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||||
package test
|
package test
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||||
package test
|
package test
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||||
package test
|
package test
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||||
package test
|
package test
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||||
package test
|
package test
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||||
package test
|
package test
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||||
package test
|
package test
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||||
package test
|
package test
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
package test
|
package test
|
||||||
|
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||||
package test
|
package test
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||||
package test
|
package test
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||||
package test
|
package test
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||||
package test
|
package test
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||||
package test
|
package test
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
package test
|
package test
|
||||||
|
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||||
package test
|
package test
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||||
package test
|
package test
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||||
package test
|
package test
|
||||||
|
|||||||
Vendored
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
// SKIP_INLINE_CHECK_IN: bar$default
|
// SKIP_INLINE_CHECK_IN: bar$default
|
||||||
package test
|
package test
|
||||||
|
|||||||
Vendored
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||||
package test
|
package test
|
||||||
|
|||||||
Vendored
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||||
package test
|
package test
|
||||||
|
|||||||
-1
@@ -1,7 +1,6 @@
|
|||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
//WITH_RUNTIME
|
//WITH_RUNTIME
|
||||||
package test
|
package test
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
// SKIP_INLINE_CHECK_IN: lParams$default
|
// SKIP_INLINE_CHECK_IN: lParams$default
|
||||||
package test
|
package test
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||||
package test
|
package test
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||||
package test
|
package test
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
// SKIP_INLINE_CHECK_IN: enumOrThrow$default
|
// SKIP_INLINE_CHECK_IN: enumOrThrow$default
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||||
package test
|
package test
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||||
package test
|
package test
|
||||||
|
|||||||
Vendored
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||||
package test
|
package test
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||||
package test
|
package test
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||||
package test
|
package test
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||||
package test
|
package test
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
|
|||||||
Vendored
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
inline fun inlineFunVoid(f: () -> Unit): Unit {
|
inline fun inlineFunVoid(f: () -> Unit): Unit {
|
||||||
return f()
|
return f()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user