From 717cf2066ad65943d8b4283401610acf672f1219 Mon Sep 17 00:00:00 2001 From: pyos Date: Tue, 6 Jul 2021 12:53:37 +0200 Subject: [PATCH] JVM: remove more redundant properties from LambdaInfo --- .../inline/AnonymousObjectTransformer.kt | 12 ++++++----- .../kotlin/codegen/inline/LambdaInfo.kt | 20 ++++++++++-------- .../kotlin/codegen/inline/MethodInliner.kt | 10 +++------ .../codegen/inline/ParametersBuilder.kt | 17 --------------- .../kotlin/codegen/inline/PsiInlineCodegen.kt | 7 ++----- .../backend/jvm/codegen/IrInlineCodegen.kt | 21 ++++++------------- 6 files changed, 29 insertions(+), 58 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt index 5549bba6eac..f00f5e9df21 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt @@ -421,11 +421,13 @@ class AnonymousObjectTransformer( } private fun getMethodParametersWithCaptured(capturedBuilder: ParametersBuilder, sourceNode: MethodNode): Parameters { - val builder = ParametersBuilder.initializeBuilderFrom( - oldObjectType, - sourceNode.desc, - isStatic = sourceNode.access and Opcodes.ACC_STATIC != 0 - ) + val builder = ParametersBuilder.newBuilder() + if (sourceNode.access and Opcodes.ACC_STATIC == 0) { + builder.addThis(oldObjectType, skipped = false) + } + for (type in Type.getArgumentTypes(sourceNode.desc)) { + builder.addNextParameter(type, false) + } for (param in capturedBuilder.listCaptured()) { builder.addCapturedParamCopy(param) } 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 ce89204bc91..18eb7447cf8 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt @@ -18,10 +18,6 @@ import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode interface FunctionalArgument abstract class LambdaInfo : FunctionalArgument { - abstract val isBoundCallableReference: Boolean - - abstract val isSuspend: Boolean - abstract val lambdaClassType: Type abstract val invokeMethod: Method @@ -39,11 +35,17 @@ abstract class LambdaInfo : FunctionalArgument { val reifiedTypeParametersUsages = ReifiedTypeParametersUsages() - open val hasDispatchReceiver = true + open val hasDispatchReceiver + get() = true fun addAllParameters(remapper: FieldRemapper): Parameters { - val builder = ParametersBuilder.initializeBuilderFrom(OBJECT_TYPE, invokeMethod.descriptor, this) - + val builder = ParametersBuilder.newBuilder() + if (hasDispatchReceiver) { + builder.addThis(lambdaClassType, skipped = true).functionalArgument = this + } + for (type in Type.getArgumentTypes(invokeMethod.descriptor)) { + builder.addNextParameter(type, skipped = false) + } for (info in capturedVars) { val field = remapper.findField(FieldInsnNode(0, info.containingLambdaName, info.fieldName, "")) ?: error("Captured field not found: " + info.containingLambdaName + "." + info.fieldName) @@ -75,9 +77,9 @@ abstract class ExpressionLambda : LambdaInfo() { } class DefaultLambda(info: ExtractedDefaultLambda, sourceCompiler: SourceCompilerForInline) : LambdaInfo() { + val isBoundCallableReference: Boolean + override val lambdaClassType: Type = info.type - override val isSuspend: Boolean get() = false // TODO: it should probably be true sometimes, but it never was - override val isBoundCallableReference: Boolean override val capturedVars: List override val invokeMethod: Method diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt index 51c57cce78e..e8d6409f699 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt @@ -228,7 +228,7 @@ class MethodInliner( val expectedParameters = info.invokeMethod.argumentTypes val expectedKotlinParameters = info.invokeMethodParameters val argumentCount = Type.getArgumentTypes(desc).size.let { - if (!inliningContext.root.state.isIrBackend && info.isSuspend && it < expectedParameters.size) { + if (info is PsiExpressionLambda && info.invokeMethodDescriptor.isSuspend && it < expectedParameters.size) { // Inlining suspend lambda into a function that takes a non-suspend lambda. // In the IR backend, this cannot happen as inline lambdas are not lowered. addFakeContinuationMarker(this) @@ -381,10 +381,7 @@ class MethodInliner( private fun getNewIndex(`var`: Int): Int { val lambdaInfo = inliningContext.lambdaInfo if (reorderIrLambdaParameters && lambdaInfo is IrExpressionLambda) { - val extensionSize = - if (lambdaInfo.isExtensionLambda && !lambdaInfo.isBoundCallableReference) - lambdaInfo.invokeMethod.argumentTypes[0].size - else 0 + val extensionSize = if (lambdaInfo.isExtensionLambda) lambdaInfo.invokeMethod.argumentTypes[0].size else 0 return when { // v-- extensionSize v-- argsSizeOnStack // |- extension -|- captured -|- real -|- locals -| old descriptor @@ -637,9 +634,8 @@ class MethodInliner( private fun replaceContinuationAccessesWithFakeContinuationsIfNeeded(processingNode: MethodNode) { // in ir backend inline suspend lambdas do not use ALOAD 0 to get continuation, since they are generated as static functions // instead they get continuation from parameter. - if (inliningContext.state.isIrBackend) return val lambdaInfo = inliningContext.lambdaInfo ?: return - if (!lambdaInfo.isSuspend) return + if (lambdaInfo !is PsiExpressionLambda || !lambdaInfo.invokeMethodDescriptor.isSuspend) return val sources = analyzeMethodNodeWithInterpreter(processingNode, Aload0Interpreter(processingNode)) val cfg = ControlFlowGraph.build(processingNode) val aload0s = processingNode.instructions.asSequence().filter { it.opcode == Opcodes.ALOAD && it.safeAs()?.`var` == 0 } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ParametersBuilder.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ParametersBuilder.kt index 3e620e7c038..30083564b94 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ParametersBuilder.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ParametersBuilder.kt @@ -107,22 +107,5 @@ class ParametersBuilder private constructor() { fun newBuilder(): ParametersBuilder { return ParametersBuilder() } - - @JvmOverloads - @JvmStatic - fun initializeBuilderFrom( - objectType: Type, descriptor: String, inlineLambda: LambdaInfo? = null, isStatic: Boolean = false - ): ParametersBuilder { - val builder = newBuilder() - if (inlineLambda?.hasDispatchReceiver != false && !isStatic) { - //skipped this for inlined lambda cause it will be removed - builder.addThis(objectType, inlineLambda != null).functionalArgument = inlineLambda - } - - for (type in Type.getArgumentTypes(descriptor)) { - builder.addNextParameter(type, false) - } - return builder - } } } 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 4b05c68e063..591244ae772 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiInlineCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiInlineCodegen.kt @@ -194,7 +194,7 @@ class PsiExpressionLambda( expression: KtExpression, private val state: GenerationState, val isCrossInline: Boolean, - override val isBoundCallableReference: Boolean + val isBoundCallableReference: Boolean ) : ExpressionLambda() { override val lambdaClassType: Type @@ -204,7 +204,7 @@ class PsiExpressionLambda( override val invokeMethodParameters: List get() { - val actualInvokeDescriptor = if (isSuspend) + val actualInvokeDescriptor = if (invokeMethodDescriptor.isSuspend) getOrCreateJvmSuspendFunctionView(invokeMethodDescriptor, state) else invokeMethodDescriptor @@ -222,8 +222,6 @@ class PsiExpressionLambda( override val returnLabels: Map - override val isSuspend: Boolean - val closure: CalculatedClosure init { @@ -252,7 +250,6 @@ class PsiExpressionLambda( ?: throw AssertionError("null closure for lambda ${expression.text}") returnLabels = getDeclarationLabels(expression, invokeMethodDescriptor).associateWith { null } invokeMethod = state.typeMapper.mapAsmMethod(invokeMethodDescriptor) - isSuspend = invokeMethodDescriptor.isSuspend } // This can only be computed after generating the body, hence `lazy`. 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 ace0b8333a6..f06b87e6b2f 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 @@ -119,17 +119,11 @@ class IrExpressionLambdaImpl( val reference: IrFunctionReference, irValueParameter: IrValueParameter ) : ExpressionLambda(), IrExpressionLambda { - override val isExtensionLambda: Boolean = irValueParameter.type.isExtensionFunctionType + override val isExtensionLambda: Boolean = irValueParameter.type.isExtensionFunctionType && reference.extensionReceiver == null val function: IrFunction get() = reference.symbol.owner - override val isBoundCallableReference: Boolean - get() = reference.extensionReceiver != null - - override val isSuspend: Boolean - get() = reference.symbol.owner.isSuspend - override val hasDispatchReceiver: Boolean get() = false @@ -148,20 +142,17 @@ class IrExpressionLambdaImpl( init { val asmMethod = codegen.methodSignatureMapper.mapAsmMethod(function) val capturedParameters = reference.getArgumentsWithIr() - val (startCapture, endCapture) = when { - isBoundCallableReference -> 0 to 1 // (bound receiver, real parameters...) - isExtensionLambda -> 1 to capturedParameters.size + 1 // (unbound receiver, captures..., real parameters...) - else -> 0 to capturedParameters.size // (captures..., real parameters...) - } + val captureStart = if (isExtensionLambda) 1 else 0 // extension receiver comes before captures + val captureEnd = captureStart + capturedParameters.size capturedVars = capturedParameters.mapIndexed { index, (parameter, _) -> val isSuspend = parameter.isInlineParameter() && parameter.type.isSuspendFunctionTypeOrSubtype() - capturedParamDesc(parameter.name.asString(), asmMethod.argumentTypes[startCapture + index], isSuspend) + capturedParamDesc(parameter.name.asString(), asmMethod.argumentTypes[captureStart + index], isSuspend) } // The parameter list should include the continuation if this is a suspend lambda. In the IR backend, // the lambda is suspend iff the inline function's parameter is marked suspend, so FunctionN.invoke call // inside the inline function already has a (real) continuation value as the last argument. - val freeParameters = function.explicitParameters.let { it.take(startCapture) + it.drop(endCapture) } - val freeAsmParameters = asmMethod.argumentTypes.let { it.take(startCapture) + it.drop(endCapture) } + val freeParameters = function.explicitParameters.let { it.take(captureStart) + it.drop(captureEnd) } + val freeAsmParameters = asmMethod.argumentTypes.let { it.take(captureStart) + it.drop(captureEnd) } // The return type, on the other hand, should be the original type if this is a suspend lambda that returns // an unboxed inline class value so that the inliner will box it (FunctionN.invoke should return a boxed value). val unboxedReturnType = function.originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass()