diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/CallBasedArgumentGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/CallBasedArgumentGenerator.kt index 2af03c53ab4..d11af10e043 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/CallBasedArgumentGenerator.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/CallBasedArgumentGenerator.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument import org.jetbrains.kotlin.resolve.calls.model.VarargValueArgument +import org.jetbrains.kotlin.resolve.inline.InlineUtil import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE import org.jetbrains.kotlin.types.upperIfFlexible import org.jetbrains.org.objectweb.asm.Type @@ -51,7 +52,7 @@ class CallBasedArgumentGenerator( callGenerator.putValueIfNeeded( getJvmKotlinType(i), StackValue.createDefaultValue(valueParameterTypes[i]), - ValueKind.DEFAULT_PARAMETER, + if (InlineUtil.isInlineParameter(valueParameters[i])) ValueKind.DEFAULT_INLINE_PARAMETER else ValueKind.DEFAULT_PARAMETER, i ) } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/CallGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/CallGenerator.kt index 75a5726d630..071792cd6a3 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/CallGenerator.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/CallGenerator.kt @@ -15,9 +15,9 @@ enum class ValueKind { GENERAL, GENERAL_VARARG, DEFAULT_PARAMETER, + DEFAULT_INLINE_PARAMETER, DEFAULT_MASK, METHOD_HANDLE_IN_DEFAULT, - CAPTURED, NON_INLINEABLE_ARGUMENT_FOR_INLINE_PARAMETER_CALLED_IN_SUSPEND, NON_INLINEABLE_ARGUMENT_FOR_INLINE_SUSPEND_PARAMETER } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt index 992387234b4..48c6a67aa25 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt @@ -71,10 +71,12 @@ abstract class InlineCodegen( private fun inlineCall(nodeAndSmap: SMAPAndMethodNode, isInlineOnly: Boolean): InlineResult { val node = nodeAndSmap.node if (maskStartIndex != -1) { - val infos = expandMaskConditionsAndUpdateVariableNodes( - node, maskStartIndex, maskValues, methodHandleInDefaultMethodIndex, computeDefaultLambdaOffsets() - ) val parameters = invocationParamBuilder.buildParameters() + val infos = expandMaskConditionsAndUpdateVariableNodes( + node, maskStartIndex, maskValues, methodHandleInDefaultMethodIndex, + parameters.parameters.filter { it.functionalArgument === DefaultValueOfInlineParameter } + .mapTo(mutableSetOf()) { parameters.getDeclarationSlot(it) } + ) for (info in infos) { val lambda = DefaultLambda(info, sourceCompiler) parameters.getParameterByDeclarationSlot(info.offset).functionalArgument = lambda @@ -83,7 +85,11 @@ abstract class InlineCodegen( if (info.needReification) { lambda.reifiedTypeParametersUsages.mergeAll(reifiedTypeInliner.reifyInstructions(lambda.node.node)) } - rememberCapturedForDefaultLambda(lambda) + for (captured in lambda.capturedVars) { + val param = invocationParamBuilder.addCapturedParam(captured, captured.fieldName, false) + param.remapValue = StackValue.local(codegen.frameMap.enterTemp(param.type), param.type) + param.isSynthetic = true + } } } @@ -141,8 +147,6 @@ abstract class InlineCodegen( return result } - abstract fun computeDefaultLambdaOffsets(): Set - private fun generateAndInsertFinallyBlocks( intoNode: MethodNode, insertPoints: List, @@ -235,10 +239,12 @@ abstract class InlineCodegen( NonInlineableArgumentForInlineableParameterCalledInSuspend ValueKind.NON_INLINEABLE_ARGUMENT_FOR_INLINE_SUSPEND_PARAMETER -> NonInlineableArgumentForInlineableSuspendParameter + ValueKind.DEFAULT_INLINE_PARAMETER -> + DefaultValueOfInlineParameter else -> null } when { - kind === ValueKind.DEFAULT_PARAMETER -> + kind === ValueKind.DEFAULT_PARAMETER || kind === ValueKind.DEFAULT_INLINE_PARAMETER -> codegen.frameMap.enterTemp(info.type) // the inline function will put the value into this slot stackValue.isLocalWithNoBoxing(jvmKotlinType) -> info.remapValue = stackValue @@ -257,14 +263,6 @@ abstract class InlineCodegen( } } - private fun rememberCapturedForDefaultLambda(defaultLambda: DefaultLambda) { - for (captured in defaultLambda.capturedVars) { - val info = invocationParamBuilder.addCapturedParam(captured, captured.fieldName, false) - info.remapValue = StackValue.local(codegen.frameMap.enterTemp(info.type), info.type) - info.isSynthetic = true - } - } - private fun processDefaultMaskOrMethodHandler(value: StackValue, kind: ValueKind) { assert(value is StackValue.Constant) { "Additional default method argument should be constant, but $value" } val constantValue = (value as StackValue.Constant).value diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt index df4dab01a40..ce89204bc91 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt @@ -65,6 +65,7 @@ abstract class LambdaInfo : FunctionalArgument { object NonInlineableArgumentForInlineableParameterCalledInSuspend : FunctionalArgument object NonInlineableArgumentForInlineableSuspendParameter : FunctionalArgument +object DefaultValueOfInlineParameter : FunctionalArgument abstract class ExpressionLambda : LambdaInfo() { fun generateLambdaBody(sourceCompiler: SourceCompilerForInline) { 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 580ff1f7ea8..aae6878b289 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInlinerUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInlinerUtil.kt @@ -10,7 +10,6 @@ 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.AbstractInsnNode import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode @@ -18,15 +17,6 @@ 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 { - var nextOffset = if (isStatic) 0 else 1 - return Array(valueParameters.size) { index -> - nextOffset.also { - nextOffset += valueParameters[index].asmType.size - } - } -} - fun MethodNode.remove(instructions: Sequence) = instructions.forEach { this@remove.instructions.remove(it) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiInlineCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiInlineCodegen.kt index 0db35255204..4b05c68e063 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiInlineCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiInlineCodegen.kt @@ -111,14 +111,6 @@ class PsiInlineCodegen( hiddenParameters.clear() } - /*lambda or callable reference*/ - private fun isInliningParameter(expression: KtExpression, valueParameterDescriptor: ValueParameterDescriptor): Boolean { - //TODO deparenthesize typed - val deparenthesized = KtPsiUtil.deparenthesize(expression) - - return InlineUtil.isInlineParameter(valueParameterDescriptor) && isInlinableParameterExpression(deparenthesized) - } - override fun genValueAndPut( valueParameterDescriptor: ValueParameterDescriptor?, argumentExpression: KtExpression, @@ -130,7 +122,9 @@ class PsiInlineCodegen( "which cannot be declared in Kotlin and thus be inline: $codegen" } - if (isInliningParameter(argumentExpression, valueParameterDescriptor)) { + val isInlineParameter = InlineUtil.isInlineParameter(valueParameterDescriptor) + //TODO deparenthesize typed + if (isInlineParameter && isInlinableParameterExpression(KtPsiUtil.deparenthesize(argumentExpression))) { rememberClosure(argumentExpression, parameterType.type, valueParameterDescriptor) } else { val value = codegen.gen(argumentExpression) @@ -191,15 +185,6 @@ class PsiInlineCodegen( putCapturedToLocalVal(stackValue, activeLambda!!.capturedVars[paramIndex], stackValue.kotlinType) override fun reorderArgumentsIfNeeded(actualArgsWithDeclIndex: List, valueParameterTypes: List) = Unit - - override fun computeDefaultLambdaOffsets(): Set { - val contextKind = (sourceCompiler as PsiSourceCompilerForInline).context.contextKind - return parameterOffsets(DescriptorAsmUtil.isStaticMethod(contextKind, functionDescriptor), jvmSignature.valueParameters) - .drop(jvmSignature.valueParameters.indexOfFirst { it.kind == JvmMethodParameterKind.VALUE }) - .filterIndexedTo(mutableSetOf()) { index, _ -> - functionDescriptor.valueParameters[index].let { InlineUtil.isInlineParameter(it) && it.declaresDefaultValue() } - } - } } private val FunctionDescriptor.explicitParameters diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt index 87822f1e738..ace0b8333a6 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt @@ -70,7 +70,7 @@ class IrInlineCodegen( IrDeclarationOrigin.METHOD_HANDLER_IN_DEFAULT_FUNCTION -> ValueKind.METHOD_HANDLE_IN_DEFAULT else -> when { argumentExpression is IrContainerExpression && argumentExpression.origin == IrStatementOrigin.DEFAULT_VALUE -> - ValueKind.DEFAULT_PARAMETER + if (isInlineParameter) ValueKind.DEFAULT_INLINE_PARAMETER else ValueKind.DEFAULT_PARAMETER // TODO ValueKind.NON_INLINEABLE_ARGUMENT_FOR_INLINE_PARAMETER_CALLED_IN_SUSPEND? isInlineParameter && irValueParameter.type.isSuspendFunctionTypeOrSubtype() -> ValueKind.NON_INLINEABLE_ARGUMENT_FOR_INLINE_SUSPEND_PARAMETER @@ -78,20 +78,17 @@ class IrInlineCodegen( } } - val onStack = when { - kind == ValueKind.METHOD_HANDLE_IN_DEFAULT -> StackValue.constant(null, AsmTypes.OBJECT_TYPE) - kind == ValueKind.DEFAULT_MASK -> StackValue.constant((argumentExpression as IrConst<*>).value, Type.INT_TYPE) - kind == ValueKind.DEFAULT_PARAMETER -> StackValue.createDefaultValue(parameterType) - irValueParameter.index >= 0 - // Reuse an existing local if possible. NOTE: when stopping at a breakpoint placed - // in an inline function, arguments which reuse an existing local will not be visible - // in the debugger. - -> codegen.genOrGetLocal(argumentExpression, parameterType, irValueParameter.type, blockInfo) + val onStack = when (kind) { + ValueKind.METHOD_HANDLE_IN_DEFAULT -> StackValue.constant(null, AsmTypes.OBJECT_TYPE) + ValueKind.DEFAULT_MASK -> StackValue.constant((argumentExpression as IrConst<*>).value, Type.INT_TYPE) + ValueKind.DEFAULT_PARAMETER, ValueKind.DEFAULT_INLINE_PARAMETER -> StackValue.createDefaultValue(parameterType) + // Here we replicate the old backend: reusing the locals for everything except extension receivers. + // TODO when stopping at a breakpoint placed in an inline function, arguments which reuse an existing + // local will not be visible in the debugger, so this needs to be reconsidered. + else -> if (irValueParameter.index >= 0) + codegen.genOrGetLocal(argumentExpression, parameterType, irValueParameter.type, 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) + codegen.gen(argumentExpression, parameterType, irValueParameter.type, blockInfo) } val expectedType = JvmKotlinType(parameterType, irValueParameter.type.toIrBasedKotlinType()) @@ -115,13 +112,6 @@ class IrInlineCodegen( override fun genCycleStub(text: String, codegen: ExpressionCodegen) { generateStub(text, codegen) } - - override fun computeDefaultLambdaOffsets(): Set = - parameterOffsets(function.isStatic, jvmSignature.valueParameters) - .drop(if (function.extensionReceiverParameter != null) 1 else 0) - .filterIndexedTo(mutableSetOf()) { index, _ -> - function.valueParameters[index].let { it.defaultValue != null && it.isInlineParameter() } - } } class IrExpressionLambdaImpl(